summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
commit50b48aec6ddd451a6d1709c0942477b503457663 (patch)
treea9ece53ec06fd0a2819de7a2a6de997193566626 /src
downloadk3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz
k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip
Added abandoned KDE3 version of K3B
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src')
-rw-r--r--src/IDEAS45
-rw-r--r--src/Makefile.am86
-rw-r--r--src/eventsrc333
-rw-r--r--src/fastscale/Makefile.am14
-rw-r--r--src/fastscale/README2
-rw-r--r--src/fastscale/asm_scale.S810
-rw-r--r--src/fastscale/configure.in.in63
-rw-r--r--src/fastscale/scale.cpp1975
-rw-r--r--src/fastscale/scale.h34
-rw-r--r--src/icons/Makefile.am2
-rw-r--r--src/icons/actions/Makefile.am2
-rw-r--r--src/icons/actions/cr16-action-greenled.pngbin0 -> 536 bytes
-rw-r--r--src/icons/actions/cr16-action-redled.pngbin0 -> 493 bytes
-rw-r--r--src/icons/actions/cr16-action-yellowinfo.pngbin0 -> 589 bytes
-rw-r--r--src/icons/actions/cr16-action-yellowled.pngbin0 -> 498 bytes
-rw-r--r--src/icons/actions/hi16-action-audiocd.pngbin0 -> 957 bytes
-rw-r--r--src/icons/actions/hi16-action-burn_cdimage.pngbin0 -> 908 bytes
-rw-r--r--src/icons/actions/hi16-action-burn_dvdimage.pngbin0 -> 1011 bytes
-rw-r--r--src/icons/actions/hi16-action-cdburn.pngbin0 -> 916 bytes
-rw-r--r--src/icons/actions/hi16-action-cdcopy.pngbin0 -> 951 bytes
-rw-r--r--src/icons/actions/hi16-action-cddarip.pngbin0 -> 872 bytes
-rw-r--r--src/icons/actions/hi16-action-datacd.pngbin0 -> 941 bytes
-rw-r--r--src/icons/actions/hi16-action-datadvd.pngbin0 -> 925 bytes
-rw-r--r--src/icons/actions/hi16-action-dvdcopy.pngbin0 -> 1050 bytes
-rw-r--r--src/icons/actions/hi16-action-emovix.pngbin0 -> 978 bytes
-rw-r--r--src/icons/actions/hi16-action-erasecd.pngbin0 -> 928 bytes
-rw-r--r--src/icons/actions/hi16-action-formatdvd.pngbin0 -> 1009 bytes
-rw-r--r--src/icons/actions/hi16-action-mixedcd.pngbin0 -> 969 bytes
-rw-r--r--src/icons/actions/hi16-action-mp3cd.pngbin0 -> 836 bytes
-rw-r--r--src/icons/actions/hi16-action-musicbrainz.pngbin0 -> 1850 bytes
-rw-r--r--src/icons/actions/hi16-action-videocd.pngbin0 -> 1026 bytes
-rw-r--r--src/icons/actions/hi16-action-videodvd.pngbin0 -> 1044 bytes
-rw-r--r--src/icons/actions/hi22-action-audiocd.pngbin0 -> 1410 bytes
-rw-r--r--src/icons/actions/hi22-action-burn_cdimage.pngbin0 -> 1291 bytes
-rw-r--r--src/icons/actions/hi22-action-burn_dvdimage.pngbin0 -> 1410 bytes
-rw-r--r--src/icons/actions/hi22-action-cdburn.pngbin0 -> 1450 bytes
-rw-r--r--src/icons/actions/hi22-action-cdcopy.pngbin0 -> 1389 bytes
-rw-r--r--src/icons/actions/hi22-action-cddarip.pngbin0 -> 1397 bytes
-rw-r--r--src/icons/actions/hi22-action-datacd.pngbin0 -> 1410 bytes
-rw-r--r--src/icons/actions/hi22-action-datadvd.pngbin0 -> 1410 bytes
-rw-r--r--src/icons/actions/hi22-action-dvdcopy.pngbin0 -> 1465 bytes
-rw-r--r--src/icons/actions/hi22-action-emovix.pngbin0 -> 1511 bytes
-rw-r--r--src/icons/actions/hi22-action-erasecd.pngbin0 -> 1503 bytes
-rw-r--r--src/icons/actions/hi22-action-formatdvd.pngbin0 -> 1612 bytes
-rw-r--r--src/icons/actions/hi22-action-mixedcd.pngbin0 -> 1553 bytes
-rw-r--r--src/icons/actions/hi22-action-mp3cd.pngbin0 -> 1155 bytes
-rw-r--r--src/icons/actions/hi22-action-videocd.pngbin0 -> 1627 bytes
-rw-r--r--src/icons/actions/hi22-action-videodvd.pngbin0 -> 1641 bytes
-rw-r--r--src/icons/actions/hi32-action-audiocd.pngbin0 -> 2358 bytes
-rw-r--r--src/icons/actions/hi32-action-burn_cdimage.pngbin0 -> 2355 bytes
-rw-r--r--src/icons/actions/hi32-action-burn_dvdimage.pngbin0 -> 2543 bytes
-rw-r--r--src/icons/actions/hi32-action-cdburn.pngbin0 -> 2422 bytes
-rw-r--r--src/icons/actions/hi32-action-cdcopy.pngbin0 -> 2288 bytes
-rw-r--r--src/icons/actions/hi32-action-cddarip.pngbin0 -> 2420 bytes
-rw-r--r--src/icons/actions/hi32-action-datacd.pngbin0 -> 2218 bytes
-rw-r--r--src/icons/actions/hi32-action-datadvd.pngbin0 -> 2281 bytes
-rw-r--r--src/icons/actions/hi32-action-dvdcopy.pngbin0 -> 2658 bytes
-rw-r--r--src/icons/actions/hi32-action-emovix.pngbin0 -> 2522 bytes
-rw-r--r--src/icons/actions/hi32-action-erasecd.pngbin0 -> 2599 bytes
-rw-r--r--src/icons/actions/hi32-action-formatdvd.pngbin0 -> 2905 bytes
-rw-r--r--src/icons/actions/hi32-action-mixedcd.pngbin0 -> 2490 bytes
-rw-r--r--src/icons/actions/hi32-action-mp3cd.pngbin0 -> 2512 bytes
-rw-r--r--src/icons/actions/hi32-action-videocd.pngbin0 -> 2895 bytes
-rw-r--r--src/icons/actions/hi32-action-videodvd.pngbin0 -> 2945 bytes
-rw-r--r--src/icons/actions/hi48-action-audiocd.pngbin0 -> 4033 bytes
-rw-r--r--src/icons/actions/hi48-action-burn_cdimage.pngbin0 -> 4060 bytes
-rw-r--r--src/icons/actions/hi48-action-burn_dvdimage.pngbin0 -> 4462 bytes
-rw-r--r--src/icons/actions/hi48-action-cdburn.pngbin0 -> 4366 bytes
-rw-r--r--src/icons/actions/hi48-action-cdcopy.pngbin0 -> 3945 bytes
-rw-r--r--src/icons/actions/hi48-action-cddarip.pngbin0 -> 4131 bytes
-rw-r--r--src/icons/actions/hi48-action-datacd.pngbin0 -> 3581 bytes
-rw-r--r--src/icons/actions/hi48-action-datadvd.pngbin0 -> 3853 bytes
-rw-r--r--src/icons/actions/hi48-action-dvdcopy.pngbin0 -> 4782 bytes
-rw-r--r--src/icons/actions/hi48-action-emovix.pngbin0 -> 4602 bytes
-rw-r--r--src/icons/actions/hi48-action-erasecd.pngbin0 -> 4676 bytes
-rw-r--r--src/icons/actions/hi48-action-formatdvd.pngbin0 -> 5330 bytes
-rw-r--r--src/icons/actions/hi48-action-mixedcd.pngbin0 -> 4289 bytes
-rw-r--r--src/icons/actions/hi48-action-mp3cd.pngbin0 -> 4351 bytes
-rw-r--r--src/icons/actions/hi48-action-videocd.pngbin0 -> 5594 bytes
-rw-r--r--src/icons/actions/hi48-action-videodvd.pngbin0 -> 5649 bytes
-rw-r--r--src/icons/actions/hi64-action-musicbrainz.pngbin0 -> 4807 bytes
-rw-r--r--src/icons/actions/hisc-action-audiocd.svgzbin0 -> 3370 bytes
-rw-r--r--src/icons/actions/hisc-action-burn_cdimage.svgzbin0 -> 7665 bytes
-rw-r--r--src/icons/actions/hisc-action-burn_dvdimage.svgzbin0 -> 8596 bytes
-rw-r--r--src/icons/actions/hisc-action-cdburn.svgzbin0 -> 2771 bytes
-rw-r--r--src/icons/actions/hisc-action-cdcopy.svgzbin0 -> 3097 bytes
-rw-r--r--src/icons/actions/hisc-action-cddarip.svgzbin0 -> 9363 bytes
-rw-r--r--src/icons/actions/hisc-action-datacd.svgzbin0 -> 4433 bytes
-rw-r--r--src/icons/actions/hisc-action-datadvd.svgzbin0 -> 3160 bytes
-rw-r--r--src/icons/actions/hisc-action-dvdcopy.svgzbin0 -> 4200 bytes
-rw-r--r--src/icons/actions/hisc-action-emovix.svgzbin0 -> 55745 bytes
-rw-r--r--src/icons/actions/hisc-action-erasecd.svgzbin0 -> 8251 bytes
-rw-r--r--src/icons/actions/hisc-action-formatdvd.svgzbin0 -> 9158 bytes
-rw-r--r--src/icons/actions/hisc-action-mixedcd.svgzbin0 -> 6298 bytes
-rw-r--r--src/icons/actions/hisc-action-mp3cd.svgzbin0 -> 4455 bytes
-rw-r--r--src/icons/actions/hisc-action-videocd.svgzbin0 -> 8587 bytes
-rw-r--r--src/icons/actions/hisc-action-videodvd.svgzbin0 -> 9447 bytes
-rw-r--r--src/icons/hi128-app-k3b.pngbin0 -> 5295 bytes
-rw-r--r--src/icons/hi16-app-k3b.pngbin0 -> 731 bytes
-rw-r--r--src/icons/hi22-app-k3b.pngbin0 -> 1142 bytes
-rw-r--r--src/icons/hi32-app-k3b.pngbin0 -> 1376 bytes
-rw-r--r--src/icons/hi48-app-k3b.pngbin0 -> 2067 bytes
-rw-r--r--src/icons/hi64-app-k3b.pngbin0 -> 2891 bytes
-rw-r--r--src/k3b-cue.desktop14
-rw-r--r--src/k3b-iso.desktop13
-rw-r--r--src/k3b.cpp1630
-rw-r--r--src/k3b.desktop123
-rw-r--r--src/k3b.h330
-rw-r--r--src/k3bappdevicemanager.cpp304
-rw-r--r--src/k3bappdevicemanager.h119
-rw-r--r--src/k3bapplication.cpp451
-rw-r--r--src/k3bapplication.h156
-rw-r--r--src/k3baudioplayer.cpp663
-rw-r--r--src/k3baudioplayer.h208
-rw-r--r--src/k3baudioprojectinterface.cpp92
-rw-r--r--src/k3baudioprojectinterface.h63
-rw-r--r--src/k3bburnprogressdialog.cpp134
-rw-r--r--src/k3bburnprogressdialog.h55
-rw-r--r--src/k3bcontentsview.cpp86
-rw-r--r--src/k3bcontentsview.h49
-rw-r--r--src/k3bdatamodewidget.cpp106
-rw-r--r--src/k3bdatamodewidget.h46
-rw-r--r--src/k3bdataprojectinterface.cpp128
-rw-r--r--src/k3bdataprojectinterface.h105
-rw-r--r--src/k3bdebuggingoutputdialog.cpp162
-rw-r--r--src/k3bdebuggingoutputdialog.h46
-rw-r--r--src/k3bdebuggingoutputfile.cpp75
-rw-r--r--src/k3bdebuggingoutputfile.h39
-rw-r--r--src/k3bdiroperator.cpp159
-rw-r--r--src/k3bdiroperator.h82
-rw-r--r--src/k3bdirview.cpp367
-rw-r--r--src/k3bdirview.h100
-rw-r--r--src/k3bdiskinfoview.cpp500
-rw-r--r--src/k3bdiskinfoview.h56
-rw-r--r--src/k3bemptydiscwaiter.cpp761
-rw-r--r--src/k3bemptydiscwaiter.h139
-rw-r--r--src/k3bfiletreecombobox.cpp393
-rw-r--r--src/k3bfiletreecombobox.h72
-rw-r--r--src/k3bfiletreeview.cpp728
-rw-r--r--src/k3bfiletreeview.h199
-rw-r--r--src/k3bfileview.cpp183
-rw-r--r--src/k3bfileview.h74
-rw-r--r--src/k3bfirstrun.cpp84
-rw-r--r--src/k3bfirstrun.h34
-rw-r--r--src/k3bflatbutton.cpp203
-rw-r--r--src/k3bflatbutton.h77
-rw-r--r--src/k3binteractiondialog.cpp662
-rw-r--r--src/k3binteractiondialog.h279
-rw-r--r--src/k3binterface.cpp192
-rw-r--r--src/k3binterface.h102
-rw-r--r--src/k3bjobinterface.cpp190
-rw-r--r--src/k3bjobinterface.h82
-rw-r--r--src/k3bjobprogressdialog.cpp696
-rw-r--r--src/k3bjobprogressdialog.h173
-rw-r--r--src/k3bjobprogressosd.cpp303
-rw-r--r--src/k3bjobprogressosd.h88
-rw-r--r--src/k3blsofwrapper.cpp108
-rw-r--r--src/k3blsofwrapper.h60
-rw-r--r--src/k3blsofwrapperdialog.cpp127
-rw-r--r--src/k3blsofwrapperdialog.h53
-rw-r--r--src/k3bmediacache.cpp373
-rw-r--r--src/k3bmediacache.h148
-rw-r--r--src/k3bmediacontentsview.cpp166
-rw-r--r--src/k3bmediacontentsview.h116
-rw-r--r--src/k3bmediaselectioncombobox.cpp505
-rw-r--r--src/k3bmediaselectioncombobox.h136
-rw-r--r--src/k3bmediaselectiondialog.cpp127
-rw-r--r--src/k3bmediaselectiondialog.h87
-rw-r--r--src/k3bmedium.cpp463
-rw-r--r--src/k3bmedium.h134
-rw-r--r--src/k3bminibutton.cpp77
-rw-r--r--src/k3bminibutton.h51
-rw-r--r--src/k3bmixedprojectinterface.cpp46
-rw-r--r--src/k3bmixedprojectinterface.h47
-rw-r--r--src/k3bmusicbrainz.cpp103
-rw-r--r--src/k3bmusicbrainz.h54
-rw-r--r--src/k3bpassivepopup.cpp280
-rw-r--r--src/k3bpassivepopup.h76
-rw-r--r--src/k3bprojectinterface.cpp138
-rw-r--r--src/k3bprojectinterface.h91
-rw-r--r--src/k3bprojectmanager.cpp653
-rw-r--r--src/k3bprojectmanager.h89
-rw-r--r--src/k3bprojecttabwidget.cpp216
-rw-r--r--src/k3bprojecttabwidget.h78
-rw-r--r--src/k3bservicemenuinstaller.cpp119
-rw-r--r--src/k3bservicemenuinstaller.h55
-rw-r--r--src/k3bsidepanel.cpp108
-rw-r--r--src/k3bsidepanel.h49
-rw-r--r--src/k3bsplash.cpp129
-rw-r--r--src/k3bsplash.h48
-rw-r--r--src/k3bstatusbarmanager.cpp250
-rw-r--r--src/k3bstatusbarmanager.h61
-rw-r--r--src/k3bsystemproblemdialog.cpp690
-rw-r--r--src/k3bsystemproblemdialog.h101
-rw-r--r--src/k3btempdirselectionwidget.cpp277
-rw-r--r--src/k3btempdirselectionwidget.h100
-rw-r--r--src/k3bthemedheader.cpp129
-rw-r--r--src/k3bthemedheader.h55
-rw-r--r--src/k3bthemedlabel.cpp76
-rw-r--r--src/k3bthemedlabel.h42
-rw-r--r--src/k3bthememanager.cpp324
-rw-r--r--src/k3bthememanager.h146
-rw-r--r--src/k3btimeoutwidget.cpp149
-rw-r--r--src/k3btimeoutwidget.h59
-rw-r--r--src/k3btooltip.cpp195
-rw-r--r--src/k3btooltip.h81
-rw-r--r--src/k3btrm.cpp93
-rw-r--r--src/k3btrm.h60
-rw-r--r--src/k3bui.rc78
-rw-r--r--src/k3bwelcomewidget.cpp489
-rw-r--r--src/k3bwelcomewidget.h124
-rw-r--r--src/k3bwidgetshoweffect.cpp203
-rw-r--r--src/k3bwidgetshoweffect.h115
-rw-r--r--src/k3bwriterselectionwidget.cpp607
-rw-r--r--src/k3bwriterselectionwidget.h146
-rw-r--r--src/k3bwritingmodewidget.cpp247
-rw-r--r--src/k3bwritingmodewidget.h91
-rw-r--r--src/konqi/Makefile.am16
-rw-r--r--src/konqi/k3b_audiocd_rip.desktop49
-rw-r--r--src/konqi/k3b_cd_copy.desktop52
-rw-r--r--src/konqi/k3b_create_audio_cd.desktop62
-rw-r--r--src/konqi/k3b_create_data_cd.desktop63
-rw-r--r--src/konqi/k3b_create_data_dvd.desktop57
-rw-r--r--src/konqi/k3b_create_video_cd.desktop61
-rw-r--r--src/konqi/k3b_dvd_copy.desktop52
-rw-r--r--src/konqi/k3b_handle_empty_cd.desktop120
-rw-r--r--src/konqi/k3b_handle_empty_dvd.desktop110
-rw-r--r--src/konqi/k3b_videodvd_rip.desktop48
-rw-r--r--src/konqi/k3b_write_bin_image.desktop62
-rw-r--r--src/konqi/k3b_write_iso_image.desktop55
-rw-r--r--src/main.cpp152
-rw-r--r--src/mimetypes/Makefile.am3
-rw-r--r--src/mimetypes/x-k3b.desktop65
-rw-r--r--src/misc/Makefile.am14
-rw-r--r--src/misc/k3bblankingdialog.cpp343
-rw-r--r--src/misc/k3bblankingdialog.h86
-rw-r--r--src/misc/k3bcdcopydialog.cpp556
-rw-r--r--src/misc/k3bcdcopydialog.h96
-rw-r--r--src/misc/k3bcdimagewritingdialog.cpp1049
-rw-r--r--src/misc/k3bcdimagewritingdialog.h116
-rw-r--r--src/misc/k3bdvdcopydialog.cpp455
-rw-r--r--src/misc/k3bdvdcopydialog.h79
-rw-r--r--src/misc/k3bdvdformattingdialog.cpp185
-rw-r--r--src/misc/k3bdvdformattingdialog.h55
-rw-r--r--src/misc/k3bisoimagewritingdialog.cpp580
-rw-r--r--src/misc/k3bisoimagewritingdialog.h90
-rw-r--r--src/option/Makefile.am20
-rw-r--r--src/option/base_k3bcddboptiontab.ui560
-rw-r--r--src/option/base_k3bmiscoptiontab.ui284
-rw-r--r--src/option/base_k3bpluginoptiontab.ui90
-rw-r--r--src/option/base_k3bthemeoptiontab.ui208
-rw-r--r--src/option/k3bburningoptiontab.cpp198
-rw-r--r--src/option/k3bburningoptiontab.h61
-rw-r--r--src/option/k3bcddboptiontab.cpp338
-rw-r--r--src/option/k3bcddboptiontab.h50
-rw-r--r--src/option/k3bdeviceoptiontab.cpp94
-rw-r--r--src/option/k3bdeviceoptiontab.h47
-rw-r--r--src/option/k3bdevicewidget.cpp404
-rw-r--r--src/option/k3bdevicewidget.h78
-rw-r--r--src/option/k3bexternalbinoptiontab.cpp78
-rw-r--r--src/option/k3bexternalbinoptiontab.h50
-rw-r--r--src/option/k3bexternalbinwidget.cpp318
-rw-r--r--src/option/k3bexternalbinwidget.h103
-rw-r--r--src/option/k3bmiscoptiontab.cpp187
-rw-r--r--src/option/k3bmiscoptiontab.h43
-rw-r--r--src/option/k3bnotifyoptiontab.cpp61
-rw-r--r--src/option/k3bnotifyoptiontab.h43
-rw-r--r--src/option/k3boptiondialog.cpp258
-rw-r--r--src/option/k3boptiondialog.h91
-rw-r--r--src/option/k3bpluginoptiontab.cpp137
-rw-r--r--src/option/k3bpluginoptiontab.h43
-rw-r--r--src/option/k3bthemeoptiontab.cpp234
-rw-r--r--src/option/k3bthemeoptiontab.h47
-rw-r--r--src/pics/73lab/Makefile.am23
-rw-r--r--src/pics/73lab/dialog_left.pngbin0 -> 556 bytes
-rw-r--r--src/pics/73lab/dialog_right.pngbin0 -> 5881 bytes
-rw-r--r--src/pics/73lab/k3b.theme5
-rw-r--r--src/pics/73lab/media_audio.pngbin0 -> 7487 bytes
-rw-r--r--src/pics/73lab/media_data.pngbin0 -> 8374 bytes
-rw-r--r--src/pics/73lab/media_empty.pngbin0 -> 8001 bytes
-rw-r--r--src/pics/73lab/media_left.pngbin0 -> 556 bytes
-rw-r--r--src/pics/73lab/media_mixed.pngbin0 -> 8116 bytes
-rw-r--r--src/pics/73lab/media_none.pngbin0 -> 5881 bytes
-rw-r--r--src/pics/73lab/media_video.pngbin0 -> 7157 bytes
-rw-r--r--src/pics/73lab/probing.pngbin0 -> 32980 bytes
-rw-r--r--src/pics/73lab/progress_fail.pngbin0 -> 17515 bytes
-rw-r--r--src/pics/73lab/progress_right.pngbin0 -> 1723 bytes
-rw-r--r--src/pics/73lab/progress_success.pngbin0 -> 16094 bytes
-rw-r--r--src/pics/73lab/progress_working.pngbin0 -> 13102 bytes
-rw-r--r--src/pics/73lab/project_left.pngbin0 -> 9445 bytes
-rw-r--r--src/pics/73lab/project_right.pngbin0 -> 1723 bytes
-rw-r--r--src/pics/73lab/splash.pngbin0 -> 159246 bytes
-rw-r--r--src/pics/73lab/welcome_bg.pngbin0 -> 37538 bytes
-rw-r--r--src/pics/Makefile.am1
-rw-r--r--src/pics/RobsTheme/Makefile.am23
-rw-r--r--src/pics/RobsTheme/dialog_left.pngbin0 -> 250 bytes
-rw-r--r--src/pics/RobsTheme/dialog_right.pngbin0 -> 2845 bytes
-rw-r--r--src/pics/RobsTheme/k3b.theme5
-rw-r--r--src/pics/RobsTheme/media_audio.pngbin0 -> 7422 bytes
-rw-r--r--src/pics/RobsTheme/media_data.pngbin0 -> 9382 bytes
-rw-r--r--src/pics/RobsTheme/media_empty.pngbin0 -> 4240 bytes
-rw-r--r--src/pics/RobsTheme/media_left.pngbin0 -> 250 bytes
-rw-r--r--src/pics/RobsTheme/media_mixed.pngbin0 -> 8748 bytes
-rw-r--r--src/pics/RobsTheme/media_none.pngbin0 -> 2861 bytes
-rw-r--r--src/pics/RobsTheme/media_video.pngbin0 -> 4334 bytes
-rw-r--r--src/pics/RobsTheme/progress_fail.pngbin0 -> 7390 bytes
-rw-r--r--src/pics/RobsTheme/progress_right.pngbin0 -> 2438 bytes
-rw-r--r--src/pics/RobsTheme/progress_success.pngbin0 -> 10252 bytes
-rw-r--r--src/pics/RobsTheme/progress_working.pngbin0 -> 6998 bytes
-rw-r--r--src/pics/RobsTheme/project_left.pngbin0 -> 8067 bytes
-rw-r--r--src/pics/RobsTheme/project_right.pngbin0 -> 2376 bytes
-rw-r--r--src/pics/RobsTheme/splash.pngbin0 -> 144339 bytes
-rw-r--r--src/pics/RobsTheme/welcome_bg.pngbin0 -> 75487 bytes
-rw-r--r--src/pics/crystal/Makefile.am24
-rw-r--r--src/pics/crystal/dialog_left.pngbin0 -> 1609 bytes
-rw-r--r--src/pics/crystal/dialog_right.pngbin0 -> 7376 bytes
-rw-r--r--src/pics/crystal/k3b.theme5
-rw-r--r--src/pics/crystal/media_audio.pngbin0 -> 5068 bytes
-rw-r--r--src/pics/crystal/media_data.pngbin0 -> 6870 bytes
-rw-r--r--src/pics/crystal/media_empty.pngbin0 -> 7545 bytes
-rw-r--r--src/pics/crystal/media_left.pngbin0 -> 1609 bytes
-rw-r--r--src/pics/crystal/media_mixed.pngbin0 -> 5474 bytes
-rw-r--r--src/pics/crystal/media_none.pngbin0 -> 7376 bytes
-rw-r--r--src/pics/crystal/media_video.pngbin0 -> 6794 bytes
-rw-r--r--src/pics/crystal/probing.pngbin0 -> 31970 bytes
-rw-r--r--src/pics/crystal/progress_fail.pngbin0 -> 5714 bytes
-rw-r--r--src/pics/crystal/progress_right.pngbin0 -> 1928 bytes
-rw-r--r--src/pics/crystal/progress_success.pngbin0 -> 6590 bytes
-rw-r--r--src/pics/crystal/progress_working.pngbin0 -> 7091 bytes
-rw-r--r--src/pics/crystal/project_left.pngbin0 -> 4303 bytes
-rw-r--r--src/pics/crystal/project_right.pngbin0 -> 1928 bytes
-rw-r--r--src/pics/crystal/splash.pngbin0 -> 150400 bytes
-rw-r--r--src/pics/crystal/welcome_bg.pngbin0 -> 33102 bytes
-rw-r--r--src/pics/quant/Makefile.am23
-rw-r--r--src/pics/quant/dialog_left.pngbin0 -> 3429 bytes
-rw-r--r--src/pics/quant/dialog_right.pngbin0 -> 4364 bytes
-rw-r--r--src/pics/quant/k3b.theme6
-rw-r--r--src/pics/quant/media_audio.pngbin0 -> 5120 bytes
-rw-r--r--src/pics/quant/media_data.pngbin0 -> 4352 bytes
-rw-r--r--src/pics/quant/media_empty.pngbin0 -> 1579 bytes
-rw-r--r--src/pics/quant/media_left.pngbin0 -> 3475 bytes
-rw-r--r--src/pics/quant/media_mixed.pngbin0 -> 3429 bytes
-rw-r--r--src/pics/quant/media_none.pngbin0 -> 1835 bytes
-rw-r--r--src/pics/quant/media_video.pngbin0 -> 10157 bytes
-rw-r--r--src/pics/quant/progress_fail.pngbin0 -> 14819 bytes
-rw-r--r--src/pics/quant/progress_right.pngbin0 -> 5548 bytes
-rw-r--r--src/pics/quant/progress_success.pngbin0 -> 12044 bytes
-rw-r--r--src/pics/quant/progress_working.pngbin0 -> 11647 bytes
-rw-r--r--src/pics/quant/project_left.pngbin0 -> 9454 bytes
-rw-r--r--src/pics/quant/project_right.pngbin0 -> 5628 bytes
-rw-r--r--src/pics/quant/splash.pngbin0 -> 216696 bytes
-rw-r--r--src/pics/quant/welcome_bg.pngbin0 -> 591641 bytes
-rw-r--r--src/projects/Makefile.am86
-rw-r--r--src/projects/base_k3badvanceddataimagesettings.ui193
-rw-r--r--src/projects/base_k3baudiocdtextallfieldswidget.ui275
-rw-r--r--src/projects/base_k3baudiocdtextwidget.ui222
-rw-r--r--src/projects/base_k3baudiotrackwidget.ui336
-rw-r--r--src/projects/base_k3bbootimageview.ui394
-rw-r--r--src/projects/base_k3bdataimagesettings.ui274
-rw-r--r--src/projects/base_k3bdatavolumedescwidget.ui370
-rw-r--r--src/projects/base_k3bmovixoptionswidget.ui337
-rw-r--r--src/projects/k3baudioburndialog.cpp341
-rw-r--r--src/projects/k3baudioburndialog.h81
-rw-r--r--src/projects/k3baudiocdtextwidget.cpp236
-rw-r--r--src/projects/k3baudiocdtextwidget.h55
-rw-r--r--src/projects/k3baudiodatasourceeditwidget.cpp166
-rw-r--r--src/projects/k3baudiodatasourceeditwidget.h70
-rw-r--r--src/projects/k3baudiodatasourceviewitem.cpp111
-rw-r--r--src/projects/k3baudiodatasourceviewitem.h54
-rw-r--r--src/projects/k3baudioeditorwidget.cpp877
-rw-r--r--src/projects/k3baudioeditorwidget.h220
-rw-r--r--src/projects/k3baudiotrackaddingdialog.cpp302
-rw-r--r--src/projects/k3baudiotrackaddingdialog.h106
-rw-r--r--src/projects/k3baudiotrackdialog.cpp113
-rw-r--r--src/projects/k3baudiotrackdialog.h57
-rw-r--r--src/projects/k3baudiotrackplayer.cpp365
-rw-r--r--src/projects/k3baudiotrackplayer.h87
-rw-r--r--src/projects/k3baudiotracksplitdialog.cpp232
-rw-r--r--src/projects/k3baudiotracksplitdialog.h71
-rw-r--r--src/projects/k3baudiotracktrmlookupdialog.cpp131
-rw-r--r--src/projects/k3baudiotracktrmlookupdialog.h54
-rw-r--r--src/projects/k3baudiotrackview.cpp1005
-rw-r--r--src/projects/k3baudiotrackview.h142
-rw-r--r--src/projects/k3baudiotrackviewitem.cpp229
-rw-r--r--src/projects/k3baudiotrackviewitem.h66
-rw-r--r--src/projects/k3baudiotrackwidget.cpp162
-rw-r--r--src/projects/k3baudiotrackwidget.h48
-rw-r--r--src/projects/k3baudioview.cpp136
-rw-r--r--src/projects/k3baudioview.h61
-rw-r--r--src/projects/k3bbootimagedialog.cpp45
-rw-r--r--src/projects/k3bbootimagedialog.h44
-rw-r--r--src/projects/k3bbootimageview.cpp273
-rw-r--r--src/projects/k3bbootimageview.h57
-rw-r--r--src/projects/k3bdataadvancedimagesettingswidget.cpp352
-rw-r--r--src/projects/k3bdataadvancedimagesettingswidget.h69
-rw-r--r--src/projects/k3bdataburndialog.cpp289
-rw-r--r--src/projects/k3bdataburndialog.h75
-rw-r--r--src/projects/k3bdatadirtreeview.cpp506
-rw-r--r--src/projects/k3bdatadirtreeview.h115
-rw-r--r--src/projects/k3bdatafileview.cpp483
-rw-r--r--src/projects/k3bdatafileview.h115
-rw-r--r--src/projects/k3bdataimagesettingswidget.cpp400
-rw-r--r--src/projects/k3bdataimagesettingswidget.h54
-rw-r--r--src/projects/k3bdatamultisessioncombobox.cpp177
-rw-r--r--src/projects/k3bdatamultisessioncombobox.h52
-rw-r--r--src/projects/k3bdatapropertiesdialog.cpp248
-rw-r--r--src/projects/k3bdatapropertiesdialog.h61
-rw-r--r--src/projects/k3bdatasessionimportdialog.cpp137
-rw-r--r--src/projects/k3bdatasessionimportdialog.h64
-rw-r--r--src/projects/k3bdataurladdingdialog.cpp826
-rw-r--r--src/projects/k3bdataurladdingdialog.h110
-rw-r--r--src/projects/k3bdataview.cpp196
-rw-r--r--src/projects/k3bdataview.h78
-rw-r--r--src/projects/k3bdataviewitem.cpp340
-rw-r--r--src/projects/k3bdataviewitem.h135
-rw-r--r--src/projects/k3bdatavolumedescwidget.cpp93
-rw-r--r--src/projects/k3bdatavolumedescwidget.h40
-rw-r--r--src/projects/k3bdvdburndialog.cpp300
-rw-r--r--src/projects/k3bdvdburndialog.h69
-rw-r--r--src/projects/k3bdvdview.cpp48
-rw-r--r--src/projects/k3bdvdview.h40
-rw-r--r--src/projects/k3bencodingconverter.cpp130
-rw-r--r--src/projects/k3bencodingconverter.h59
-rw-r--r--src/projects/k3bfillstatusdisplay.cpp759
-rw-r--r--src/projects/k3bfillstatusdisplay.h117
-rw-r--r--src/projects/k3bmixedburndialog.cpp353
-rw-r--r--src/projects/k3bmixedburndialog.h78
-rw-r--r--src/projects/k3bmixeddirtreeview.cpp103
-rw-r--r--src/projects/k3bmixeddirtreeview.h56
-rw-r--r--src/projects/k3bmixedview.cpp155
-rw-r--r--src/projects/k3bmixedview.h66
-rw-r--r--src/projects/k3bmovixburndialog.cpp265
-rw-r--r--src/projects/k3bmovixburndialog.h64
-rw-r--r--src/projects/k3bmovixdvdburndialog.cpp219
-rw-r--r--src/projects/k3bmovixdvdburndialog.h57
-rw-r--r--src/projects/k3bmovixdvdview.cpp48
-rw-r--r--src/projects/k3bmovixdvdview.h40
-rw-r--r--src/projects/k3bmovixlistview.cpp327
-rw-r--r--src/projects/k3bmovixlistview.h100
-rw-r--r--src/projects/k3bmovixoptionswidget.cpp243
-rw-r--r--src/projects/k3bmovixoptionswidget.h50
-rw-r--r--src/projects/k3bmovixview.cpp192
-rw-r--r--src/projects/k3bmovixview.h65
-rw-r--r--src/projects/k3bmusicbrainzjob.cpp287
-rw-r--r--src/projects/k3bmusicbrainzjob.h89
-rw-r--r--src/projects/k3bprojectburndialog.cpp413
-rw-r--r--src/projects/k3bprojectburndialog.h191
-rw-r--r--src/projects/k3bprojectplugindialog.cpp68
-rw-r--r--src/projects/k3bprojectplugindialog.h46
-rw-r--r--src/projects/k3bvcdburndialog.cpp1088
-rw-r--r--src/projects/k3bvcdburndialog.h142
-rw-r--r--src/projects/k3bvcdlistview.cpp271
-rw-r--r--src/projects/k3bvcdlistview.h90
-rw-r--r--src/projects/k3bvcdlistviewitem.cpp129
-rw-r--r--src/projects/k3bvcdlistviewitem.h50
-rw-r--r--src/projects/k3bvcdtrackdialog.cpp802
-rw-r--r--src/projects/k3bvcdtrackdialog.h123
-rw-r--r--src/projects/k3bvcdview.cpp74
-rw-r--r--src/projects/k3bvcdview.h55
-rw-r--r--src/projects/k3bvideodvdburndialog.cpp198
-rw-r--r--src/projects/k3bvideodvdburndialog.h55
-rw-r--r--src/projects/k3bvideodvdview.cpp84
-rw-r--r--src/projects/k3bvideodvdview.h48
-rw-r--r--src/projects/k3bview.cpp176
-rw-r--r--src/projects/k3bview.h112
-rw-r--r--src/projects/kostore/Makefile.am11
-rw-r--r--src/projects/kostore/README.k3b2
-rw-r--r--src/projects/kostore/SPEC122
-rw-r--r--src/projects/kostore/koStore.cc629
-rw-r--r--src/projects/kostore/koStore.h384
-rw-r--r--src/projects/kostore/koStoreBase.cc29
-rw-r--r--src/projects/kostore/koStoreBase.h51
-rw-r--r--src/projects/kostore/koStoreDevice.h88
-rw-r--r--src/projects/kostore/koZipStore.cc237
-rw-r--r--src/projects/kostore/koZipStore.h61
-rw-r--r--src/rip/Makefile.am32
-rw-r--r--src/rip/base_k3baudiorippingoptionwidget.ui282
-rw-r--r--src/rip/base_k3bcddbpatternwidget.ui180
-rw-r--r--src/rip/k3baudiocdlistview.cpp66
-rw-r--r--src/rip/k3baudiocdlistview.h45
-rw-r--r--src/rip/k3baudiocdview.cpp631
-rw-r--r--src/rip/k3baudiocdview.h107
-rw-r--r--src/rip/k3baudioconvertingoptionwidget.cpp266
-rw-r--r--src/rip/k3baudioconvertingoptionwidget.h74
-rw-r--r--src/rip/k3baudioprojectconvertingdialog.cpp371
-rw-r--r--src/rip/k3baudioprojectconvertingdialog.h78
-rw-r--r--src/rip/k3baudioprojectconvertingthread.cpp459
-rw-r--r--src/rip/k3baudioprojectconvertingthread.h101
-rw-r--r--src/rip/k3baudioripjob.cpp77
-rw-r--r--src/rip/k3baudioripjob.h71
-rw-r--r--src/rip/k3baudiorippingdialog.cpp470
-rw-r--r--src/rip/k3baudiorippingdialog.h92
-rw-r--r--src/rip/k3baudioripthread.cpp602
-rw-r--r--src/rip/k3baudioripthread.h117
-rw-r--r--src/rip/k3bcddbpatternwidget.cpp175
-rw-r--r--src/rip/k3bcddbpatternwidget.h51
-rw-r--r--src/rip/k3bcuefilewriter.cpp91
-rw-r--r--src/rip/k3bcuefilewriter.h54
-rw-r--r--src/rip/k3bpatternparser.cpp305
-rw-r--r--src/rip/k3bpatternparser.h52
-rw-r--r--src/rip/k3bvideocdinfo.cpp247
-rw-r--r--src/rip/k3bvideocdinfo.h107
-rw-r--r--src/rip/k3bvideocdrip.cpp355
-rw-r--r--src/rip/k3bvideocdrip.h74
-rw-r--r--src/rip/k3bvideocdrippingdialog.cpp260
-rw-r--r--src/rip/k3bvideocdrippingdialog.h73
-rw-r--r--src/rip/k3bvideocdrippingoptions.h74
-rw-r--r--src/rip/k3bvideocdview.cpp509
-rw-r--r--src/rip/k3bvideocdview.h105
-rw-r--r--src/rip/videodvd/Makefile.am16
-rw-r--r--src/rip/videodvd/base_k3bvideodvdrippingwidget.ui721
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingdialog.cpp634
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingdialog.h82
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingjob.cpp385
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingjob.h106
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingpreview.cpp135
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingpreview.h66
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingtitlelistview.cpp410
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingtitlelistview.h58
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingview.cpp256
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingview.h66
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingwidget.cpp375
-rw-r--r--src/rip/videodvd/k3bvideodvdrippingwidget.h67
-rw-r--r--src/sounds/Makefile.am5
-rw-r--r--src/sounds/k3b_error1.wavbin0 -> 15669 bytes
-rw-r--r--src/sounds/k3b_success1.wavbin0 -> 46657 bytes
-rw-r--r--src/sounds/k3b_wait_media1.wavbin0 -> 1940 bytes
-rw-r--r--src/sourceheader15
-rw-r--r--src/tips47
529 files changed, 68414 insertions, 0 deletions
diff --git a/src/IDEAS b/src/IDEAS
new file mode 100644
index 0000000..f8a2f9c
--- /dev/null
+++ b/src/IDEAS
@@ -0,0 +1,45 @@
+wie in KOffice K3bDoc von KParts::ReadWritePart ableiten
+in KOffice ist der view von KParts::PartBase abgeleitet. Warum das?
+alle actions, die das doc ndern, auch ins doc packen.
+alle actions, die nur fr die ansicht da sind (zb. properties dialog) in den view
+
+da wir verschiedene projekt-typen fr den gleichen mimetype haben macht ein ReadWritePartWrapper,
+der aufgrund des doctypes entscheidet, welches K3bDoc bentigt wird, mehr Sinn. Das hiee,
+dass es einen K3bPart gibt, der alle Projekte beinhaltet. Die einzelnen Projekte knnten allerdings auch wieder
+dynamisch hinzugeladen werden, so dass immer nur das gerade bentigte K3bDoc im Speicher ist.
+Der Wrapper muss dann nur den externalbin- und den devicemanager initialisieren und den kostore ffnen. Dann alle
+K3bDocFactories (wenn ein K3bDoc als eine Art plugin dynamisch hinzugeladen werden soll) fragen, ob sie
+den projekttyp untersttzen und wenn ja, eine instanz erzeugen und das dokument laden.
+Wie sieht es dann mit dem erstellen eines neuen dokumentes aus? Ev. Knnte der Wrapper hier alle Factories nach
+dem projecttyp fragen und fr jeden eine Action erstellen.
+K3b selber benutzt dann nicht den Wrapper, sondern macht alles selber. Das hiee redundanten Code in K3b und dem
+Wrapper.
+
+
+Audiodoc:
+ tracks und files.
+ ein track kann mehrere files enthalten
+ ein file kann vorne und hinten abgeschnitten werden
+ tracks knnen zusammengefhrt werden (resultiert in einem track mit den files aus den beiden quelltracks)
+ es gibt track- und filefilter; trackfilter sind das gewohnte und sollten meist benutzt werden, filefilter
+ filtern nur innerhalb eines tracks (Bsp: normalising nur ber alle files in einem track, wohingegen
+ normalising als trackfilter ber alle tracks normalisiert)
+ Das normale verhalten ist wie jetzt: Anlegen eines Tracks mit einem File. Das sollte fr die meisten
+ Anwender reichen. Wenn ctrl oder sowas gehalten wird kann man files zu einem track hinzufgen
+ (die gui knnte hier beim drcken von ctrl alle files als kindelemente der tracks anzeigen, auch bei
+ solchen tracks, die nur ein file enthalten. So wrde deutlich, dass ein file zu einem track hinzugefgt
+ werden kann.)
+
+K3bFileSystem:
+ K3bFsItem
+ -> K3bFsFile
+ -> K3bFsDirectory
+ FileSystem bietet virtuelle Funktionen newFile( filename ) und newDirectory( name ), mit welchen neue
+ Elemente von den addUrl Funktionen angelegt werden. Jedes Item hat eine size methode, welche die Gre
+ der Datei angibt. Zustzlich gibt es eine methode, welche die Gesamtgre aller Kinder und Enkel angibt
+ (nur sinnvoll fr K3bFsDirectory)
+ K3bFileSystem hat zustzlich ein caching-system, welches inode-basierte Grenberechung erlaubt.
+ K3bFsItem hat methoden wie isDir() und einen void Zeiger fr zustzliche Daten, wenn man nicht ableiten
+ mchte.
+ Von K3bFileSystem knnte man K3bIso9660FileSystem und K3bUdfFileSystem ableiten, welche zustzliche Daten
+ enthalten. \ No newline at end of file
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..be55a51
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,86 @@
+bin_PROGRAMS = k3b
+
+k3b_SOURCES = k3bwelcomewidget.cpp k3bapplication.cpp k3bdiroperator.cpp \
+ k3bfiletreeview.cpp \
+ k3bprojecttabwidget.cpp k3bsplash.cpp \
+ k3bfileview.cpp k3bdirview.cpp k3b.cpp main.cpp \
+ k3bstatusbarmanager.cpp k3bfiletreecombobox.cpp \
+ k3binterface.cpp k3binterface.skel \
+ k3bjobinterface.cpp k3bjobinterface.skel \
+ k3bprojectinterface.cpp k3bprojectinterface.skel \
+ k3bdataprojectinterface.cpp k3bdataprojectinterface.skel \
+ k3bsystemproblemdialog.cpp k3bmediacontentsview.cpp \
+ k3bsidepanel.cpp k3bcontentsview.cpp \
+ k3bjobprogressdialog.cpp k3bburnprogressdialog.cpp k3btempdirselectionwidget.cpp \
+ k3bdatamodewidget.cpp k3bwritingmodewidget.cpp k3bwriterselectionwidget.cpp \
+ k3binteractiondialog.cpp k3bthememanager.cpp \
+ k3bprojectmanager.cpp k3btrm.cpp k3bmusicbrainz.cpp \
+ k3baudioprojectinterface.cpp k3bmixedprojectinterface.cpp \
+ k3baudioprojectinterface.skel k3bmixedprojectinterface.skel k3bflatbutton.cpp \
+ k3bemptydiscwaiter.cpp k3bjobprogressosd.cpp \
+ k3bdebuggingoutputdialog.cpp k3bdebuggingoutputfile.cpp k3bappdevicemanager.cpp \
+ k3bmediacache.cpp k3bmedium.cpp k3bmediaselectioncombobox.cpp k3btooltip.cpp \
+ k3bwidgetshoweffect.cpp k3bmediaselectiondialog.cpp k3bdiskinfoview.cpp \
+ k3bpassivepopup.cpp k3btimeoutwidget.cpp k3bminibutton.cpp \
+ k3bthemedheader.cpp k3bthemedlabel.cpp k3blsofwrapper.cpp \
+ k3blsofwrapperdialog.cpp k3bservicemenuinstaller.cpp k3bfirstrun.cpp
+
+k3b_LDADD = ./option/liboption.la ./rip/librip.la \
+ ./projects/libprojects.la ../libk3bdevice/libk3bdevice.la \
+ ../libk3b/libk3b.la ./misc/libmisc.la ./fastscale/libfastscale.la \
+ -lkio -lkparts $(CAM_LIB) $(MUSICBRAINZ_LIBS)
+
+SUBDIRS = option misc rip projects fastscale pics icons konqi mimetypes sounds
+
+xdg_apps_DATA = k3b.desktop
+
+silent_DATA = k3b-iso.desktop k3b-cue.desktop
+silentdir = $(kde_appsdir)/.hidden/
+
+###################
+# this 10 paths are KDE specific. Use them:
+# kde_htmldir Where your docs should go to. (contains lang subdirs)
+# kde_appsdir Where your application file (.kdelnk) should go to.
+# kde_icondir Where your icon should go to.
+# kde_minidir Where your mini icon should go to.
+# kde_datadir Where you install application data. (Use a subdir)
+# kde_locale Where translation files should go to.(contains lang subdirs)
+# kde_cgidir Where cgi-bin executables should go to.
+# kde_confdir Where config files should go to.
+# kde_mimedir Where mimetypes should go to.
+# kde_toolbardir Where general toolbar icons should go to.
+# kde_wallpaperdir Where general wallpapers should go to.
+
+# set the include path for X, qt and KDE
+AM_CPPFLAGS = -I$(srcdir)/../libk3b/tools \
+ -I$(srcdir)/../libk3b/core \
+ -I$(srcdir)/../libk3b/cddb \
+ -I$(srcdir)/../libk3b/videodvd \
+ -I$(srcdir)/../libk3b/jobs \
+ -I$(srcdir)/../libk3bdevice \
+ -I$(srcdir)/../libk3b/projects \
+ -I$(srcdir)/../libk3b/projects/datacd \
+ -I$(srcdir)/../libk3b/projects/datadvd \
+ -I$(srcdir)/../libk3b/projects/audiocd \
+ -I$(srcdir)/../libk3b/projects/videocd \
+ -I$(srcdir)/../libk3b/projects/mixedcd \
+ -I$(srcdir)/../libk3b/projects/movixcd \
+ -I$(srcdir)/../libk3b/projects/videodvd \
+ -I$(srcdir)/../libk3b/projects/movixdvd \
+ -I$(srcdir)/../libk3b/plugin \
+ -I$(srcdir)/projects \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+# the library search path.
+k3b_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+rcdir = $(kde_datadir)/k3b
+rc_DATA = k3bui.rc eventsrc tips
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.rc -o -name \*.ui` `find ../plugins -name \*.rc -o -name \*.ui`> rc.cpp
+ $(PREPARETIPS) > tips.cpp
+ $(XGETTEXT) `find . -name \*.cpp -o -name \*.h` `find ../plugins -name \*.cpp -o -name \*.h` -o $(podir)/k3b.pot
+ rm -f tips.cpp
diff --git a/src/eventsrc b/src/eventsrc
new file mode 100644
index 0000000..a577acb
--- /dev/null
+++ b/src/eventsrc
@@ -0,0 +1,333 @@
+[!Global!]
+IconName=k3b
+Comment=K3b
+Comment[ar]= K3b
+Comment[bn]=কে-থ্রি-বি
+Comment[hi]=के3बी
+
+[SuccessfullyFinished]
+Name=Process successful
+Name[af]=Proses suksesvol
+Name[ar]= تمت المعالجة بنجاح
+Name[bg]=Процесът е успешен
+Name[bn]=প্রসেস সফল
+Name[bs]=Proces je uspio
+Name[ca]=Procés correcte
+Name[cs]=Proces úspěšný
+Name[da]=Processen lykkedes
+Name[de]=Vorgang erfolgreich
+Name[el]=Διεργασία επιτυχής
+Name[eo]=Tasko sukcesa
+Name[es]=Éxito de proceso
+Name[et]=Tegevus oli edukas
+Name[fa]=فرآیند موفق
+Name[fi]=Suoritettu
+Name[fr]=Processus réussi
+Name[ga]=D'éirigh leis an bpróiseas
+Name[gl]=Proceso exitoso
+Name[he]=תהליך מוצלח
+Name[hi]=प्रक्रिया सफल
+Name[hu]=A művelet sikeresen befejeződött
+Name[is]=Velheppnað ferli
+Name[it]=Processo riuscito
+Name[ja]=プロセス成功
+Name[ka]=პროცესი წარმატებულია
+Name[km]=ដំណើរការ​បាន​ជោគជ័យ
+Name[lt]=Procesas pavyko
+Name[mk]=Процесот е успешен
+Name[ms]= Proses berjaya
+Name[nb]=Vellykket prosess
+Name[nds]=Vörgang is glückt
+Name[ne]=प्रक्रिया सफल भयो
+Name[nl]=Proces was succesvol
+Name[nn]=Vellykka prosess
+Name[pa]=ਕਾਰਵਾਈ ਸਫ਼ਲ ਹੋਈ
+Name[pl]=Proces zakończony pomyślnie
+Name[pt]=Processo com sucesso
+Name[pt_BR]=Processo bem-sucedido
+Name[ru]=Успешно завершено
+Name[sk]=Proces úspešný
+Name[sl]=Proces uspešen
+Name[sr]=Обрада је успешна
+Name[sr@Latn]=Obrada je uspešna
+Name[sv]=Processen lyckades
+Name[ta]=வெற்றிகரமான தொகுப்பு
+Name[tg]=Бомуваффақият ба анҷом расид
+Name[tr]=İşlem başarılı
+Name[uk]=Процес успішний
+Name[uz]=Muvaffaqiyatli jarayon
+Name[uz@cyrillic]=Муваффақиятли жараён
+Name[zh_CN]=处理成功
+Name[zh_TW]=處理成功
+Comment=Process successfully finished
+Comment[af]=Proses het suksesvol klaar gemaak
+Comment[ar]=نهاية المعالجة بنجاح
+Comment[bg]=Процесът завърши успешно
+Comment[bn]=প্রসেস সফলভাবে শেষ হল
+Comment[bs]=Proces je uspješno završen
+Comment[ca]=Procés finalitzat amb èxit
+Comment[cs]=Proces úspěšně dokončen
+Comment[da]=Processen afsluttedes korrekt
+Comment[de]=Vorgang erfolgreich abgeschlossen
+Comment[el]=Η διεργασία ολοκληρώθηκε επιτυχώς
+Comment[eo]=Tasko sukcese finis
+Comment[es]=Proceso terminado con éxito
+Comment[et]=Tegevus lõppes edukalt
+Comment[fa]=فرآیند با موفقیت تمام شد
+Comment[fi]=Työ on suoritettu
+Comment[fr]=Processus terminé avec succès
+Comment[gl]=O proceso terminou con éxito
+Comment[he]=התהליך הסתיים בהצלחה
+Comment[hi]=प्रक्रिया सफलतापूर्वक पूर्ण
+Comment[hu]=A művelet sikeresen befejeződött
+Comment[is]=Ferli lauk með góðum árangri
+Comment[it]=Processo riuscito e terminato
+Comment[ja]=プロセス完了
+Comment[ka]=პროცესი წარმატებით დასრულდა
+Comment[km]=បាន​បញ្ចប់​ដំណើរការ​ដោយ​ជោគជ័យ
+Comment[lt]=Procesas sėkmingai baigtas
+Comment[mk]=Процесот заврши успешно
+Comment[ms]= Proses selesai dengan jayanya
+Comment[nb]=Prosessen ble fullført vellykket
+Comment[nds]=Vörgang afslaten
+Comment[ne]=प्रक्रिया सफलतापूर्वक समाप्त भयो
+Comment[nl]=Proces met succes voltooid
+Comment[nn]=Prosessen er fullført
+Comment[pa]=ਕਾਰਵਾਈ ਸਫ਼ਲਤਾਪੂਰਕ ਪੂਰੀ ਕੀਤੀ ਗਈ
+Comment[pl]=Proces zakończył się pomyślnie
+Comment[pt]=O processo terminou com sucesso
+Comment[pt_BR]=Processo finalizado com sucesso
+Comment[ru]=Процесс завершён успешно
+Comment[sk]=Proces úspešne ukončený
+Comment[sl]=Proces je uspešno končan
+Comment[sr]=Обрада је успешно завршена
+Comment[sr@Latn]=Obrada je uspešno završena
+Comment[sv]=Processen avslutades med lyckat resultat
+Comment[ta]=வெற்றிகரமாக தொகுப்பு முடிந்தது
+Comment[tg]=Амалиёт бомуваффақият ба анҷом расид
+Comment[tr]=İşlem başarıyla sonuçlandı
+Comment[uk]=Процес успішно завершився
+Comment[uz]=Jarayon muvaffaqiyatli tugadi
+Comment[uz@cyrillic]=Жараён муваффақиятли тугади
+Comment[zh_CN]=处理成功完成
+Comment[zh_TW]=成功完成處理
+default_sound=k3b_success1.wav
+default_presentation=1
+# None = 0, Sound = 1, Messagebox = 2, Logfile = 4, Stderr = 8, PassivePopup = 16, Execute = 32
+
+[FinishedWithError]
+Name=Process error
+Name[af]=Verwerking fout
+Name[ar]= خطأ خلال المعالجة
+Name[bg]=Грешка при обработка
+Name[bn]=প্রসেস ত্রুটি
+Name[bs]=Greška u procesu
+Name[ca]=Procés amb error
+Name[cs]=Chyba procesu
+Name[da]=Procesfejl
+Name[de]=Vorgang nicht erfolgreich
+Name[el]=Σφάλμα διεργασίας
+Name[eo]=Taska eraro
+Name[es]=Error de proceso
+Name[et]=Tegevuse viga
+Name[fa]=خطای فرآیند
+Name[fi]=Virhe
+Name[fr]=Erreur du processus
+Name[gl]=Erro no proceso
+Name[he]=שגיאת תהליך
+Name[hi]=प्रक्रिया त्रुटि
+Name[hu]=A művelet során hiba történt
+Name[is]=Villa í ferli
+Name[it]=Errore di Processo
+Name[ja]=プロセスエラー
+Name[ka]=პროცესის შეცდომა
+Name[km]=ដំណើរការ​មាន​កំហុស
+Name[lt]=Proceso klaida
+Name[mk]=Грешка во процесот
+Name[ms]=Ralat proses
+Name[nb]=Prosessfeil
+Name[nds]=Perzessfehler
+Name[ne]=प्रक्रिया त्रुटि
+Name[nl]=Procesfout
+Name[nn]=Prosessfeil
+Name[pa]=ਕਾਰਜ ਗਲਤੀ
+Name[pl]=Błąd procesu
+Name[pt]=Erro no processo
+Name[pt_BR]=Erro no processo
+Name[ru]=Ошибка
+Name[sk]=Chyba procesu
+Name[sl]=Napaka procesa
+Name[sr]=Грешка у обради
+Name[sr@Latn]=Greška u obradi
+Name[sv]=Processfel
+Name[ta]=தொகுப்புப் பிழை
+Name[tg]=Хатогӣ
+Name[tr]=İşlemde hata var
+Name[uk]=Помилка процесу
+Name[uz]=Xatoli jarayon
+Name[uz@cyrillic]=Хатоли жараён
+Name[zh_CN]=处理错误
+Name[zh_TW]=處理發生錯誤
+Comment=Process finished with errors
+Comment[af]=Die proses het met foute klaar gemaak
+Comment[ar]= انتهت المعالجة على خطأ
+Comment[bg]=Процесът завърши с грешки
+Comment[bn]=প্রসেস ত্রুটিপূর্ণভাবে শেষ হল
+Comment[bs]=Proces je završen sa greškama
+Comment[ca]=Procés finalitzat amb errors
+Comment[cs]=Proces ukončen s chybami
+Comment[da]=Processen afsluttede med fejl
+Comment[de]=Vorgang wurde mit Fehlern beendet
+Comment[el]=Η διεργασία ολοκληρώθηκε με σφάλματα
+Comment[eo]=Tasko finis erare
+Comment[es]=Proceso terminado con errores
+Comment[et]=Tegevus lõppes vigadega
+Comment[fa]=فرآیند با خطاهایی تمام شد
+Comment[fi]=Työtä suoritettaessa tapahtui virheitä
+Comment[fr]=Processus terminé avec des erreurs
+Comment[gl]=O proceso terminou con erros
+Comment[he]=התהליך הסתיים עם שגיאות
+Comment[hi]=प्रक्रिया त्रुटि के साथ पूर्ण
+Comment[hu]=A művelet hibajelzéssel fejeződött be
+Comment[is]=Ferli lauk með villum
+Comment[it]=Processo terminato con errori
+Comment[ja]=プロセス未了 (エラー)
+Comment[ka]=პროცესი შეცდომებით დასრულდა
+Comment[km]=បាន​បញ្ចប់​ដំណើរការ​ដោយ​មាន​កំហុស
+Comment[lt]=Procesas baigtas su klaidomis
+Comment[mk]=Процесот заврши со грешки
+Comment[ms]= Proses selesai dengan ralat
+Comment[nb]=Prosessen ble fullført med feil
+Comment[nds]=Vörgang mit Fehlers afslaten
+Comment[ne]=प्रक्रिया त्रुटिसँग समाप्त भयो
+Comment[nl]=Proces voltooid met fouten
+Comment[nn]=Prosess vart fullført med feil
+Comment[pa]=ਕਾਰਵਾਈ ਗਲਤੀਆਂ ਨਾਲ ਪੂਰੀ
+Comment[pl]=Proces zakończył się z błędami
+Comment[pt]=O processo terminou com erros
+Comment[pt_BR]=Processo finalizado com erros
+Comment[ru]=Процесс завершён с ошибками
+Comment[sk]=Proces ukončený s chybami
+Comment[sl]=Proces je končal brez napak
+Comment[sr]=Обрада је завршена уз грешке
+Comment[sr@Latn]=Obrada je završena uz greške
+Comment[sv]=Processen avslutades med fel
+Comment[ta]=பிழையுள்ள தொகுப்பு முடிந்தது
+Comment[tg]=Амалиёт бо хатогӣ ба анҷом расид
+Comment[tr]=İşlem hatayla sonuçlandı
+Comment[uk]=Процес завершився з помилками
+Comment[uz]=Jarayon xatolar bilan tugadi
+Comment[uz@cyrillic]=Жараён хатолар билан тугади
+Comment[zh_CN]=处理完成,有错误
+Comment[zh_TW]=完成處理,但發生錯誤
+default_sound=k3b_error1.wav
+default_presentation=1
+
+[WaitingForMedium]
+Name=Waiting for medium
+Name[af]=Wag vir medium
+Name[ar]= في انتظار الواسطة
+Name[bg]=Изчакване за диск
+Name[bn]=মাধ্যমের জন্য অপেক্ষারত
+Name[br]=Emaon o c'hortoz evit ar vedium
+Name[bs]=Čekam medij
+Name[ca]=S'està esperant un suport
+Name[cs]=Čekám na médium
+Name[da]=Venter på mediet
+Name[de]=Warten auf Medium
+Name[el]=Αναμονή για μέσο
+Name[eo]=Atendante ujon
+Name[es]=Esperando medio
+Name[et]=Andmekandja ootamine
+Name[fa]=انتظار برای رسانه
+Name[fi]=Odotetaan levyä
+Name[fr]=En attente du média
+Name[gl]=Á espera do disco
+Name[he]=מצפה למדיה
+Name[hi]=साधन हेतु प्रतीक्षारत
+Name[hu]=Várakozás egy lemezre
+Name[is]=Býð eftir miðli
+Name[it]=Si è in attesa di un supporto
+Name[ja]=メディアを待っています
+Name[ka]=ველოდები მატარებელს
+Name[km]=កំពុងរង់ចាំ​មេឌៀ
+Name[lt]=Laukiama disko
+Name[mk]=Исчекување за носач
+Name[ms]= Menunggu media
+Name[nb]=Venter på medium
+Name[nds]=An't Töven op Medium
+Name[ne]=माध्यमका लागि प्रतिक्षा गर्दै
+Name[nl]=Wacht op medium
+Name[nn]=Ventar på medium
+Name[pa]=ਲਿਖਣ ਲਈ ਮੀਡਿਆ ਦੀ ਉਡੀਕ
+Name[pl]=Oczekiwanie na płytę
+Name[pt]=À espera do disco
+Name[pt_BR]=Aguardando pela mídia
+Name[ru]=Ожидание носителя
+Name[sk]=Čakám na médium
+Name[sl]=Čakanje na medij
+Name[sr]=Чекам на диск
+Name[sr@Latn]=Čekam na disk
+Name[sv]=Väntar på media
+Name[ta]=ஊடகத்திற்காக காத்திருக்கவும்
+Name[tg]=Интизори расона
+Name[tr]=Ortam bekleniyor
+Name[uk]=Очікування носія
+Name[uz]=Disk kutilmoqda
+Name[uz@cyrillic]=Диск кутилмоқда
+Name[zh_CN]=等待存储介质
+Name[zh_TW]=等待插入媒體
+Comment=The user needs to insert a medium
+Comment[af]=Die gebruiker moet 'n medium insit
+Comment[ar]= يجب على المستعمل ادخال الواسطة
+Comment[bg]=Потребителят трябва да постави диск в устройството
+Comment[bn]=ব্যবহারকারীর একটি মাধ্যম ভিতরে ঢোকানোর প্রয়োজন
+Comment[bs]=Korisnik mora ubaciti medij
+Comment[ca]=Cal que l'usuari insereixi un suport
+Comment[cs]=Uživatel musí vložit médium
+Comment[da]=Brugeren må indsætte et medie
+Comment[de]=Der Benutzer muss ein Medium einlegen
+Comment[el]=Ο χρήστης πρέπει να εισάγει ένα μέσο
+Comment[eo]=La uzanto devas enigi ujon
+Comment[es]=El usuario necesita insertar un medio
+Comment[et]=Kasutajal tuleb andmekandja sisse panna
+Comment[fa]=کاربر نیاز به درج یک رسانه دارد
+Comment[fi]=Odotetaan käyttäjän syöttävän levyn
+Comment[fr]=L'utilisateur doit insérer un média
+Comment[gl]=O usuário debe inserir un disco
+Comment[he]=המשתמש חייב להכניס מדיית צריבה
+Comment[hi]=उपयोगकर्ता को आवश्यक होगा कि साधन प्रविष्ट करे
+Comment[hu]=Be kell helyezni egy lemezt
+Comment[is]=Notandi verður að setja inn disk
+Comment[it]=L'utente deve inserire un supporto
+Comment[ja]=メディアを入れてください
+Comment[ka]=მომხმარებელს სჭირდება მატარებლის ჩადება
+Comment[km]=អ្នកប្រើ​ត្រូវ​តែ​បញ្ចូល​ឧបករណ៍​ផ្ទុក​មួយ
+Comment[lt]=Naudotojas turi įdėti diską
+Comment[mk]=Корисникот треба да внесе носач
+Comment[ms]=Pengguna perlu menyelitkan media
+Comment[nb]=Brukeren må sette inn et medium
+Comment[nds]=De Bruker mutt en Medium inleggen
+Comment[ne]=प्रयोगकर्तालाई माध्यम घुसाउँन आवश्यक पर्दछ
+Comment[nl]=De gebruiker dient een medium in te voeren
+Comment[nn]=Brukaren må setja inn eit medium
+Comment[pa]=ਉਪਭੋਗੀ ਨੂੰ ਇੱਕ ਮੀਡੀਅਮ ਪਾਉਣ ਦੀ ਲੋੜ ਹੈ
+Comment[pl]=Użytkownik musi włożyć płytę
+Comment[pt]=O utilizador tem que inserir um disco
+Comment[pt_BR]=O usuário precisa inserir uma mídia
+Comment[ru]=Необходимо вставить носитель
+Comment[sk]=Používateľ má vložiť médium
+Comment[sl]=Uporabnik mora vstaviti medij
+Comment[sr]=Корисник мора да убаци диск
+Comment[sr@Latn]=Korisnik mora da ubaci disk
+Comment[sv]=Användaren måste mata in media
+Comment[ta]=உபயோகிப்பவர் ஊடகத்தை சொருக வேண்டும்
+Comment[tg]=Истифодабаранда бояд расонаро барқарор кунад
+Comment[tr]=Kullanıcının bir ortam takması gerekiyor
+Comment[uk]=Користувач мусить вставити носій
+Comment[uz]=Foydalanuvchi diskni qoʻyishi kerak
+Comment[uz@cyrillic]=Фойдаланувчи дискни қўйиши керак
+Comment[zh_CN]=用户需要插入存储介质
+Comment[zh_TW]=使用者需要插入媒體
+default_sound=k3b_wait_media1.wav
+default_presentation=1
diff --git a/src/fastscale/Makefile.am b/src/fastscale/Makefile.am
new file mode 100644
index 0000000..2fafe00
--- /dev/null
+++ b/src/fastscale/Makefile.am
@@ -0,0 +1,14 @@
+AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. $(all_includes)
+AM_CCASFLAGS = -I$(srcdir) $(GV_ASM_DEFS)
+
+#CXXFLAGS = -fexceptions
+
+noinst_LTLIBRARIES = libfastscale.la
+
+libfastscale_la_SOURCES = \
+ scale.cpp \
+ asm_scale.S
+
+libfastscale_la_LIBADD = $(LIB_KDECORE) $(LIBQT) $(LIBJPEG)
+
+METASOURCES = AUTO
diff --git a/src/fastscale/README b/src/fastscale/README
new file mode 100644
index 0000000..13d4ccc
--- /dev/null
+++ b/src/fastscale/README
@@ -0,0 +1,2 @@
+This directory contains fast scaling algorithms from ImageMagick and Mosfet.
+They have been copied from the Gwenview source tree. \ No newline at end of file
diff --git a/src/fastscale/asm_scale.S b/src/fastscale/asm_scale.S
new file mode 100644
index 0000000..08b43da
--- /dev/null
+++ b/src/fastscale/asm_scale.S
@@ -0,0 +1,810 @@
+#ifdef HAVE_X86_MMX
+
+#ifdef __EMX__
+/* Due to strange behaviour of as.exe we use this macros */
+/* For all OS/2 coders - please use PGCC to compile this code */
+#define PR_(foo) ___##foo
+#define PT_(foo,func) ___##foo,func
+#define SIZE(sym) \
+ .___end_##sym:; \
+ .size ___##sym,.___end_##sym-___##sym; \
+ .align 8;
+#else
+#define PR_(foo) __##foo
+#define PT_(foo,func) __##foo,func
+#define SIZE(sym) \
+ .__end_##sym:; \
+ .size __##sym,.__end_##sym-__##sym; \
+ .align 8;
+#endif
+
+/*\
+|*| MMX assembly scaling routine for Imlib2
+|*| Written by Willem Monsuwe <willem@stack.nl>
+\*/
+
+.text
+ .align 8
+.globl PR_(mimageScale_mmx_AARGBA)
+/* .type PT_(mimageScale_mmx_AARGBA,@function) */
+
+
+/*\ Prototype: __mimageScale_mmx_AARGBA(ImlibScaleInfo *isi, DATA32 *dest,
+|*| int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow)
+\*/
+
+#define isi 8(%ebp)
+#define dest 12(%ebp)
+#define dxx 16(%ebp)
+#define dyy 20(%ebp)
+#define dx 24(%ebp)
+#define dy 28(%ebp)
+#define dw 32(%ebp)
+#define dh 36(%ebp)
+#define dow 40(%ebp)
+#define sow 44(%ebp)
+
+/*\ Local variables that didn't fit in registers \*/
+#define y -4(%ebp)
+#define yp -8(%ebp)
+#define yap -12(%ebp)
+#define xp -16(%ebp)
+#define xap -20(%ebp)
+#define Cx -24(%ebp)
+#define Mx -28(%ebp)
+#define Cy -32(%ebp)
+#define My -36(%ebp)
+#define sow_4 -40(%ebp)
+
+/*\ When %edx points to ImlibScaleInfo, these are the members \*/
+#define xpoints (%edx)
+#define ypoints 4(%edx)
+#define xapoints 8(%edx)
+#define yapoints 12(%edx)
+#define xup_yup 16(%edx)
+
+PR_(mimageScale_mmx_AARGBA):
+ pushl %ebp
+ movl %esp, %ebp
+ subl $40, %esp
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %edi
+ pushl %esi
+ movl isi, %edx
+
+ /*\ Check (dw > 0) && (dh > 0) \*/
+ cmpl $0, dw
+ jle .scale_leave
+ cmpl $0, dh
+ jle .scale_leave
+
+ /*\ X-based array pointers point to the end; we're looping up to 0 \*/
+ /*\ %edi = dest + dow * dy + dx + dw \*/
+ movl dow, %eax
+ imull dy, %eax
+ addl dx, %eax
+ addl dw, %eax
+ movl dest, %edi
+ leal (%edi, %eax, 4), %edi
+ /*\ xp = xpoints + dxx + dw \*/
+ movl dxx, %ebx
+ addl dw, %ebx
+ movl xpoints, %eax
+ leal (%eax, %ebx, 4), %eax
+ movl %eax, xp
+ /*\ xap = xapoints + dxx + dw \*/
+ movl xapoints, %eax
+ leal (%eax, %ebx, 4), %eax
+ movl %eax, xap
+ /*\ y = dh \*/
+ movl dh, %eax
+ movl %eax, y
+ /*\ yp = ypoints + dyy \*/
+ movl dyy, %ebx
+ movl ypoints, %eax
+ leal (%eax, %ebx, 4), %eax
+ movl %eax, yp
+ /*\ yap = yapoints + dyy \*/
+ movl yapoints, %eax
+ leal (%eax, %ebx, 4), %eax
+ movl %eax, yap
+
+ pxor %mm7, %mm7
+
+ /*\ Test xup bit \*/
+ movl xup_yup, %eax
+ sarl $1, %eax
+ jnc .scale_x_down
+
+.scale_x_up:
+ /*\ Test yup bit \*/
+ sarl $1, %eax
+ jnc .scale_x_up_y_down
+
+
+/*\ Scaling up both ways \*/
+
+.scale_x_up_y_up:
+ movl sow, %ebx
+
+.up_up_loop_y:
+
+ /*\ x = -dw \*/
+ movl dw, %ecx
+ negl %ecx
+
+ /*\ %eax = *yap << 4 \*/
+ movl yap, %eax
+ movl (%eax), %eax
+ sall $4, %eax
+ jz .up_up_yap_0
+ movd %eax, %mm1
+ punpcklwd %mm1, %mm1
+ punpckldq %mm1, %mm1
+
+.up_up_loop1_x:
+ /*\ %esi = *yp + xp[x] \*/
+ movl yp, %eax
+ movl (%eax), %esi
+ movl xp, %eax
+ movl (%eax, %ecx, 4), %eax
+ leal (%esi, %eax, 4), %esi
+
+ /*\ %eax = xap[x] << 4 \*/
+ movl xap, %eax
+ movl (%eax, %ecx, 4), %eax
+ sall $4, %eax
+ jz .up_up_xap_0
+
+ /*\ %mm0 = xap[x] << 4 \*/
+ movd %eax, %mm0
+ punpcklwd %mm0, %mm0
+ punpckldq %mm0, %mm0
+
+ /*\ Load and unpack four pixels in parralel
+ |*| %mm2 = ptr[0], %mm3 = ptr[1]
+ |*| %mm4 = ptr[sow], %mm5 = ptr[sow + 1]
+ \*/
+ movq (%esi), %mm2
+ movq (%esi, %ebx, 4), %mm4
+ movq %mm2, %mm3
+ movq %mm4, %mm5
+ punpcklbw %mm7, %mm2
+ punpcklbw %mm7, %mm4
+ punpckhbw %mm7, %mm3
+ punpckhbw %mm7, %mm5
+
+ /*\ X interpolation: r = l + (r - l) * xap \*/
+ psubw %mm2, %mm3
+ psubw %mm4, %mm5
+ psllw $4, %mm3
+ psllw $4, %mm5
+ pmulhw %mm0, %mm3
+ pmulhw %mm0, %mm5
+ paddw %mm2, %mm3
+ paddw %mm4, %mm5
+ /*\ Now %mm3 = I(ptr[0], ptr[1]), %mm5 = I(ptr[sow], ptr[sow + 1]) \*/
+ jmp .up_up_common
+.up_up_xap_0:
+ /*\ Load and unpack two pixels
+ |*| %mm3 = ptr[0], %mm5 = ptr[sow]
+ \*/
+ movd (%esi), %mm3
+ movd (%esi, %ebx, 4), %mm5
+ punpcklbw %mm7, %mm3
+ punpcklbw %mm7, %mm5
+.up_up_common:
+ /*\ Y interpolation: d = u + (d - u) * yap \*/
+ psubw %mm3, %mm5
+ psllw $4, %mm5
+ pmulhw %mm1, %mm5
+ paddw %mm3, %mm5
+ packuswb %mm5, %mm5
+ movd %mm5, (%edi, %ecx, 4)
+
+ /*\ while (++x) \*/
+ incl %ecx
+ jnz .up_up_loop1_x
+ jmp .up_up_yap_end
+.up_up_yap_0:
+
+.up_up_loop2_x:
+ /*\ %esi = *yp + xp[x] \*/
+ movl yp, %eax
+ movl (%eax), %esi
+ movl xp, %eax
+ movl (%eax, %ecx, 4), %eax
+ leal (%esi, %eax, 4), %esi
+
+ /*\ %eax = xap[x] << 4 \*/
+ movl xap, %eax
+ movl (%eax, %ecx, 4), %eax
+ sall $4, %eax
+ jz .up_up_0
+
+ /*\ %mm0 = xap[x] << 4 \*/
+ movd %eax, %mm0
+ punpcklwd %mm0, %mm0
+ punpckldq %mm0, %mm0
+
+ /*\ Load and unpack two pixels in parralel
+ |*| %mm2 = ptr[0], %mm3 = ptr[1]
+ \*/
+ movq (%esi), %mm2
+ movq %mm2, %mm3
+ punpcklbw %mm7, %mm2
+ punpckhbw %mm7, %mm3
+
+ /*\ X interpolation: r = l + (r - l) * xap \*/
+ psubw %mm2, %mm3
+ psllw $4, %mm3
+ pmulhw %mm0, %mm3
+ paddw %mm2, %mm3
+ packuswb %mm3, %mm3
+ movd %mm3, (%edi, %ecx, 4)
+ jmp .up_up_1
+.up_up_0:
+ /*\ dptr[x] = *sptr \*/
+ movl (%esi), %eax
+ movl %eax, (%edi, %ecx, 4)
+.up_up_1:
+ incl %ecx
+ jnz .up_up_loop2_x
+
+.up_up_yap_end:
+ /*\ dptr += dow \*/
+ movl dow, %eax
+ leal (%edi, %eax, 4), %edi
+ /*\ yap++; yp++ \*/
+ addl $4, yap
+ addl $4, yp
+ /*\ while (y--) \*/
+ decl y
+ jnz .up_up_loop_y
+
+ jmp .scale_leave
+
+
+/*\ Scaling down vertically \*/
+
+.scale_x_up_y_down:
+ /*\ sow_4 = sow * 4 \*/
+ movl sow, %eax
+ sall $2, %eax
+ movl %eax, sow_4
+
+.up_down_loop_y:
+
+ /*\ Setup My and Cy \*/
+ movl yap, %eax
+ movzwl (%eax), %ebx
+ movl %ebx, My
+ movzwl 2(%eax), %eax
+ movl %eax, Cy
+
+ /*\ mm4 = Cy \*/
+ movd %eax, %mm4
+ punpcklwd %mm4, %mm4
+ punpckldq %mm4, %mm4
+ /*\ mm5 = My \*/
+ movd %ebx, %mm5
+ punpcklwd %mm5, %mm5
+ punpckldq %mm5, %mm5
+
+ /*\ x = -dw \*/
+ movl dw, %ecx
+ negl %ecx
+.up_down_loop_x:
+ /*\ %esi = *yp + xp[x] \*/
+ movl yp, %eax
+ movl (%eax), %esi
+ movl xp, %eax
+ movl (%eax, %ecx, 4), %eax
+ leal (%esi, %eax, 4), %esi
+
+ movl %esi, %eax
+ /*\ v = (*p * My) >> 10 \*/
+ movd (%eax), %mm0
+ punpcklbw %mm7, %mm0
+ psllw $6, %mm0
+ pmulhw %mm5, %mm0
+
+ /*\ i = 0x4000 - My \*/
+ movl $0x4000, %ebx
+ subl My, %ebx
+ jbe 5f
+ jmp 2f
+1:
+ /*\ p += sow; v += (*p * Cy) >> 10 \*/
+ addl sow_4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm4, %mm1
+ paddw %mm1, %mm0
+
+ /*\ i -= Cy; while (i > Cy) \*/
+ subl Cy, %ebx
+2:
+ cmpl Cy, %ebx
+ jg 1b
+
+ /*\ mm6 = i \*/
+ movd %ebx, %mm6
+ punpcklwd %mm6, %mm6
+ punpckldq %mm6, %mm6
+
+ /*\ p += sow; v += (*p * i) >> 10 \*/
+ addl sow_4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm6, %mm1
+ paddw %mm1, %mm0
+5:
+ /*\ %eax = xap[x] << 5 \*/
+ movl xap, %eax
+ movl (%eax, %ecx, 4), %eax
+ sall $5, %eax
+ jz 6f
+ /*\ mm3 = xap[x] << 5 \*/
+ movd %eax, %mm3
+ punpcklwd %mm3, %mm3
+ punpckldq %mm3, %mm3
+
+ /*\ p + 1 \*/
+ movl %esi, %eax
+ addl $4, %eax
+ /*\ vv = (*p * My) >> 10 \*/
+ movd (%eax), %mm2
+ punpcklbw %mm7, %mm2
+ psllw $6, %mm2
+ pmulhw %mm5, %mm2
+
+ /*\ i = 0x4000 - My \*/
+ movl $0x4000, %ebx
+ subl My, %ebx
+ jbe 5f
+ jmp 2f
+1:
+ /*\ p += sow; vv += (*p * Cy) >> 10 \*/
+ addl sow_4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm4, %mm1
+ paddw %mm1, %mm2
+
+ /*\ i -= Cy; while (i > Cy) \*/
+ subl Cy, %ebx
+2:
+ cmpl Cy, %ebx
+ jg 1b
+
+ /*\ p += sow; v += (*p * i) >> 10 \*/
+ addl sow_4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm6, %mm1
+ paddw %mm1, %mm2
+5:
+ /*\ v = v + (vv - v) * xap \*/
+ psubw %mm0, %mm2
+ psllw $3, %mm2
+ pmulhw %mm3, %mm2
+ paddw %mm2, %mm0
+6:
+ /*\ dest[x] = v >> 4 \*/
+ psrlw $4, %mm0
+ packuswb %mm0, %mm0
+ movd %mm0, (%edi, %ecx, 4)
+
+ /*\ while (++x) \*/
+ incl %ecx
+ jnz .up_down_loop_x
+
+ /*\ dptr += dow \*/
+ movl dow, %eax
+ leal (%edi, %eax, 4), %edi
+ /*\ yap++; yp++ \*/
+ addl $4, yap
+ addl $4, yp
+ /*\ while (y--) \*/
+ decl y
+ jnz .up_down_loop_y
+
+ jmp .scale_leave
+
+.scale_x_down:
+ /*\ Test yup bit \*/
+ sarl $1, %eax
+ jnc .scale_x_down_y_down
+
+
+/*\ Scaling down horizontally \*/
+
+.scale_x_down_y_up:
+ /*\ sow_4 = sow * 4 \*/
+ movl sow, %eax
+ sall $2, %eax
+ movl %eax, sow_4
+
+.down_up_loop_y:
+
+ /*\ %eax = *yap << 5 \*/
+ movl yap, %eax
+ movl (%eax), %eax
+ sall $5, %eax
+ /*\ mm3 = *yap << 5 \*/
+ movd %eax, %mm3
+ punpcklwd %mm3, %mm3
+ punpckldq %mm3, %mm3
+
+ /*\ x = -dw \*/
+ movl dw, %ecx
+ negl %ecx
+.down_up_loop_x:
+ /*\ %esi = *yp + xp[x] \*/
+ movl yp, %eax
+ movl (%eax), %esi
+ movl xp, %eax
+ movl (%eax, %ecx, 4), %eax
+ leal (%esi, %eax, 4), %esi
+
+ /*\ Setup Mx and Cx \*/
+ movl xap, %eax
+ movzwl (%eax, %ecx, 4), %ebx
+ movl %ebx, Mx
+ movzwl 2(%eax, %ecx, 4), %eax
+ movl %eax, Cx
+
+ /*\ mm4 = Cx \*/
+ movd %eax, %mm4
+ punpcklwd %mm4, %mm4
+ punpckldq %mm4, %mm4
+ /*\ mm5 = Mx \*/
+ movd %ebx, %mm5
+ punpcklwd %mm5, %mm5
+ punpckldq %mm5, %mm5
+
+ movl %esi, %eax
+ /*\ v = (*p * Mx) >> 10 \*/
+ movd (%eax), %mm0
+ punpcklbw %mm7, %mm0
+ psllw $6, %mm0
+ pmulhw %mm5, %mm0
+
+ /*\ i = 0x4000 - Mx \*/
+ movl $0x4000, %ebx
+ subl Mx, %ebx
+ jbe 5f
+ jmp 2f
+1:
+ /*\ p += sow; v += (*p * Cx) >> 10 \*/
+ addl $4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm4, %mm1
+ paddw %mm1, %mm0
+
+ /*\ i -= Cx; while (i > Cx) \*/
+ subl Cx, %ebx
+2:
+ cmpl Cx, %ebx
+ jg 1b
+
+ /*\ mm6 = i \*/
+ movd %ebx, %mm6
+ punpcklwd %mm6, %mm6
+ punpckldq %mm6, %mm6
+
+ /*\ p += sow; v += (*p * i) >> 10 \*/
+ addl $4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm6, %mm1
+ paddw %mm1, %mm0
+5:
+ movd %mm3, %eax
+ testl %eax, %eax
+ jz 6f
+ /*\ p + sow \*/
+ movl %esi, %eax
+ addl sow_4, %eax
+ /*\ vv = (*p * Mx) >> 10 \*/
+ movd (%eax), %mm2
+ punpcklbw %mm7, %mm2
+ psllw $6, %mm2
+ pmulhw %mm5, %mm2
+
+ /*\ i = 0x4000 - Mx \*/
+ movl $0x4000, %ebx
+ subl Mx, %ebx
+ jbe 5f
+ jmp 2f
+1:
+ /*\ p += sow; vv += (*p * Cx) >> 10 \*/
+ addl $4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm4, %mm1
+ paddw %mm1, %mm2
+
+ /*\ i -= Cx; while (i > Cx) \*/
+ subl Cx, %ebx
+2:
+ cmpl Cx, %ebx
+ jg 1b
+
+ /*\ p += sow; v += (*p * i) >> 10 \*/
+ addl $4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $6, %mm1
+ pmulhw %mm6, %mm1
+ paddw %mm1, %mm2
+5:
+ /*\ v = v + (vv - v) * yap \*/
+ psubw %mm0, %mm2
+ psllw $3, %mm2
+ pmulhw %mm3, %mm2
+ paddw %mm2, %mm0
+6:
+ /*\ dest[x] = v >> 4 \*/
+ psrlw $4, %mm0
+ packuswb %mm0, %mm0
+ movd %mm0, (%edi, %ecx, 4)
+
+ /*\ while (++x) \*/
+ incl %ecx
+ jnz .down_up_loop_x
+
+ /*\ dptr += dow \*/
+ movl dow, %eax
+ leal (%edi, %eax, 4), %edi
+ /*\ yap++; yp++ \*/
+ addl $4, yap
+ addl $4, yp
+ /*\ while (y--) \*/
+ decl y
+ jnz .down_up_loop_y
+
+ jmp .scale_leave
+
+
+/*\ Scaling down both ways \*/
+
+.scale_x_down_y_down:
+ /*\ sow_4 = sow * 4 \*/
+ movl sow, %eax
+ sall $2, %eax
+ movl %eax, sow_4
+
+.down_down_loop_y:
+
+ /*\ Setup My and Cy \*/
+ movl yap, %eax
+ movzwl (%eax), %ebx
+ movl %ebx, My
+ movzwl 2(%eax), %eax
+ movl %eax, Cy
+
+ /*\ x = -dw \*/
+ movl dw, %ecx
+ negl %ecx
+.down_down_loop_x:
+ /*\ %esi = *yp + xp[x] \*/
+ movl yp, %eax
+ movl (%eax), %esi
+ movl xp, %eax
+ movl (%eax, %ecx, 4), %eax
+ leal (%esi, %eax, 4), %esi
+
+ /*\ Setup Mx and Cx \*/
+ movl xap, %eax
+ movzwl (%eax, %ecx, 4), %ebx
+ movl %ebx, Mx
+ movzwl 2(%eax, %ecx, 4), %eax
+ movl %eax, Cx
+
+ /*\ mm3 = Cx \*/
+ movd %eax, %mm3
+ punpcklwd %mm3, %mm3
+ punpckldq %mm3, %mm3
+ /*\ mm5 = Mx \*/
+ movd %ebx, %mm5
+ punpcklwd %mm5, %mm5
+ punpckldq %mm5, %mm5
+
+ /*\ p = sptr; v = (*p * Mx) >> 9 \*/
+ movl %esi, %eax
+ movd (%eax), %mm0
+ punpcklbw %mm7, %mm0
+ psllw $7, %mm0
+ pmulhw %mm5, %mm0
+
+ /*\ i = 0x4000 - Mx \*/
+ movl $0x4000, %ebx
+ subl Mx, %ebx
+ jbe 5f
+ jmp 2f
+1:
+ /*\ v += (*++p * Cx) >> 9 \*/
+ addl $4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $7, %mm1
+ pmulhw %mm3, %mm1
+ paddw %mm1, %mm0
+
+ /*\ i -= Cx; while (i > Cx) \*/
+ subl Cx, %ebx
+2:
+ cmpl Cx, %ebx
+ jg 1b
+
+ /*\ mm6 = i \*/
+ movd %ebx, %mm6
+ punpcklwd %mm6, %mm6
+ punpckldq %mm6, %mm6
+
+ /*\ v += (*++p * i) >> 9 \*/
+ addl $4, %eax
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $7, %mm1
+ pmulhw %mm6, %mm1
+ paddw %mm1, %mm0
+5:
+ /*\ v *= My \*/
+ movd My, %mm4
+ punpcklwd %mm4, %mm4
+ punpckldq %mm4, %mm4
+ psllw $2, %mm0
+ pmulhw %mm4, %mm0
+
+ /*\ j = 0x4000 - My \*/
+ movl $0x4000, %edx
+ subl My, %edx
+ jbe 6f
+ jmp 4f
+3:
+ /*\ sptr += sow; p = sptr \*/
+ addl sow_4, %esi
+ movl %esi, %eax
+ /*\ vx = (*p * Mx) >> 9 \*/
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $7, %mm1
+ pmulhw %mm5, %mm1
+
+ /*\ i = 0x4000 - Mx \*/
+ movl $0x4000, %ebx
+ subl Mx, %ebx
+ jbe 5f
+ jmp 2f
+1:
+ /*\ vx += (*++p * Cx) >> 9 \*/
+ addl $4, %eax
+ movd (%eax), %mm2
+ punpcklbw %mm7, %mm2
+ psllw $7, %mm2
+ pmulhw %mm3, %mm2
+ paddw %mm2, %mm1
+
+ /*\ i -= Cx; while (i > Cx) \*/
+ subl Cx, %ebx
+2:
+ cmpl Cx, %ebx
+ jg 1b
+
+ /*\ vx += (*++p * i) >> 9 \*/
+ addl $4, %eax
+ movd (%eax), %mm2
+ punpcklbw %mm7, %mm2
+ psllw $7, %mm2
+ pmulhw %mm6, %mm2
+ paddw %mm2, %mm1
+5:
+ /*\ v += (vx * Cy) >> 14 \*/
+ movd Cy, %mm4
+ punpcklwd %mm4, %mm4
+ punpckldq %mm4, %mm4
+ psllw $2, %mm1
+ pmulhw %mm4, %mm1
+ paddw %mm1, %mm0
+
+ /*\ j -= Cy; while (j > Cy) \*/
+ subl Cy, %edx
+4:
+ cmpl Cy, %edx
+ jg 3b
+
+ /*\ sptr += sow; p = sptr \*/
+ addl sow_4, %esi
+ movl %esi, %eax
+ /*\ vx = (*p * Mx) >> 9 \*/
+ movd (%eax), %mm1
+ punpcklbw %mm7, %mm1
+ psllw $7, %mm1
+ pmulhw %mm5, %mm1
+
+ /*\ i = 0x4000 - Mx \*/
+ movl $0x4000, %ebx
+ subl Mx, %ebx
+ jbe 5f
+ jmp 2f
+1:
+ /*\ vx += (*++p * Cx) >> 9 \*/
+ addl $4, %eax
+ movd (%eax), %mm2
+ punpcklbw %mm7, %mm2
+ psllw $7, %mm2
+ pmulhw %mm3, %mm2
+ paddw %mm2, %mm1
+
+ /*\ i -= Cx; while (i > Cx) \*/
+ subl Cx, %ebx
+2:
+ cmpl Cx, %ebx
+ jg 1b
+
+ /*\ vx += (*++p * i) >> 9 \*/
+ addl $4, %eax
+ movd (%eax), %mm2
+ punpcklbw %mm7, %mm2
+ psllw $7, %mm2
+ pmulhw %mm6, %mm2
+ paddw %mm2, %mm1
+5:
+ /*\ v += (vx * j) >> 14 \*/
+ movd %edx, %mm4
+ punpcklwd %mm4, %mm4
+ punpckldq %mm4, %mm4
+ psllw $2, %mm1
+ pmulhw %mm4, %mm1
+ paddw %mm1, %mm0
+6:
+ /*\ dptr[x] = mm0 >> 5 \*/
+ psrlw $5, %mm0
+ packuswb %mm0, %mm0
+ movd %mm0, (%edi, %ecx, 4)
+
+ /*\ while (++x) \*/
+ incl %ecx
+ jnz .down_down_loop_x
+
+ /*\ dptr += dow \*/
+ movl dow, %eax
+ leal (%edi, %eax, 4), %edi
+ /*\ yap++; yp++ \*/
+ addl $4, yap
+ addl $4, yp
+ /*\ while (y--) \*/
+ decl y
+ jnz .down_down_loop_y
+
+ jmp .scale_leave
+
+.scale_leave:
+ emms
+ popl %esi
+ popl %edi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ movl %ebp, %esp
+ popl %ebp
+ ret
+
+SIZE(mimageScale_mmx_AARGBA)
+
+#endif
+
+.section .note.GNU-stack,"",%progbits
diff --git a/src/fastscale/configure.in.in b/src/fastscale/configure.in.in
new file mode 100644
index 0000000..a1a5f28
--- /dev/null
+++ b/src/fastscale/configure.in.in
@@ -0,0 +1,63 @@
+#
+# Imlib/Mosfet scaling
+#
+AM_PROG_AS
+
+# MMX test duped from kdelibs/kdefx - it should be probably moved to admin/
+dnl -----------------------------------------------------
+dnl IA32 checks
+dnl -----------------------------------------------------
+
+gv_asm_defs=
+case $host_cpu in
+ i*86 )
+ AC_MSG_CHECKING(for assembler support for IA32 extensions)
+
+ dnl MMX check
+ AC_TRY_COMPILE(, [ __asm__("pxor %mm0, %mm0") ],
+ [
+ echo $ECHO_N "MMX yes$ECHO_C"
+ AC_DEFINE_UNQUOTED(HAVE_X86_MMX, 1, [Define to 1 if the assembler supports MMX instructions.])
+ gv_asm_defs="$gv_asm_defs -DHAVE_X86_MMX"
+ ], [ echo $ECHO_N "MMX no$ECHO_C" ])
+
+ dnl SSE check
+ AC_TRY_COMPILE(,[ __asm__("xorps %xmm0, %xmm0") ],
+ [
+ echo $ECHO_N ", SSE yes$ECHO_C"
+ AC_DEFINE_UNQUOTED(HAVE_X86_SSE, 1, [Define to 1 if the assembler supports SSE instructions.])
+ gv_asm_defs="$gv_asm_defs -DHAVE_X86_SSE"
+ ], [ echo $ECHO_N ", SSE no$ECHO_C" ])
+
+ dnl SSE2 check
+ AC_TRY_COMPILE(, [ __asm__("xorpd %xmm0, %xmm0") ],
+ [
+ echo $ECHO_N ", SSE2 yes$ECHO_C"
+ AC_DEFINE_UNQUOTED(HAVE_X86_SSE2, 1, [Define to 1 if the assembler supports SSE2 instructions.])
+ gv_asm_defs="$gv_asm_defs -DHAVE_X86_SSE2"
+ ], [ echo $ECHO_N ", SSE2 no$ECHO_C" ])
+
+ dnl 3DNOW check
+ AC_TRY_COMPILE(, [ __asm__("femms") ],
+ [
+ echo $ECHO_N ", 3DNOW yes$ECHO_C"
+ AC_DEFINE_UNQUOTED(HAVE_X86_3DNOW, 1, [Define to 1 if the assembler supports 3DNOW instructions.])
+ gv_asm_defs="$gv_asm_defs -DHAVE_X86_3DNOW"
+ ], [ echo $ECHO_N ", 3DNOW no$ECHO_C" ])
+ echo
+ ;;
+ powerpc )
+ AC_MSG_CHECKING(for assembler support for AltiVec instructions)
+ dnl AltiVec check
+ AC_TRY_COMPILE(, [ __asm__("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0" : : "r"(-1) ) ],
+ [
+ echo $ECHO_N " yes$ECHO_C"
+ AC_DEFINE_UNQUOTED(HAVE_PPC_ALTIVEC, 1, [Define to 1 if the assembler supports AltiVec instructions.])
+ gv_asm_defs="$gv_asm_defs -DHAVE_PPC_ALTIVEC"
+ ], [ echo $ECHO_N ", AltiVec no$ECHO_C" ])
+ echo
+ ;;
+esac
+
+GV_ASM_DEFS="$gv_asm_defs"
+AC_SUBST(GV_ASM_DEFS)
diff --git a/src/fastscale/scale.cpp b/src/fastscale/scale.cpp
new file mode 100644
index 0000000..e2332fe
--- /dev/null
+++ b/src/fastscale/scale.cpp
@@ -0,0 +1,1975 @@
+// This file includes code for scaling images, in two versions.
+// One ported from ImageMagick (slower, but can achieve better quality),
+// and from Imlib2 ported by Mosfet (very fast).
+
+
+// ImageMagick code begin
+// ----------------------
+
+// This code is ImageMagick's resize code, adapted for QImage, with
+// fastfloat class added as an optimization.
+// The original license text follows.
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% RRRR EEEEE SSSSS IIIII ZZZZZ EEEEE %
+% R R E SS I ZZ E %
+% RRRR EEE SSS I ZZZ EEE %
+% R R E SS I ZZ E %
+% R R EEEEE SSSSS IIIII ZZZZZ EEEEE %
+% %
+% ImageMagick Image Resize Methods %
+% %
+% %
+% Software Design %
+% John Cristy %
+% July 1992 %
+% %
+% %
+% Copyright (C) 2003 ImageMagick Studio, a non-profit organization dedicated %
+% to making software imaging solutions freely available. %
+% %
+% Permission is hereby granted, free of charge, to any person obtaining a %
+% copy of this software and associated documentation files ("ImageMagick"), %
+% to deal in ImageMagick without restriction, including without limitation %
+% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
+% and/or sell copies of ImageMagick, and to permit persons to whom the %
+% ImageMagick 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 ImageMagick. %
+% %
+% 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 %
+% ImageMagick Studio 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 ImageMagick or the use or other dealings in %
+% ImageMagick. %
+% %
+% Except as contained in this notice, the name of the ImageMagick Studio %
+% shall not be used in advertising or otherwise to promote the sale, use or %
+% other dealings in ImageMagick without prior written authorization from the %
+% ImageMagick Studio. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+*/
+#include "config.h"
+
+// System
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else
+#ifdef HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+#endif
+
+// Qt
+#include <qimage.h>
+#include <qcolor.h>
+
+#include <kdeversion.h>
+#include <kcpuinfo.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+// Local
+#include "scale.h"
+
+// everything in namespace
+namespace ImageUtils {
+
+
+#define Max QMAX
+#define Min QMIN
+
+// mustn't be less than used precision (i.e. 1/fastfloat::RATIO)
+#define MagickEpsilon 0.0002
+
+// fastfloat begin
+// this class stores floating point numbers as integers, with BITS shift,
+// i.e. value XYZ is stored as XYZ * RATIO
+struct fastfloat
+ {
+ private:
+ enum { BITS = 12, RATIO = 4096 };
+ public:
+ fastfloat() {}
+ fastfloat( long v ) : value( v << BITS ) {}
+ fastfloat( int v ) : value( v << BITS ) {}
+ fastfloat( double v ) : value( static_cast< long >( v * RATIO + 0.5 )) {}
+ double toDouble() const { return static_cast< double >( value ) / RATIO; }
+ long toLong() const { return value >> BITS; }
+ fastfloat& operator += ( fastfloat r ) { value += r.value; return *this; }
+ fastfloat& operator -= ( fastfloat r ) { value -= r.value; return *this; }
+ fastfloat& operator *= ( fastfloat r ) { value = static_cast< long long >( value ) * r.value >> BITS; return *this; }
+ fastfloat& operator /= ( fastfloat r ) { value = ( static_cast< long long >( value ) << BITS ) / r.value; return *this; }
+ bool operator< ( fastfloat r ) const { return value < r.value; }
+ bool operator<= ( fastfloat r ) const { return value <= r.value; }
+ bool operator> ( fastfloat r ) const { return value > r.value; }
+ bool operator>= ( fastfloat r ) const { return value >= r.value; }
+ bool operator== ( fastfloat r ) const { return value == r.value; }
+ bool operator!= ( fastfloat r ) const { return value != r.value; }
+ fastfloat operator-() const { return fastfloat( -value, false ); }
+ private:
+ fastfloat( long v, bool ) : value( v ) {} // for operator-()
+ long value;
+ };
+
+inline fastfloat operator+ ( fastfloat l, fastfloat r ) { return fastfloat( l ) += r; }
+inline fastfloat operator- ( fastfloat l, fastfloat r ) { return fastfloat( l ) -= r; }
+inline fastfloat operator* ( fastfloat l, fastfloat r ) { return fastfloat( l ) *= r; }
+inline fastfloat operator/ ( fastfloat l, fastfloat r ) { return fastfloat( l ) /= r; }
+
+inline bool operator< ( fastfloat l, double r ) { return l < fastfloat( r ); }
+inline bool operator<= ( fastfloat l, double r ) { return l <= fastfloat( r ); }
+inline bool operator> ( fastfloat l, double r ) { return l > fastfloat( r ); }
+inline bool operator>= ( fastfloat l, double r ) { return l >= fastfloat( r ); }
+inline bool operator== ( fastfloat l, double r ) { return l == fastfloat( r ); }
+inline bool operator!= ( fastfloat l, double r ) { return l != fastfloat( r ); }
+
+inline bool operator< ( double l, fastfloat r ) { return fastfloat( l ) < r ; }
+inline bool operator<= ( double l, fastfloat r ) { return fastfloat( l ) <= r ; }
+inline bool operator> ( double l, fastfloat r ) { return fastfloat( l ) > r ; }
+inline bool operator>= ( double l, fastfloat r ) { return fastfloat( l ) >= r ; }
+inline bool operator== ( double l, fastfloat r ) { return fastfloat( l ) == r ; }
+inline bool operator!= ( double l, fastfloat r ) { return fastfloat( l ) != r ; }
+
+inline double fasttodouble( fastfloat v ) { return v.toDouble(); }
+inline long fasttolong( fastfloat v ) { return v.toLong(); }
+
+#if 1 // change to 0 to turn fastfloat usage off
+#else
+#define fastfloat double
+#define fasttodouble( v ) double( v )
+#define fasttolong( v ) long( v )
+#endif
+
+//fastfloat end
+
+
+typedef fastfloat (*Filter)(const fastfloat, const fastfloat);
+
+typedef struct _ContributionInfo
+{
+ fastfloat
+ weight;
+
+ long
+ pixel;
+} ContributionInfo;
+
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% R e s i z e I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ResizeImage() scales an image to the desired dimensions with one of these
+% filters:
+%
+% Bessel Blackman Box
+% Catrom Cubic Gaussian
+% Hanning Hermite Lanczos
+% Mitchell Point Quandratic
+% Sinc Triangle
+%
+% Most of the filters are FIR (finite impulse response), however, Bessel,
+% Gaussian, and Sinc are IIR (infinite impulse response). Bessel and Sinc
+% are windowed (brought down to zero) with the Blackman filter.
+%
+% ResizeImage() was inspired by Paul Heckbert's zoom program.
+%
+% The format of the ResizeImage method is:
+%
+% Image *ResizeImage(Image *image,const unsigned long columns,
+% const unsigned long rows,const FilterTypes filter,const double blur,
+% ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: The image.
+%
+% o columns: The number of columns in the scaled image.
+%
+% o rows: The number of rows in the scaled image.
+%
+% o filter: Image filter to use.
+%
+% o blur: The blur factor where > 1 is blurry, < 1 is sharp.
+%
+% o exception: Return any errors or warnings in this structure.
+%
+%
+*/
+
+#if 0
+static fastfloat Bessel(const fastfloat x,const fastfloat)
+{
+ if (x == 0.0)
+ return(MagickPI/4.0);
+ return(BesselOrderOne(MagickPI*x)/(2.0*x));
+}
+
+static fastfloat Sinc(const fastfloat x,const fastfloat)
+{
+ if (x == 0.0)
+ return(1.0);
+ return(sin(MagickPI*x)/(MagickPI*x));
+}
+
+static fastfloat Blackman(const fastfloat x,const fastfloat)
+{
+ return(0.42+0.5*cos(MagickPI*x)+0.08*cos(2*MagickPI*x));
+}
+
+static fastfloat BlackmanBessel(const fastfloat x,const fastfloat)
+{
+ return(Blackman(x/support,support)*Bessel(x,support));
+}
+
+static fastfloat BlackmanSinc(const fastfloat x,const fastfloat)
+{
+ return(Blackman(x/support,support)*Sinc(x,support));
+}
+#endif
+
+static fastfloat Box(const fastfloat x,const fastfloat)
+{
+ if (x < -0.5)
+ return(0.0);
+ if (x < 0.5)
+ return(1.0);
+ return(0.0);
+}
+
+#if 0
+static fastfloat Catrom(const fastfloat x,const fastfloat)
+{
+ if (x < -2.0)
+ return(0.0);
+ if (x < -1.0)
+ return(0.5*(4.0+x*(8.0+x*(5.0+x))));
+ if (x < 0.0)
+ return(0.5*(2.0+x*x*(-5.0-3.0*x)));
+ if (x < 1.0)
+ return(0.5*(2.0+x*x*(-5.0+3.0*x)));
+ if (x < 2.0)
+ return(0.5*(4.0+x*(-8.0+x*(5.0-x))));
+ return(0.0);
+}
+
+static fastfloat Cubic(const fastfloat x,const fastfloat)
+{
+ if (x < -2.0)
+ return(0.0);
+ if (x < -1.0)
+ return((2.0+x)*(2.0+x)*(2.0+x)/6.0);
+ if (x < 0.0)
+ return((4.0+x*x*(-6.0-3.0*x))/6.0);
+ if (x < 1.0)
+ return((4.0+x*x*(-6.0+3.0*x))/6.0);
+ if (x < 2.0)
+ return((2.0-x)*(2.0-x)*(2.0-x)/6.0);
+ return(0.0);
+}
+
+static fastfloat Gaussian(const fastfloat x,const fastfloat)
+{
+ return(exp(-2.0*x*x)*sqrt(2.0/MagickPI));
+}
+
+static fastfloat Hanning(const fastfloat x,const fastfloat)
+{
+ return(0.5+0.5*cos(MagickPI*x));
+}
+
+static fastfloat Hamming(const fastfloat x,const fastfloat)
+{
+ return(0.54+0.46*cos(MagickPI*x));
+}
+
+static fastfloat Hermite(const fastfloat x,const fastfloat)
+{
+ if (x < -1.0)
+ return(0.0);
+ if (x < 0.0)
+ return((2.0*(-x)-3.0)*(-x)*(-x)+1.0);
+ if (x < 1.0)
+ return((2.0*x-3.0)*x*x+1.0);
+ return(0.0);
+}
+
+static fastfloat Lanczos(const fastfloat x,const fastfloat support)
+{
+ if (x < -3.0)
+ return(0.0);
+ if (x < 0.0)
+ return(Sinc(-x,support)*Sinc(-x/3.0,support));
+ if (x < 3.0)
+ return(Sinc(x,support)*Sinc(x/3.0,support));
+ return(0.0);
+}
+
+static fastfloat Mitchell(const fastfloat x,const fastfloat)
+{
+#define B (1.0/3.0)
+#define C (1.0/3.0)
+#define P0 (( 6.0- 2.0*B )/6.0)
+#define P2 ((-18.0+12.0*B+ 6.0*C)/6.0)
+#define P3 (( 12.0- 9.0*B- 6.0*C)/6.0)
+#define Q0 (( 8.0*B+24.0*C)/6.0)
+#define Q1 (( -12.0*B-48.0*C)/6.0)
+#define Q2 (( 6.0*B+30.0*C)/6.0)
+#define Q3 (( - 1.0*B- 6.0*C)/6.0)
+
+ if (x < -2.0)
+ return(0.0);
+ if (x < -1.0)
+ return(Q0-x*(Q1-x*(Q2-x*Q3)));
+ if (x < 0.0)
+ return(P0+x*x*(P2-x*P3));
+ if (x < 1.0)
+ return(P0+x*x*(P2+x*P3));
+ if (x < 2.0)
+ return(Q0+x*(Q1+x*(Q2+x*Q3)));
+ return(0.0);
+
+#undef B
+#undef C
+#undef P0
+#undef P2
+#undef P3
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+}
+#endif
+
+// this is the same like Mitchell, but it has different values
+// for B and C, resulting in sharper images
+// http://sourceforge.net/mailarchive/forum.php?thread_id=7445822&forum_id=1210
+static fastfloat Bicubic(const fastfloat x,const fastfloat)
+{
+#define B (0.0/3.0)
+#define C (2.0/3.0)
+#define P0 (( 6.0- 2.0*B )/6.0)
+#define P2 ((-18.0+12.0*B+ 6.0*C)/6.0)
+#define P3 (( 12.0- 9.0*B- 6.0*C)/6.0)
+#define Q0 (( 8.0*B+24.0*C)/6.0)
+#define Q1 (( -12.0*B-48.0*C)/6.0)
+#define Q2 (( 6.0*B+30.0*C)/6.0)
+#define Q3 (( - 1.0*B- 6.0*C)/6.0)
+
+ if (x < -2.0)
+ return(0.0);
+ if (x < -1.0)
+ return(Q0-x*(Q1-x*(Q2-x*Q3)));
+ if (x < 0.0)
+ return(P0+x*x*(P2-x*P3));
+ if (x < 1.0)
+ return(P0+x*x*(P2+x*P3));
+ if (x < 2.0)
+ return(Q0+x*(Q1+x*(Q2+x*Q3)));
+ return(0.0);
+
+#undef B
+#undef C
+#undef P0
+#undef P2
+#undef P3
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+}
+
+#if 0
+static fastfloat Quadratic(const fastfloat x,const fastfloat)
+{
+ if (x < -1.5)
+ return(0.0);
+ if (x < -0.5)
+ return(0.5*(x+1.5)*(x+1.5));
+ if (x < 0.5)
+ return(0.75-x*x);
+ if (x < 1.5)
+ return(0.5*(x-1.5)*(x-1.5));
+ return(0.0);
+}
+#endif
+
+static fastfloat Triangle(const fastfloat x,const fastfloat)
+{
+ if (x < -1.0)
+ return(0.0);
+ if (x < 0.0)
+ return(1.0+x);
+ if (x < 1.0)
+ return(1.0-x);
+ return(0.0);
+}
+
+static void HorizontalFilter(const QImage& source,QImage& destination,
+ const fastfloat x_factor,const fastfloat blur,
+ ContributionInfo *contribution, Filter filter, fastfloat filtersupport)
+{
+ fastfloat
+ center,
+ density,
+ scale,
+ support;
+
+ long
+ n,
+ start,
+ stop,
+ y;
+
+ register long
+ i,
+ x;
+
+ /*
+ Apply filter to resize horizontally from source to destination.
+ */
+ scale=blur*Max(1.0/x_factor,1.0);
+ support=scale* filtersupport;
+ if (support <= 0.5)
+ {
+ /*
+ Reduce to point sampling.
+ */
+ support=0.5+MagickEpsilon;
+ scale=1.0;
+ }
+ scale=1.0/scale;
+ for (x=0; x < (long) destination.width(); x++)
+ {
+ center=(fastfloat) (x+0.5)/x_factor;
+ start= fasttolong(Max(center-support+0.5,0));
+ stop= fasttolong(Min(center+support+0.5,source.width()));
+ density=0.0;
+ for (n=0; n < (stop-start); n++)
+ {
+ contribution[n].pixel=start+n;
+ contribution[n].weight=
+ filter (scale*(start+n-center+0.5), filtersupport );
+ density+=contribution[n].weight;
+ }
+ if ((density != 0.0) && (density != 1.0))
+ {
+ /*
+ Normalize.
+ */
+ density=1.0/density;
+ for (i=0; i < n; i++)
+ contribution[i].weight*=density;
+ }
+// p=AcquireImagePixels(source,contribution[0].pixel,0,contribution[n-1].pixel-
+// contribution[0].pixel+1,source->rows,exception);
+// q=SetImagePixels(destination,x,0,1,destination->rows);
+ for (y=0; y < (long) destination.height(); y++)
+ {
+ fastfloat red = 0;
+ fastfloat green = 0;
+ fastfloat blue = 0;
+ fastfloat alpha = 0;
+ for (i=0; i < n; i++)
+ {
+ int px = contribution[i].pixel;
+ int py = y;
+ QRgb p = reinterpret_cast< QRgb* >( source.jumpTable()[ py ])[ px ];
+ red+=contribution[i].weight*qRed(p);
+ green+=contribution[i].weight*qGreen(p);
+ blue+=contribution[i].weight*qBlue(p);
+ alpha+=contribution[i].weight*qAlpha(p);
+ }
+ QRgb pix = qRgba(
+ fasttolong( red < 0 ? 0 : red > 255 ? 255 : red + 0.5 ),
+ fasttolong( green < 0 ? 0 : green > 255 ? 255 : green + 0.5 ),
+ fasttolong( blue < 0 ? 0 : blue > 255 ? 255 : blue + 0.5 ),
+ fasttolong( alpha < 0 ? 0 : alpha > 255 ? 255 : alpha + 0.5 ));
+ reinterpret_cast< QRgb* >( destination.jumpTable()[ y ])[ x ] = pix;
+ }
+ }
+}
+
+static void VerticalFilter(const QImage& source,QImage& destination,
+ const fastfloat y_factor,const fastfloat blur,
+ ContributionInfo *contribution, Filter filter, fastfloat filtersupport )
+{
+ fastfloat
+ center,
+ density,
+ scale,
+ support;
+
+ long
+ n,
+ start,
+ stop,
+ x;
+
+ register long
+ i,
+ y;
+
+ /*
+ Apply filter to resize vertically from source to destination.
+ */
+ scale=blur*Max(1.0/y_factor,1.0);
+ support=scale* filtersupport;
+ if (support <= 0.5)
+ {
+ /*
+ Reduce to point sampling.
+ */
+ support=0.5+MagickEpsilon;
+ scale=1.0;
+ }
+ scale=1.0/scale;
+ for (y=0; y < (long) destination.height(); y++)
+ {
+ center=(fastfloat) (y+0.5)/y_factor;
+ start= fasttolong(Max(center-support+0.5,0));
+ stop= fasttolong(Min(center+support+0.5,source.height()));
+ density=0.0;
+ for (n=0; n < (stop-start); n++)
+ {
+ contribution[n].pixel=start+n;
+ contribution[n].weight=
+ filter (scale*(start+n-center+0.5), filtersupport);
+ density+=contribution[n].weight;
+ }
+ if ((density != 0.0) && (density != 1.0))
+ {
+ /*
+ Normalize.
+ */
+ density=1.0/density;
+ for (i=0; i < n; i++)
+ contribution[i].weight*=density;
+ }
+// p=AcquireImagePixels(source,0,contribution[0].pixel,source->columns,
+// contribution[n-1].pixel-contribution[0].pixel+1,exception);
+// q=SetImagePixels(destination,0,y,destination->columns,1);
+ for (x=0; x < (long) destination.width(); x++)
+ {
+ fastfloat red = 0;
+ fastfloat green = 0;
+ fastfloat blue = 0;
+ fastfloat alpha = 0;
+ for (i=0; i < n; i++)
+ {
+ int px = x;
+ int py = contribution[i].pixel;
+ QRgb p = reinterpret_cast< QRgb* >( source.jumpTable()[ py ])[ px ];
+ red+=contribution[i].weight*qRed(p);
+ green+=contribution[i].weight*qGreen(p);
+ blue+=contribution[i].weight*qBlue(p);
+ alpha+=contribution[i].weight*qAlpha(p);
+ }
+ QRgb pix = qRgba(
+ fasttolong( red < 0 ? 0 : red > 255 ? 255 : red + 0.5 ),
+ fasttolong( green < 0 ? 0 : green > 255 ? 255 : green + 0.5 ),
+ fasttolong( blue < 0 ? 0 : blue > 255 ? 255 : blue + 0.5 ),
+ fasttolong( alpha < 0 ? 0 : alpha > 255 ? 255 : alpha + 0.5 ));
+ reinterpret_cast< QRgb* >( destination.jumpTable()[ y ])[ x ] = pix;
+ }
+ }
+}
+
+static QImage ResizeImage(const QImage& image,const int columns,
+ const int rows, Filter filter, fastfloat filtersupport, double blur)
+{
+ ContributionInfo
+ *contribution;
+
+ fastfloat
+ support,
+ x_factor,
+ x_support,
+ y_factor,
+ y_support;
+
+ /*
+ Initialize resize image attributes.
+ */
+ if ((columns == image.width()) && (rows == image.height()) && (blur == 1.0))
+ return image.copy();
+ QImage resize_image( columns, rows, 32 );
+ resize_image.setAlphaBuffer( image.hasAlphaBuffer());
+ /*
+ Allocate filter contribution info.
+ */
+ x_factor=(fastfloat) resize_image.width()/image.width();
+ y_factor=(fastfloat) resize_image.height()/image.height();
+// i=(long) LanczosFilter;
+// if (image->filter != UndefinedFilter)
+// i=(long) image->filter;
+// else
+// if ((image->storage_class == PseudoClass) || image->matte ||
+// ((x_factor*y_factor) > 1.0))
+// i=(long) MitchellFilter;
+ x_support=blur*Max(1.0/x_factor,1.0)*filtersupport;
+ y_support=blur*Max(1.0/y_factor,1.0)*filtersupport;
+ support=Max(x_support,y_support);
+ if (support < filtersupport)
+ support=filtersupport;
+ contribution=new ContributionInfo[ fasttolong( 2.0*Max(support,0.5)+3 ) ];
+ Q_CHECK_PTR( contribution );
+ /*
+ Resize image.
+ */
+ if (((fastfloat) columns*(image.height()+rows)) >
+ ((fastfloat) rows*(image.width()+columns)))
+ {
+ QImage source_image( columns, image.height(), 32 );
+ source_image.setAlphaBuffer( image.hasAlphaBuffer());
+ HorizontalFilter(image,source_image,x_factor,blur,
+ contribution,filter,filtersupport);
+ VerticalFilter(source_image,resize_image,y_factor,
+ blur,contribution,filter,filtersupport);
+ }
+ else
+ {
+ QImage source_image( image.width(), rows, 32 );
+ source_image.setAlphaBuffer( image.hasAlphaBuffer());
+ VerticalFilter(image,source_image,y_factor,blur,
+ contribution,filter,filtersupport);
+ HorizontalFilter(source_image,resize_image,x_factor,
+ blur,contribution,filter,filtersupport);
+ }
+ /*
+ Free allocated memory.
+ */
+ delete[] contribution;
+ return(resize_image);
+}
+
+
+#undef Max
+#undef Min
+#undef MagickEpsilon
+
+
+// filters and their matching support values
+#if 0
+ static const FilterInfo
+ filters[SincFilter+1] =
+ {
+ { Box, 0.0 },
+ { Box, 0.0 },
+ { Box, 0.5 },
+ { Triangle, 1.0 },
+ { Hermite, 1.0 },
+ { Hanning, 1.0 },
+ { Hamming, 1.0 },
+ { Blackman, 1.0 },
+ { Gaussian, 1.25 },
+ { Quadratic, 1.5 },
+ { Cubic, 2.0 },
+ { Catrom, 2.0 },
+ { Mitchell, 2.0 },
+ { Lanczos, 3.0 },
+ { BlackmanBessel, 3.2383 },
+ { BlackmanSinc, 4.0 }
+ };
+#endif
+
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% S a m p l e I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% SampleImage() scales an image to the desired dimensions with pixel
+% sampling. Unlike other scaling methods, this method does not introduce
+% any additional color into the scaled image.
+%
+% The format of the SampleImage method is:
+%
+% Image *SampleImage(const Image *image,const unsigned long columns,
+% const unsigned long rows,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: The image.
+%
+% o columns: The number of columns in the sampled image.
+%
+% o rows: The number of rows in the sampled image.
+%
+% o exception: Return any errors or warnings in this structure.
+%
+%
+*/
+QImage SampleImage(const QImage& image,const int columns,
+ const int rows)
+{
+ int
+ *x_offset,
+ *y_offset;
+
+ long
+ j,
+ y;
+
+ uchar
+ *pixels;
+
+ register const uchar
+ *p;
+
+ register long
+ x;
+
+ register uchar
+ *q;
+
+ /*
+ Initialize sampled image attributes.
+ */
+ if ((columns == image.width()) && (rows == image.height()))
+ return image;
+ // This function is modified to handle any image depth, not only
+ // 32bit like the ImageMagick original. This avoids the relatively
+ // expensive conversion.
+ const int d = image.depth() / 8;
+ QImage sample_image( columns, rows, image.depth());
+ sample_image.setAlphaBuffer( image.hasAlphaBuffer());
+ /*
+ Allocate scan line buffer and column offset buffers.
+ */
+ pixels= new uchar[ image.width() * d ];
+ x_offset= new int[ sample_image.width() ];
+ y_offset= new int[ sample_image.height() ];
+ /*
+ Initialize pixel offsets.
+ */
+// In the following several code 0.5 needs to be added, otherwise the image
+// would be moved by half a pixel to bottom-right, just like
+// with Qt's QImage::scale()
+ for (x=0; x < (long) sample_image.width(); x++)
+ {
+ x_offset[x]=int((x+0.5)*image.width()/sample_image.width());
+ }
+ for (y=0; y < (long) sample_image.height(); y++)
+ {
+ y_offset[y]=int((y+0.5)*image.height()/sample_image.height());
+ }
+ /*
+ Sample each row.
+ */
+ j=(-1);
+ for (y=0; y < (long) sample_image.height(); y++)
+ {
+ q= sample_image.scanLine( y );
+ if (j != y_offset[y] )
+ {
+ /*
+ Read a scan line.
+ */
+ j= y_offset[y];
+ p= image.scanLine( j );
+ (void) memcpy(pixels,p,image.width()*d);
+ }
+ /*
+ Sample each column.
+ */
+ switch( d )
+ {
+ case 1: // 8bit
+ for (x=0; x < (long) sample_image.width(); x++)
+ {
+ *q++=pixels[ x_offset[x] ];
+ }
+ break;
+ case 4: // 32bit
+ for (x=0; x < (long) sample_image.width(); x++)
+ {
+ *(QRgb*)q=((QRgb*)pixels)[ x_offset[x] ];
+ q += d;
+ }
+ break;
+ default:
+ for (x=0; x < (long) sample_image.width(); x++)
+ {
+ memcpy( q, pixels + x_offset[x] * d, d );
+ q += d;
+ }
+ break;
+ }
+ }
+ if( d != 4 ) // != 32bit
+ {
+ sample_image.setNumColors( image.numColors());
+ for( int i = 0; i < image.numColors(); ++i )
+ sample_image.setColor( i, image.color( i ));
+ }
+ delete[] y_offset;
+ delete[] x_offset;
+ delete[] pixels;
+ return sample_image;
+}
+
+
+// ImageMagick code end
+
+
+// Imlib2/Mosfet code begin
+// ------------------------
+
+// This code is Imlib2 code, additionally modified by Mosfet, and with few small
+// modifications for Gwenview. The MMX scaling code also belongs to it.
+
+// The original license texts follow.
+
+/**
+ * This is the normal smoothscale method, based on Imlib2's smoothscale.
+ *
+ * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
+ * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
+ * C algorithm and it ran at about the same speed as my MMX optimized one...
+ * Finally I ported Imlib's MMX version and it ran in less than half the
+ * time as my MMX algorithm, (taking only a quarter of the time Qt does).
+ *
+ * Changes include formatting, namespaces and other C++'ings, removal of old
+ * #ifdef'ed code, and removal of unneeded border calculation code.
+ *
+ * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
+ * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
+ * (C) Daniel M. Duley.
+ */
+
+/*
+ Copyright (C) 2004 Daniel M. Duley <dan.duley@verizon.net>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+/*
+Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
+
+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 of the Software and its Copyright notices. In addition publicly
+documented acknowledgment must be given that this software has been used if no
+source code of this software is made available publicly. This includes
+acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
+documents or any documentation provided with any product containing this
+software. This License does not apply to any software that links to the
+libraries provided by this software (statically or dynamically), but only to
+the software provided.
+
+Please see the COPYING.PLAIN for a plain-english explanation of this notice
+and it's intent.
+
+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.
+*/
+
+namespace MImageScale{
+ typedef struct __mimage_scale_info
+ {
+ int *xpoints;
+ unsigned int **ypoints;
+ int *xapoints, *yapoints;
+ int xup_yup;
+ } MImageScaleInfo;
+
+ unsigned int** mimageCalcYPoints(unsigned int *src, int sow, int sh,
+ int dh);
+ int* mimageCalcXPoints(int sw, int dw);
+ int* mimageCalcApoints(int s, int d, int up);
+ MImageScaleInfo* mimageFreeScaleInfo(MImageScaleInfo *isi);
+ MImageScaleInfo *mimageCalcScaleInfo(QImage &img, int sw, int sh,
+ int dw, int dh, char aa, int sow);
+ void mimageSampleRGBA(MImageScaleInfo *isi, unsigned int *dest, int dxx,
+ int dyy, int dx, int dy, int dw, int dh, int dow);
+ void mimageScaleAARGBA(MImageScaleInfo *isi, unsigned int *dest, int dxx,
+ int dyy, int dx, int dy, int dw, int dh, int dow,
+ int sow);
+ void mimageScaleAARGB(MImageScaleInfo *isi, unsigned int *dest, int dxx,
+ int dyy, int dx, int dy, int dw, int dh, int dow, int
+ sow);
+ QImage smoothScale(const QImage& img, int dw, int dh);
+}
+
+#ifdef HAVE_X86_MMX
+extern "C" {
+ void __mimageScale_mmx_AARGBA(MImageScale::MImageScaleInfo *isi,
+ unsigned int *dest, int dxx, int dyy,
+ int dx, int dy, int dw, int dh,
+ int dow, int sow);
+}
+#endif
+
+using namespace MImageScale;
+
+QImage MImageScale::smoothScale(const QImage& image, int dw, int dh)
+{
+ QImage img = image.depth() < 32 ? image.convertDepth( 32 ) : image;
+ int w = img.width();
+ int h = img.height();
+
+ int sow = img.bytesPerLine();
+ // handle CroppedQImage
+ if( img.height() > 1 && sow != img.scanLine( 1 ) - img.scanLine( 0 ))
+ sow = img.scanLine( 1 ) - img.scanLine( 0 );
+ sow = sow / ( img.depth() / 8 );
+
+ MImageScaleInfo *scaleinfo =
+ mimageCalcScaleInfo(img, w, h, dw, dh, true, sow);
+ if(!scaleinfo)
+ return QImage();
+
+ QImage buffer(dw, dh, 32);
+ buffer.setAlphaBuffer(img.hasAlphaBuffer());
+
+#ifdef HAVE_X86_MMX
+//#warning Using MMX Smoothscale
+ bool haveMMX = KCPUInfo::haveExtension( KCPUInfo::IntelMMX );
+ if(haveMMX){
+ __mimageScale_mmx_AARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
+ 0, 0, 0, 0, dw, dh, dw, sow);
+ }
+ else
+#endif
+ {
+ if(img.hasAlphaBuffer())
+ mimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
+ 0, 0, dw, dh, dw, sow);
+ else
+ mimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
+ 0, 0, dw, dh, dw, sow);
+ }
+ mimageFreeScaleInfo(scaleinfo);
+ return(buffer);
+}
+
+//
+// Code ported from Imlib...
+//
+
+// FIXME: replace with mRed, etc... These work on pointers to pixels, not
+// pixel values
+#if BYTE_ORDER == BIG_ENDIAN
+#define A_VAL(p) ((unsigned char *)(p))[0]
+#define R_VAL(p) ((unsigned char *)(p))[1]
+#define G_VAL(p) ((unsigned char *)(p))[2]
+#define B_VAL(p) ((unsigned char *)(p))[3]
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define A_VAL(p) ((unsigned char *)(p))[3]
+#define R_VAL(p) ((unsigned char *)(p))[2]
+#define G_VAL(p) ((unsigned char *)(p))[1]
+#define B_VAL(p) ((unsigned char *)(p))[0]
+#else
+#error "BYTE_ORDER is not defined"
+#endif
+
+#define INV_XAP (256 - xapoints[x])
+#define XAP (xapoints[x])
+#define INV_YAP (256 - yapoints[dyy + y])
+#define YAP (yapoints[dyy + y])
+
+unsigned int** MImageScale::mimageCalcYPoints(unsigned int *src,
+ int sow, int sh, int dh)
+{
+ unsigned int **p;
+ int i, j = 0;
+ int val, inc, rv = 0;
+
+ if(dh < 0){
+ dh = -dh;
+ rv = 1;
+ }
+ p = new unsigned int* [dh+1];
+
+ val = 0;
+ inc = (sh << 16) / dh;
+ for(i = 0; i < dh; i++){
+ p[j++] = src + ((val >> 16) * sow);
+ val += inc;
+ }
+ if(rv){
+ for(i = dh / 2; --i >= 0; ){
+ unsigned int *tmp = p[i];
+ p[i] = p[dh - i - 1];
+ p[dh - i - 1] = tmp;
+ }
+ }
+ return(p);
+}
+
+int* MImageScale::mimageCalcXPoints(int sw, int dw)
+{
+ int *p, i, j = 0;
+ int val, inc, rv = 0;
+
+ if(dw < 0){
+ dw = -dw;
+ rv = 1;
+ }
+ p = new int[dw+1];
+
+ val = 0;
+ inc = (sw << 16) / dw;
+ for(i = 0; i < dw; i++){
+ p[j++] = (val >> 16);
+ val += inc;
+ }
+
+ if(rv){
+ for(i = dw / 2; --i >= 0; ){
+ int tmp = p[i];
+ p[i] = p[dw - i - 1];
+ p[dw - i - 1] = tmp;
+ }
+ }
+ return(p);
+}
+
+int* MImageScale::mimageCalcApoints(int s, int d, int up)
+{
+ int *p, i, j = 0, rv = 0;
+
+ if(d < 0){
+ rv = 1;
+ d = -d;
+ }
+ p = new int[d];
+
+ /* scaling up */
+ if(up){
+ int val, inc;
+
+ val = 0;
+ inc = (s << 16) / d;
+ for(i = 0; i < d; i++){
+ p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
+ if((val >> 16) >= (s - 1))
+ p[j - 1] = 0;
+ val += inc;
+ }
+ }
+ /* scaling down */
+ else{
+ int val, inc, ap, Cp;
+ val = 0;
+ inc = (s << 16) / d;
+ Cp = ((d << 14) / s) + 1;
+ for(i = 0; i < d; i++){
+ ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
+ p[j] = ap | (Cp << 16);
+ j++;
+ val += inc;
+ }
+ }
+ if(rv){
+ int tmp;
+ for(i = d / 2; --i >= 0; ){
+ tmp = p[i];
+ p[i] = p[d - i - 1];
+ p[d - i - 1] = tmp;
+ }
+ }
+ return(p);
+}
+
+MImageScaleInfo* MImageScale::mimageFreeScaleInfo(MImageScaleInfo *isi)
+{
+ if(isi){
+ delete[] isi->xpoints;
+ delete[] isi->ypoints;
+ delete[] isi->xapoints;
+ delete[] isi->yapoints;
+ delete isi;
+ }
+ return(NULL);
+}
+
+MImageScaleInfo* MImageScale::mimageCalcScaleInfo(QImage &img, int sw, int sh,
+ int dw, int dh, char aa, int sow)
+{
+ MImageScaleInfo *isi;
+ int scw, sch;
+
+ scw = dw * img.width() / sw;
+ sch = dh * img.height() / sh;
+
+ isi = new MImageScaleInfo;
+ if(!isi)
+ return(NULL);
+ memset(isi, 0, sizeof(MImageScaleInfo));
+
+ isi->xup_yup = (abs(dw) >= sw) + ((abs(dh) >= sh) << 1);
+
+ isi->xpoints = mimageCalcXPoints(img.width(), scw);
+ if(!isi->xpoints)
+ return(mimageFreeScaleInfo(isi));
+ isi->ypoints = mimageCalcYPoints((unsigned int *)img.scanLine(0),
+ sow, img.height(), sch );
+ if (!isi->ypoints)
+ return(mimageFreeScaleInfo(isi));
+ if(aa){
+ isi->xapoints = mimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
+ if(!isi->xapoints)
+ return(mimageFreeScaleInfo(isi));
+ isi->yapoints = mimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
+ if(!isi->yapoints)
+ return(mimageFreeScaleInfo(isi));
+ }
+ return(isi);
+}
+
+/* scale by pixel sampling only */
+void MImageScale::mimageSampleRGBA(MImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow)
+{
+ unsigned int *sptr, *dptr;
+ int x, y, end;
+ unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+
+ /* whats the last pixel ont he line so we stop there */
+ end = dxx + dw;
+ /* go through every scanline in the output buffer */
+ for(y = 0; y < dh; y++){
+ /* get the pointer to the start of the destination scanline */
+ dptr = dest + dx + ((y + dy) * dow);
+ /* calculate the source line we'll scan from */
+ sptr = ypoints[dyy + y];
+ /* go thru the scanline and copy across */
+ for(x = dxx; x < end; x++)
+ *dptr++ = sptr[xpoints[x]];
+ }
+}
+
+/* FIXME: NEED to optimise ScaleAARGBA - currently its "ok" but needs work*/
+
+/* scale by area sampling */
+void MImageScale::mimageScaleAARGBA(MImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ unsigned int *sptr, *dptr;
+ int x, y, end;
+ unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ end = dxx + dw;
+ /* scaling up both ways */
+ if(isi->xup_yup == 3){
+ /* go through every scanline in the output buffer */
+ for(y = 0; y < dh; y++){
+ /* calculate the source line we'll scan from */
+ dptr = dest + dx + ((y + dy) * dow);
+ sptr = ypoints[dyy + y];
+ if(YAP > 0){
+ for(x = dxx; x < end; x++){
+ int r, g, b, a;
+ int rr, gg, bb, aa;
+ unsigned int *pix;
+
+ if(XAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL(pix) * INV_XAP;
+ g = G_VAL(pix) * INV_XAP;
+ b = B_VAL(pix) * INV_XAP;
+ a = A_VAL(pix) * INV_XAP;
+ pix++;
+ r += R_VAL(pix) * XAP;
+ g += G_VAL(pix) * XAP;
+ b += B_VAL(pix) * XAP;
+ a += A_VAL(pix) * XAP;
+ pix += sow;
+ rr = R_VAL(pix) * XAP;
+ gg = G_VAL(pix) * XAP;
+ bb = B_VAL(pix) * XAP;
+ aa = A_VAL(pix) * XAP;
+ pix--;
+ rr += R_VAL(pix) * INV_XAP;
+ gg += G_VAL(pix) * INV_XAP;
+ bb += B_VAL(pix) * INV_XAP;
+ aa += A_VAL(pix) * INV_XAP;
+ r = ((rr * YAP) + (r * INV_YAP)) >> 16;
+ g = ((gg * YAP) + (g * INV_YAP)) >> 16;
+ b = ((bb * YAP) + (b * INV_YAP)) >> 16;
+ a = ((aa * YAP) + (a * INV_YAP)) >> 16;
+ *dptr++ = qRgba(r, g, b, a);
+ }
+ else{
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL(pix) * INV_YAP;
+ g = G_VAL(pix) * INV_YAP;
+ b = B_VAL(pix) * INV_YAP;
+ a = A_VAL(pix) * INV_YAP;
+ pix += sow;
+ r += R_VAL(pix) * YAP;
+ g += G_VAL(pix) * YAP;
+ b += B_VAL(pix) * YAP;
+ a += A_VAL(pix) * YAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+ a >>= 8;
+ *dptr++ = qRgba(r, g, b, a);
+ }
+ }
+ }
+ else{
+ for(x = dxx; x < end; x++){
+ int r, g, b, a;
+ unsigned int *pix;
+
+ if(XAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL(pix) * INV_XAP;
+ g = G_VAL(pix) * INV_XAP;
+ b = B_VAL(pix) * INV_XAP;
+ a = A_VAL(pix) * INV_XAP;
+ pix++;
+ r += R_VAL(pix) * XAP;
+ g += G_VAL(pix) * XAP;
+ b += B_VAL(pix) * XAP;
+ a += A_VAL(pix) * XAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+ a >>= 8;
+ *dptr++ = qRgba(r, g, b, a);
+ }
+ else
+ *dptr++ = sptr[xpoints[x] ];
+ }
+ }
+ }
+ }
+ /* if we're scaling down vertically */
+ else if(isi->xup_yup == 1){
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cy, j;
+ unsigned int *pix;
+ int r, g, b, a, rr, gg, bb, aa;
+ int yap;
+
+ /* go through every scanline in the output buffer */
+ for(y = 0; y < dh; y++){
+ Cy = YAP >> 16;
+ yap = YAP & 0xffff;
+
+ dptr = dest + dx + ((y + dy) * dow);
+ for(x = dxx; x < end; x++){
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL(pix) * yap) >> 10;
+ g = (G_VAL(pix) * yap) >> 10;
+ b = (B_VAL(pix) * yap) >> 10;
+ a = (A_VAL(pix) * yap) >> 10;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy){
+ pix += sow;
+ r += (R_VAL(pix) * Cy) >> 10;
+ g += (G_VAL(pix) * Cy) >> 10;
+ b += (B_VAL(pix) * Cy) >> 10;
+ a += (A_VAL(pix) * Cy) >> 10;
+ }
+ if(j > 0){
+ pix += sow;
+ r += (R_VAL(pix) * j) >> 10;
+ g += (G_VAL(pix) * j) >> 10;
+ b += (B_VAL(pix) * j) >> 10;
+ a += (A_VAL(pix) * j) >> 10;
+ }
+ if(XAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x] + 1;
+ rr = (R_VAL(pix) * yap) >> 10;
+ gg = (G_VAL(pix) * yap) >> 10;
+ bb = (B_VAL(pix) * yap) >> 10;
+ aa = (A_VAL(pix) * yap) >> 10;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy){
+ pix += sow;
+ rr += (R_VAL(pix) * Cy) >> 10;
+ gg += (G_VAL(pix) * Cy) >> 10;
+ bb += (B_VAL(pix) * Cy) >> 10;
+ aa += (A_VAL(pix) * Cy) >> 10;
+ }
+ if(j > 0){
+ pix += sow;
+ rr += (R_VAL(pix) * j) >> 10;
+ gg += (G_VAL(pix) * j) >> 10;
+ bb += (B_VAL(pix) * j) >> 10;
+ aa += (A_VAL(pix) * j) >> 10;
+ }
+ r = r * INV_XAP;
+ g = g * INV_XAP;
+ b = b * INV_XAP;
+ a = a * INV_XAP;
+ r = (r + ((rr * XAP))) >> 12;
+ g = (g + ((gg * XAP))) >> 12;
+ b = (b + ((bb * XAP))) >> 12;
+ a = (a + ((aa * XAP))) >> 12;
+ }
+ else{
+ r >>= 4;
+ g >>= 4;
+ b >>= 4;
+ a >>= 4;
+ }
+ *dptr = qRgba(r, g, b, a);
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally */
+ else if(isi->xup_yup == 2){
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cx, j;
+ unsigned int *pix;
+ int r, g, b, a, rr, gg, bb, aa;
+ int xap;
+
+ /* go through every scanline in the output buffer */
+ for(y = 0; y < dh; y++){
+ dptr = dest + dx + ((y + dy) * dow);
+ for(x = dxx; x < end; x++){
+ Cx = XAP >> 16;
+ xap = XAP & 0xffff;
+
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL(pix) * xap) >> 10;
+ g = (G_VAL(pix) * xap) >> 10;
+ b = (B_VAL(pix) * xap) >> 10;
+ a = (A_VAL(pix) * xap) >> 10;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx){
+ pix++;
+ r += (R_VAL(pix) * Cx) >> 10;
+ g += (G_VAL(pix) * Cx) >> 10;
+ b += (B_VAL(pix) * Cx) >> 10;
+ a += (A_VAL(pix) * Cx) >> 10;
+ }
+ if(j > 0){
+ pix++;
+ r += (R_VAL(pix) * j) >> 10;
+ g += (G_VAL(pix) * j) >> 10;
+ b += (B_VAL(pix) * j) >> 10;
+ a += (A_VAL(pix) * j) >> 10;
+ }
+ if(YAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x] + sow;
+ rr = (R_VAL(pix) * xap) >> 10;
+ gg = (G_VAL(pix) * xap) >> 10;
+ bb = (B_VAL(pix) * xap) >> 10;
+ aa = (A_VAL(pix) * xap) >> 10;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx){
+ pix++;
+ rr += (R_VAL(pix) * Cx) >> 10;
+ gg += (G_VAL(pix) * Cx) >> 10;
+ bb += (B_VAL(pix) * Cx) >> 10;
+ aa += (A_VAL(pix) * Cx) >> 10;
+ }
+ if(j > 0){
+ pix++;
+ rr += (R_VAL(pix) * j) >> 10;
+ gg += (G_VAL(pix) * j) >> 10;
+ bb += (B_VAL(pix) * j) >> 10;
+ aa += (A_VAL(pix) * j) >> 10;
+ }
+ r = r * INV_YAP;
+ g = g * INV_YAP;
+ b = b * INV_YAP;
+ a = a * INV_YAP;
+ r = (r + ((rr * YAP))) >> 12;
+ g = (g + ((gg * YAP))) >> 12;
+ b = (b + ((bb * YAP))) >> 12;
+ a = (a + ((aa * YAP))) >> 12;
+ }
+ else{
+ r >>= 4;
+ g >>= 4;
+ b >>= 4;
+ a >>= 4;
+ }
+ *dptr = qRgba(r, g, b, a);
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally & vertically */
+ else{
+ /*\ 'Correct' version, with math units prepared for MMXification:
+ |*| The operation 'b = (b * c) >> 16' translates to pmulhw,
+ |*| so the operation 'b = (b * c) >> d' would translate to
+ |*| psllw (16 - d), %mmb; pmulh %mmc, %mmb
+ \*/
+ int Cx, Cy, i, j;
+ unsigned int *pix;
+ int a, r, g, b, ax, rx, gx, bx;
+ int xap, yap;
+
+ for(y = 0; y < dh; y++){
+ Cy = YAP >> 16;
+ yap = YAP & 0xffff;
+
+ dptr = dest + dx + ((y + dy) * dow);
+ for(x = dxx; x < end; x++){
+ Cx = XAP >> 16;
+ xap = XAP & 0xffff;
+
+ sptr = ypoints[dyy + y] + xpoints[x];
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL(pix) * xap) >> 9;
+ gx = (G_VAL(pix) * xap) >> 9;
+ bx = (B_VAL(pix) * xap) >> 9;
+ ax = (A_VAL(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx){
+ rx += (R_VAL(pix) * Cx) >> 9;
+ gx += (G_VAL(pix) * Cx) >> 9;
+ bx += (B_VAL(pix) * Cx) >> 9;
+ ax += (A_VAL(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0){
+ rx += (R_VAL(pix) * i) >> 9;
+ gx += (G_VAL(pix) * i) >> 9;
+ bx += (B_VAL(pix) * i) >> 9;
+ ax += (A_VAL(pix) * i) >> 9;
+ }
+
+ r = (rx * yap) >> 14;
+ g = (gx * yap) >> 14;
+ b = (bx * yap) >> 14;
+ a = (ax * yap) >> 14;
+
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy){
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL(pix) * xap) >> 9;
+ gx = (G_VAL(pix) * xap) >> 9;
+ bx = (B_VAL(pix) * xap) >> 9;
+ ax = (A_VAL(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx){
+ rx += (R_VAL(pix) * Cx) >> 9;
+ gx += (G_VAL(pix) * Cx) >> 9;
+ bx += (B_VAL(pix) * Cx) >> 9;
+ ax += (A_VAL(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0){
+ rx += (R_VAL(pix) * i) >> 9;
+ gx += (G_VAL(pix) * i) >> 9;
+ bx += (B_VAL(pix) * i) >> 9;
+ ax += (A_VAL(pix) * i) >> 9;
+ }
+
+ r += (rx * Cy) >> 14;
+ g += (gx * Cy) >> 14;
+ b += (bx * Cy) >> 14;
+ a += (ax * Cy) >> 14;
+ }
+ if(j > 0){
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL(pix) * xap) >> 9;
+ gx = (G_VAL(pix) * xap) >> 9;
+ bx = (B_VAL(pix) * xap) >> 9;
+ ax = (A_VAL(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx){
+ rx += (R_VAL(pix) * Cx) >> 9;
+ gx += (G_VAL(pix) * Cx) >> 9;
+ bx += (B_VAL(pix) * Cx) >> 9;
+ ax += (A_VAL(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0){
+ rx += (R_VAL(pix) * i) >> 9;
+ gx += (G_VAL(pix) * i) >> 9;
+ bx += (B_VAL(pix) * i) >> 9;
+ ax += (A_VAL(pix) * i) >> 9;
+ }
+
+ r += (rx * j) >> 14;
+ g += (gx * j) >> 14;
+ b += (bx * j) >> 14;
+ a += (ax * j) >> 14;
+ }
+
+ R_VAL(dptr) = r >> 5;
+ G_VAL(dptr) = g >> 5;
+ B_VAL(dptr) = b >> 5;
+ A_VAL(dptr) = a >> 5;
+ dptr++;
+ }
+ }
+ }
+}
+
+/* scale by area sampling - IGNORE the ALPHA byte*/
+void MImageScale::mimageScaleAARGB(MImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ unsigned int *sptr, *dptr;
+ int x, y, end;
+ unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ end = dxx + dw;
+ /* scaling up both ways */
+ if(isi->xup_yup == 3){
+ /* go through every scanline in the output buffer */
+ for(y = 0; y < dh; y++){
+ /* calculate the source line we'll scan from */
+ dptr = dest + dx + ((y + dy) * dow);
+ sptr = ypoints[dyy + y];
+ if(YAP > 0){
+ for(x = dxx; x < end; x++){
+ int r = 0, g = 0, b = 0;
+ int rr = 0, gg = 0, bb = 0;
+ unsigned int *pix;
+
+ if(XAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL(pix) * INV_XAP;
+ g = G_VAL(pix) * INV_XAP;
+ b = B_VAL(pix) * INV_XAP;
+ pix++;
+ r += R_VAL(pix) * XAP;
+ g += G_VAL(pix) * XAP;
+ b += B_VAL(pix) * XAP;
+ pix += sow;
+ rr = R_VAL(pix) * XAP;
+ gg = G_VAL(pix) * XAP;
+ bb = B_VAL(pix) * XAP;
+ pix --;
+ rr += R_VAL(pix) * INV_XAP;
+ gg += G_VAL(pix) * INV_XAP;
+ bb += B_VAL(pix) * INV_XAP;
+ r = ((rr * YAP) + (r * INV_YAP)) >> 16;
+ g = ((gg * YAP) + (g * INV_YAP)) >> 16;
+ b = ((bb * YAP) + (b * INV_YAP)) >> 16;
+ *dptr++ = qRgba(r, g, b, 0xff);
+ }
+ else{
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL(pix) * INV_YAP;
+ g = G_VAL(pix) * INV_YAP;
+ b = B_VAL(pix) * INV_YAP;
+ pix += sow;
+ r += R_VAL(pix) * YAP;
+ g += G_VAL(pix) * YAP;
+ b += B_VAL(pix) * YAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+ *dptr++ = qRgba(r, g, b, 0xff);
+ }
+ }
+ }
+ else{
+ for(x = dxx; x < end; x++){
+ int r = 0, g = 0, b = 0;
+ unsigned int *pix;
+
+ if(XAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL(pix) * INV_XAP;
+ g = G_VAL(pix) * INV_XAP;
+ b = B_VAL(pix) * INV_XAP;
+ pix++;
+ r += R_VAL(pix) * XAP;
+ g += G_VAL(pix) * XAP;
+ b += B_VAL(pix) * XAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+ *dptr++ = qRgba(r, g, b, 0xff);
+ }
+ else
+ *dptr++ = sptr[xpoints[x] ];
+ }
+ }
+ }
+ }
+ /* if we're scaling down vertically */
+ else if(isi->xup_yup == 1){
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cy, j;
+ unsigned int *pix;
+ int r, g, b, rr, gg, bb;
+ int yap;
+
+ /* go through every scanline in the output buffer */
+ for(y = 0; y < dh; y++){
+ Cy = YAP >> 16;
+ yap = YAP & 0xffff;
+
+ dptr = dest + dx + ((y + dy) * dow);
+ for(x = dxx; x < end; x++){
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL(pix) * yap) >> 10;
+ g = (G_VAL(pix) * yap) >> 10;
+ b = (B_VAL(pix) * yap) >> 10;
+ pix += sow;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy){
+ r += (R_VAL(pix) * Cy) >> 10;
+ g += (G_VAL(pix) * Cy) >> 10;
+ b += (B_VAL(pix) * Cy) >> 10;
+ pix += sow;
+ }
+ if(j > 0){
+ r += (R_VAL(pix) * j) >> 10;
+ g += (G_VAL(pix) * j) >> 10;
+ b += (B_VAL(pix) * j) >> 10;
+ }
+ if(XAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x] + 1;
+ rr = (R_VAL(pix) * yap) >> 10;
+ gg = (G_VAL(pix) * yap) >> 10;
+ bb = (B_VAL(pix) * yap) >> 10;
+ pix += sow;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy){
+ rr += (R_VAL(pix) * Cy) >> 10;
+ gg += (G_VAL(pix) * Cy) >> 10;
+ bb += (B_VAL(pix) * Cy) >> 10;
+ pix += sow;
+ }
+ if(j > 0){
+ rr += (R_VAL(pix) * j) >> 10;
+ gg += (G_VAL(pix) * j) >> 10;
+ bb += (B_VAL(pix) * j) >> 10;
+ }
+ r = r * INV_XAP;
+ g = g * INV_XAP;
+ b = b * INV_XAP;
+ r = (r + ((rr * XAP))) >> 12;
+ g = (g + ((gg * XAP))) >> 12;
+ b = (b + ((bb * XAP))) >> 12;
+ }
+ else{
+ r >>= 4;
+ g >>= 4;
+ b >>= 4;
+ }
+ *dptr = qRgba(r, g, b, 0xff);
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally */
+ else if(isi->xup_yup == 2){
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cx, j;
+ unsigned int *pix;
+ int r, g, b, rr, gg, bb;
+ int xap;
+
+ /* go through every scanline in the output buffer */
+ for(y = 0; y < dh; y++){
+ dptr = dest + dx + ((y + dy) * dow);
+ for(x = dxx; x < end; x++){
+ Cx = XAP >> 16;
+ xap = XAP & 0xffff;
+
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL(pix) * xap) >> 10;
+ g = (G_VAL(pix) * xap) >> 10;
+ b = (B_VAL(pix) * xap) >> 10;
+ pix++;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx){
+ r += (R_VAL(pix) * Cx) >> 10;
+ g += (G_VAL(pix) * Cx) >> 10;
+ b += (B_VAL(pix) * Cx) >> 10;
+ pix++;
+ }
+ if(j > 0){
+ r += (R_VAL(pix) * j) >> 10;
+ g += (G_VAL(pix) * j) >> 10;
+ b += (B_VAL(pix) * j) >> 10;
+ }
+ if(YAP > 0){
+ pix = ypoints[dyy + y] + xpoints[x] + sow;
+ rr = (R_VAL(pix) * xap) >> 10;
+ gg = (G_VAL(pix) * xap) >> 10;
+ bb = (B_VAL(pix) * xap) >> 10;
+ pix++;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx){
+ rr += (R_VAL(pix) * Cx) >> 10;
+ gg += (G_VAL(pix) * Cx) >> 10;
+ bb += (B_VAL(pix) * Cx) >> 10;
+ pix++;
+ }
+ if(j > 0){
+ rr += (R_VAL(pix) * j) >> 10;
+ gg += (G_VAL(pix) * j) >> 10;
+ bb += (B_VAL(pix) * j) >> 10;
+ }
+ r = r * INV_YAP;
+ g = g * INV_YAP;
+ b = b * INV_YAP;
+ r = (r + ((rr * YAP))) >> 12;
+ g = (g + ((gg * YAP))) >> 12;
+ b = (b + ((bb * YAP))) >> 12;
+ }
+ else{
+ r >>= 4;
+ g >>= 4;
+ b >>= 4;
+ }
+ *dptr = qRgba(r, g, b, 0xff);
+ dptr++;
+ }
+ }
+ }
+ /* fully optimized (i think) - onyl change of algorithm can help */
+ /* if we're scaling down horizontally & vertically */
+ else{
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cx, Cy, i, j;
+ unsigned int *pix;
+ int r, g, b, rx, gx, bx;
+ int xap, yap;
+
+ for(y = 0; y < dh; y++){
+ Cy = YAP >> 16;
+ yap = YAP & 0xffff;
+
+ dptr = dest + dx + ((y + dy) * dow);
+ for(x = dxx; x < end; x++){
+ Cx = XAP >> 16;
+ xap = XAP & 0xffff;
+
+ sptr = ypoints[dyy + y] + xpoints[x];
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL(pix) * xap) >> 9;
+ gx = (G_VAL(pix) * xap) >> 9;
+ bx = (B_VAL(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx){
+ rx += (R_VAL(pix) * Cx) >> 9;
+ gx += (G_VAL(pix) * Cx) >> 9;
+ bx += (B_VAL(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0){
+ rx += (R_VAL(pix) * i) >> 9;
+ gx += (G_VAL(pix) * i) >> 9;
+ bx += (B_VAL(pix) * i) >> 9;
+ }
+
+ r = (rx * yap) >> 14;
+ g = (gx * yap) >> 14;
+ b = (bx * yap) >> 14;
+
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy){
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL(pix) * xap) >> 9;
+ gx = (G_VAL(pix) * xap) >> 9;
+ bx = (B_VAL(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx){
+ rx += (R_VAL(pix) * Cx) >> 9;
+ gx += (G_VAL(pix) * Cx) >> 9;
+ bx += (B_VAL(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0){
+ rx += (R_VAL(pix) * i) >> 9;
+ gx += (G_VAL(pix) * i) >> 9;
+ bx += (B_VAL(pix) * i) >> 9;
+ }
+
+ r += (rx * Cy) >> 14;
+ g += (gx * Cy) >> 14;
+ b += (bx * Cy) >> 14;
+ }
+ if(j > 0){
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL(pix) * xap) >> 9;
+ gx = (G_VAL(pix) * xap) >> 9;
+ bx = (B_VAL(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx){
+ rx += (R_VAL(pix) * Cx) >> 9;
+ gx += (G_VAL(pix) * Cx) >> 9;
+ bx += (B_VAL(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0){
+ rx += (R_VAL(pix) * i) >> 9;
+ gx += (G_VAL(pix) * i) >> 9;
+ bx += (B_VAL(pix) * i) >> 9;
+ }
+
+ r += (rx * j) >> 14;
+ g += (gx * j) >> 14;
+ b += (bx * j) >> 14;
+ }
+
+ R_VAL(dptr) = r >> 5;
+ G_VAL(dptr) = g >> 5;
+ B_VAL(dptr) = b >> 5;
+ dptr++;
+ }
+ }
+ }
+}
+
+// Imlib2/Mosfet code end
+
+
+// public functions :
+// ------------------
+
+// This function returns how many pixels around the zoomed area should be
+// included in the image. This is used when doing incremental painting, because
+// some smoothing algorithms use surrounding pixels and not including them
+// could sometimes make the edges between incremental steps visible.
+// int extraScalePixels( SmoothAlgorithm alg, double zoom, double blur )
+// {
+// double filtersupport = 0;
+// Filter filter = NULL;
+// switch( alg ) {
+// case SMOOTH_NONE:
+// filter = NULL;
+// filtersupport = 0.0;
+// break;
+// case SMOOTH_FAST:
+// filter = Box;
+// filtersupport = 0.5;
+// break;
+// case SMOOTH_NORMAL:
+// filter = Triangle;
+// filtersupport = 1.0;
+// break;
+// case SMOOTH_BEST:
+// // filter = Mitchell;
+// filter = Bicubic;
+// filtersupport = 2.0;
+// break;
+// }
+// if( zoom == 1.0 || filtersupport == 0.0 ) return 0;
+// // Imlib2/Mosfet scale - I have really no idea how many pixels it needs
+// if( filter == Box && blur == 1.0 ) return int( 3 / zoom + 1 );
+// // This is support size for ImageMagick's scaling.
+// double scale=blur*QMAX(1.0/zoom,1.0);
+// double support=scale* filtersupport;
+// if (support <= 0.5) support=0.5+0.000001;
+// return int( support + 1 );
+// }
+
+QImage scale(const QImage& image, int width, int height,
+ SmoothAlgorithm alg, QImage::ScaleMode mode, double blur )
+{
+ if( image.isNull()) return image.copy();
+
+ QSize newSize( image.size() );
+ newSize.scale( QSize( width, height ), (QSize::ScaleMode)mode ); // ### remove cast in Qt 4.0
+ newSize = newSize.expandedTo( QSize( 1, 1 )); // make sure it doesn't become null
+
+ if ( newSize == image.size() ) return image.copy();
+
+ width = newSize.width();
+ height = newSize.height();
+ Filter filter = NULL;
+ fastfloat filtersupport;
+
+ switch( alg ) {
+ case SMOOTH_NONE:
+ filter = NULL;
+ filtersupport = 0.0;
+ break;
+ case SMOOTH_FAST:
+ filter = Box;
+ filtersupport = 0.5;
+ break;
+ case SMOOTH_NORMAL:
+ default:
+ filter = Triangle;
+ filtersupport = 1.0;
+ break;
+ case SMOOTH_BEST:
+// filter = Mitchell;
+ filter = Bicubic;
+ filtersupport = 2.0;
+ break;
+ }
+
+ if( filter == Box && blur == 1.0 )
+ return MImageScale::smoothScale( image, width, height );
+
+ if( filter == Box && width > image.width() && height > image.height() && blur == 1.0 ) {
+ filter = NULL; // Box doesn't really smooth when enlarging
+ }
+
+ if( filter == NULL ) {
+ return SampleImage( image, width, height ); // doesn't need 32bit
+ }
+
+ return ResizeImage( image.convertDepth( 32 ), width, height, filter, filtersupport, blur );
+ // unlike Qt's smoothScale() this function introduces new colors to grayscale images ... oh well
+}
+
+
+} // namespace
diff --git a/src/fastscale/scale.h b/src/fastscale/scale.h
new file mode 100644
index 0000000..299ac16
--- /dev/null
+++ b/src/fastscale/scale.h
@@ -0,0 +1,34 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab
+/*
+Gwenview - A simple image viewer for KDE
+Copyright 2000-2004 Aurlien Gteau
+
+ 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 FAST_SCALE_H
+#define FAST_SCALE_H
+
+// Qt
+#include <qimage.h>
+
+namespace ImageUtils {
+ enum SmoothAlgorithm { SMOOTH_NONE, SMOOTH_FAST, SMOOTH_NORMAL, SMOOTH_BEST };
+
+ QImage scale(const QImage& image, int width, int height,
+ SmoothAlgorithm alg, QImage::ScaleMode mode = QImage::ScaleFree, double blur = 1.0);
+}
+
+#endif
diff --git a/src/icons/Makefile.am b/src/icons/Makefile.am
new file mode 100644
index 0000000..c7abccf
--- /dev/null
+++ b/src/icons/Makefile.am
@@ -0,0 +1,2 @@
+KDE_ICON = AUTO
+SUBDIRS = actions
diff --git a/src/icons/actions/Makefile.am b/src/icons/actions/Makefile.am
new file mode 100644
index 0000000..a8f669e
--- /dev/null
+++ b/src/icons/actions/Makefile.am
@@ -0,0 +1,2 @@
+k3bicondir = $(kde_datadir)/k3b/icons
+k3bicon_ICON = AUTO
diff --git a/src/icons/actions/cr16-action-greenled.png b/src/icons/actions/cr16-action-greenled.png
new file mode 100644
index 0000000..bf2a36c
--- /dev/null
+++ b/src/icons/actions/cr16-action-greenled.png
Binary files differ
diff --git a/src/icons/actions/cr16-action-redled.png b/src/icons/actions/cr16-action-redled.png
new file mode 100644
index 0000000..04db8ff
--- /dev/null
+++ b/src/icons/actions/cr16-action-redled.png
Binary files differ
diff --git a/src/icons/actions/cr16-action-yellowinfo.png b/src/icons/actions/cr16-action-yellowinfo.png
new file mode 100644
index 0000000..5a464f3
--- /dev/null
+++ b/src/icons/actions/cr16-action-yellowinfo.png
Binary files differ
diff --git a/src/icons/actions/cr16-action-yellowled.png b/src/icons/actions/cr16-action-yellowled.png
new file mode 100644
index 0000000..a0e8f87
--- /dev/null
+++ b/src/icons/actions/cr16-action-yellowled.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-audiocd.png b/src/icons/actions/hi16-action-audiocd.png
new file mode 100644
index 0000000..d452cdc
--- /dev/null
+++ b/src/icons/actions/hi16-action-audiocd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-burn_cdimage.png b/src/icons/actions/hi16-action-burn_cdimage.png
new file mode 100644
index 0000000..b9821b3
--- /dev/null
+++ b/src/icons/actions/hi16-action-burn_cdimage.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-burn_dvdimage.png b/src/icons/actions/hi16-action-burn_dvdimage.png
new file mode 100644
index 0000000..28a8fbc
--- /dev/null
+++ b/src/icons/actions/hi16-action-burn_dvdimage.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-cdburn.png b/src/icons/actions/hi16-action-cdburn.png
new file mode 100644
index 0000000..4e1e406
--- /dev/null
+++ b/src/icons/actions/hi16-action-cdburn.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-cdcopy.png b/src/icons/actions/hi16-action-cdcopy.png
new file mode 100644
index 0000000..49a7505
--- /dev/null
+++ b/src/icons/actions/hi16-action-cdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-cddarip.png b/src/icons/actions/hi16-action-cddarip.png
new file mode 100644
index 0000000..ab28c17
--- /dev/null
+++ b/src/icons/actions/hi16-action-cddarip.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-datacd.png b/src/icons/actions/hi16-action-datacd.png
new file mode 100644
index 0000000..a0cd3a7
--- /dev/null
+++ b/src/icons/actions/hi16-action-datacd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-datadvd.png b/src/icons/actions/hi16-action-datadvd.png
new file mode 100644
index 0000000..78fa410
--- /dev/null
+++ b/src/icons/actions/hi16-action-datadvd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-dvdcopy.png b/src/icons/actions/hi16-action-dvdcopy.png
new file mode 100644
index 0000000..52012d0
--- /dev/null
+++ b/src/icons/actions/hi16-action-dvdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-emovix.png b/src/icons/actions/hi16-action-emovix.png
new file mode 100644
index 0000000..5242645
--- /dev/null
+++ b/src/icons/actions/hi16-action-emovix.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-erasecd.png b/src/icons/actions/hi16-action-erasecd.png
new file mode 100644
index 0000000..1d08a42
--- /dev/null
+++ b/src/icons/actions/hi16-action-erasecd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-formatdvd.png b/src/icons/actions/hi16-action-formatdvd.png
new file mode 100644
index 0000000..ecc8153
--- /dev/null
+++ b/src/icons/actions/hi16-action-formatdvd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-mixedcd.png b/src/icons/actions/hi16-action-mixedcd.png
new file mode 100644
index 0000000..514bb3e
--- /dev/null
+++ b/src/icons/actions/hi16-action-mixedcd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-mp3cd.png b/src/icons/actions/hi16-action-mp3cd.png
new file mode 100644
index 0000000..378d072
--- /dev/null
+++ b/src/icons/actions/hi16-action-mp3cd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-musicbrainz.png b/src/icons/actions/hi16-action-musicbrainz.png
new file mode 100644
index 0000000..0608908
--- /dev/null
+++ b/src/icons/actions/hi16-action-musicbrainz.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-videocd.png b/src/icons/actions/hi16-action-videocd.png
new file mode 100644
index 0000000..b9e8c18
--- /dev/null
+++ b/src/icons/actions/hi16-action-videocd.png
Binary files differ
diff --git a/src/icons/actions/hi16-action-videodvd.png b/src/icons/actions/hi16-action-videodvd.png
new file mode 100644
index 0000000..8bb3470
--- /dev/null
+++ b/src/icons/actions/hi16-action-videodvd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-audiocd.png b/src/icons/actions/hi22-action-audiocd.png
new file mode 100644
index 0000000..46762b4
--- /dev/null
+++ b/src/icons/actions/hi22-action-audiocd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-burn_cdimage.png b/src/icons/actions/hi22-action-burn_cdimage.png
new file mode 100644
index 0000000..f5e1b0d
--- /dev/null
+++ b/src/icons/actions/hi22-action-burn_cdimage.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-burn_dvdimage.png b/src/icons/actions/hi22-action-burn_dvdimage.png
new file mode 100644
index 0000000..6e6b94b
--- /dev/null
+++ b/src/icons/actions/hi22-action-burn_dvdimage.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-cdburn.png b/src/icons/actions/hi22-action-cdburn.png
new file mode 100644
index 0000000..7862d9e
--- /dev/null
+++ b/src/icons/actions/hi22-action-cdburn.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-cdcopy.png b/src/icons/actions/hi22-action-cdcopy.png
new file mode 100644
index 0000000..0269b7e
--- /dev/null
+++ b/src/icons/actions/hi22-action-cdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-cddarip.png b/src/icons/actions/hi22-action-cddarip.png
new file mode 100644
index 0000000..6bbc468
--- /dev/null
+++ b/src/icons/actions/hi22-action-cddarip.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-datacd.png b/src/icons/actions/hi22-action-datacd.png
new file mode 100644
index 0000000..cfc2e69
--- /dev/null
+++ b/src/icons/actions/hi22-action-datacd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-datadvd.png b/src/icons/actions/hi22-action-datadvd.png
new file mode 100644
index 0000000..c1cb979
--- /dev/null
+++ b/src/icons/actions/hi22-action-datadvd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-dvdcopy.png b/src/icons/actions/hi22-action-dvdcopy.png
new file mode 100644
index 0000000..b05714c
--- /dev/null
+++ b/src/icons/actions/hi22-action-dvdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-emovix.png b/src/icons/actions/hi22-action-emovix.png
new file mode 100644
index 0000000..04f6478
--- /dev/null
+++ b/src/icons/actions/hi22-action-emovix.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-erasecd.png b/src/icons/actions/hi22-action-erasecd.png
new file mode 100644
index 0000000..6619f67
--- /dev/null
+++ b/src/icons/actions/hi22-action-erasecd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-formatdvd.png b/src/icons/actions/hi22-action-formatdvd.png
new file mode 100644
index 0000000..8d419f4
--- /dev/null
+++ b/src/icons/actions/hi22-action-formatdvd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-mixedcd.png b/src/icons/actions/hi22-action-mixedcd.png
new file mode 100644
index 0000000..13cbf7f
--- /dev/null
+++ b/src/icons/actions/hi22-action-mixedcd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-mp3cd.png b/src/icons/actions/hi22-action-mp3cd.png
new file mode 100644
index 0000000..653129d
--- /dev/null
+++ b/src/icons/actions/hi22-action-mp3cd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-videocd.png b/src/icons/actions/hi22-action-videocd.png
new file mode 100644
index 0000000..0ebe179
--- /dev/null
+++ b/src/icons/actions/hi22-action-videocd.png
Binary files differ
diff --git a/src/icons/actions/hi22-action-videodvd.png b/src/icons/actions/hi22-action-videodvd.png
new file mode 100644
index 0000000..6ca9619
--- /dev/null
+++ b/src/icons/actions/hi22-action-videodvd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-audiocd.png b/src/icons/actions/hi32-action-audiocd.png
new file mode 100644
index 0000000..6509ef7
--- /dev/null
+++ b/src/icons/actions/hi32-action-audiocd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-burn_cdimage.png b/src/icons/actions/hi32-action-burn_cdimage.png
new file mode 100644
index 0000000..5bdcbf0
--- /dev/null
+++ b/src/icons/actions/hi32-action-burn_cdimage.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-burn_dvdimage.png b/src/icons/actions/hi32-action-burn_dvdimage.png
new file mode 100644
index 0000000..647d9b1
--- /dev/null
+++ b/src/icons/actions/hi32-action-burn_dvdimage.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-cdburn.png b/src/icons/actions/hi32-action-cdburn.png
new file mode 100644
index 0000000..3150417
--- /dev/null
+++ b/src/icons/actions/hi32-action-cdburn.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-cdcopy.png b/src/icons/actions/hi32-action-cdcopy.png
new file mode 100644
index 0000000..4c650ce
--- /dev/null
+++ b/src/icons/actions/hi32-action-cdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-cddarip.png b/src/icons/actions/hi32-action-cddarip.png
new file mode 100644
index 0000000..e0af956
--- /dev/null
+++ b/src/icons/actions/hi32-action-cddarip.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-datacd.png b/src/icons/actions/hi32-action-datacd.png
new file mode 100644
index 0000000..fec1dd3
--- /dev/null
+++ b/src/icons/actions/hi32-action-datacd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-datadvd.png b/src/icons/actions/hi32-action-datadvd.png
new file mode 100644
index 0000000..730fdb0
--- /dev/null
+++ b/src/icons/actions/hi32-action-datadvd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-dvdcopy.png b/src/icons/actions/hi32-action-dvdcopy.png
new file mode 100644
index 0000000..0ffc7b9
--- /dev/null
+++ b/src/icons/actions/hi32-action-dvdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-emovix.png b/src/icons/actions/hi32-action-emovix.png
new file mode 100644
index 0000000..779159e
--- /dev/null
+++ b/src/icons/actions/hi32-action-emovix.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-erasecd.png b/src/icons/actions/hi32-action-erasecd.png
new file mode 100644
index 0000000..e699d07
--- /dev/null
+++ b/src/icons/actions/hi32-action-erasecd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-formatdvd.png b/src/icons/actions/hi32-action-formatdvd.png
new file mode 100644
index 0000000..4e4c044
--- /dev/null
+++ b/src/icons/actions/hi32-action-formatdvd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-mixedcd.png b/src/icons/actions/hi32-action-mixedcd.png
new file mode 100644
index 0000000..7f842c8
--- /dev/null
+++ b/src/icons/actions/hi32-action-mixedcd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-mp3cd.png b/src/icons/actions/hi32-action-mp3cd.png
new file mode 100644
index 0000000..98a9787
--- /dev/null
+++ b/src/icons/actions/hi32-action-mp3cd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-videocd.png b/src/icons/actions/hi32-action-videocd.png
new file mode 100644
index 0000000..93b5838
--- /dev/null
+++ b/src/icons/actions/hi32-action-videocd.png
Binary files differ
diff --git a/src/icons/actions/hi32-action-videodvd.png b/src/icons/actions/hi32-action-videodvd.png
new file mode 100644
index 0000000..3b1ed2d
--- /dev/null
+++ b/src/icons/actions/hi32-action-videodvd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-audiocd.png b/src/icons/actions/hi48-action-audiocd.png
new file mode 100644
index 0000000..a609713
--- /dev/null
+++ b/src/icons/actions/hi48-action-audiocd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-burn_cdimage.png b/src/icons/actions/hi48-action-burn_cdimage.png
new file mode 100644
index 0000000..1d91604
--- /dev/null
+++ b/src/icons/actions/hi48-action-burn_cdimage.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-burn_dvdimage.png b/src/icons/actions/hi48-action-burn_dvdimage.png
new file mode 100644
index 0000000..36d24a6
--- /dev/null
+++ b/src/icons/actions/hi48-action-burn_dvdimage.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-cdburn.png b/src/icons/actions/hi48-action-cdburn.png
new file mode 100644
index 0000000..d4c8c7b
--- /dev/null
+++ b/src/icons/actions/hi48-action-cdburn.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-cdcopy.png b/src/icons/actions/hi48-action-cdcopy.png
new file mode 100644
index 0000000..a2ca951
--- /dev/null
+++ b/src/icons/actions/hi48-action-cdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-cddarip.png b/src/icons/actions/hi48-action-cddarip.png
new file mode 100644
index 0000000..d21b6f0
--- /dev/null
+++ b/src/icons/actions/hi48-action-cddarip.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-datacd.png b/src/icons/actions/hi48-action-datacd.png
new file mode 100644
index 0000000..77740bb
--- /dev/null
+++ b/src/icons/actions/hi48-action-datacd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-datadvd.png b/src/icons/actions/hi48-action-datadvd.png
new file mode 100644
index 0000000..12e2ae6
--- /dev/null
+++ b/src/icons/actions/hi48-action-datadvd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-dvdcopy.png b/src/icons/actions/hi48-action-dvdcopy.png
new file mode 100644
index 0000000..c2b39ef
--- /dev/null
+++ b/src/icons/actions/hi48-action-dvdcopy.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-emovix.png b/src/icons/actions/hi48-action-emovix.png
new file mode 100644
index 0000000..cec838a
--- /dev/null
+++ b/src/icons/actions/hi48-action-emovix.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-erasecd.png b/src/icons/actions/hi48-action-erasecd.png
new file mode 100644
index 0000000..8a47870
--- /dev/null
+++ b/src/icons/actions/hi48-action-erasecd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-formatdvd.png b/src/icons/actions/hi48-action-formatdvd.png
new file mode 100644
index 0000000..1f536f1
--- /dev/null
+++ b/src/icons/actions/hi48-action-formatdvd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-mixedcd.png b/src/icons/actions/hi48-action-mixedcd.png
new file mode 100644
index 0000000..77e2202
--- /dev/null
+++ b/src/icons/actions/hi48-action-mixedcd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-mp3cd.png b/src/icons/actions/hi48-action-mp3cd.png
new file mode 100644
index 0000000..665e431
--- /dev/null
+++ b/src/icons/actions/hi48-action-mp3cd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-videocd.png b/src/icons/actions/hi48-action-videocd.png
new file mode 100644
index 0000000..55bccd4
--- /dev/null
+++ b/src/icons/actions/hi48-action-videocd.png
Binary files differ
diff --git a/src/icons/actions/hi48-action-videodvd.png b/src/icons/actions/hi48-action-videodvd.png
new file mode 100644
index 0000000..2078bec
--- /dev/null
+++ b/src/icons/actions/hi48-action-videodvd.png
Binary files differ
diff --git a/src/icons/actions/hi64-action-musicbrainz.png b/src/icons/actions/hi64-action-musicbrainz.png
new file mode 100644
index 0000000..f5074c6
--- /dev/null
+++ b/src/icons/actions/hi64-action-musicbrainz.png
Binary files differ
diff --git a/src/icons/actions/hisc-action-audiocd.svgz b/src/icons/actions/hisc-action-audiocd.svgz
new file mode 100644
index 0000000..cb05f70
--- /dev/null
+++ b/src/icons/actions/hisc-action-audiocd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-burn_cdimage.svgz b/src/icons/actions/hisc-action-burn_cdimage.svgz
new file mode 100644
index 0000000..b0a8fde
--- /dev/null
+++ b/src/icons/actions/hisc-action-burn_cdimage.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-burn_dvdimage.svgz b/src/icons/actions/hisc-action-burn_dvdimage.svgz
new file mode 100644
index 0000000..b89af60
--- /dev/null
+++ b/src/icons/actions/hisc-action-burn_dvdimage.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-cdburn.svgz b/src/icons/actions/hisc-action-cdburn.svgz
new file mode 100644
index 0000000..014f1b8
--- /dev/null
+++ b/src/icons/actions/hisc-action-cdburn.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-cdcopy.svgz b/src/icons/actions/hisc-action-cdcopy.svgz
new file mode 100644
index 0000000..9143b8d
--- /dev/null
+++ b/src/icons/actions/hisc-action-cdcopy.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-cddarip.svgz b/src/icons/actions/hisc-action-cddarip.svgz
new file mode 100644
index 0000000..2a86c86
--- /dev/null
+++ b/src/icons/actions/hisc-action-cddarip.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-datacd.svgz b/src/icons/actions/hisc-action-datacd.svgz
new file mode 100644
index 0000000..e2f0f2a
--- /dev/null
+++ b/src/icons/actions/hisc-action-datacd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-datadvd.svgz b/src/icons/actions/hisc-action-datadvd.svgz
new file mode 100644
index 0000000..332b73c
--- /dev/null
+++ b/src/icons/actions/hisc-action-datadvd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-dvdcopy.svgz b/src/icons/actions/hisc-action-dvdcopy.svgz
new file mode 100644
index 0000000..b8efe33
--- /dev/null
+++ b/src/icons/actions/hisc-action-dvdcopy.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-emovix.svgz b/src/icons/actions/hisc-action-emovix.svgz
new file mode 100644
index 0000000..5053e3d
--- /dev/null
+++ b/src/icons/actions/hisc-action-emovix.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-erasecd.svgz b/src/icons/actions/hisc-action-erasecd.svgz
new file mode 100644
index 0000000..7a99c82
--- /dev/null
+++ b/src/icons/actions/hisc-action-erasecd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-formatdvd.svgz b/src/icons/actions/hisc-action-formatdvd.svgz
new file mode 100644
index 0000000..33e4877
--- /dev/null
+++ b/src/icons/actions/hisc-action-formatdvd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-mixedcd.svgz b/src/icons/actions/hisc-action-mixedcd.svgz
new file mode 100644
index 0000000..fa10365
--- /dev/null
+++ b/src/icons/actions/hisc-action-mixedcd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-mp3cd.svgz b/src/icons/actions/hisc-action-mp3cd.svgz
new file mode 100644
index 0000000..5142c80
--- /dev/null
+++ b/src/icons/actions/hisc-action-mp3cd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-videocd.svgz b/src/icons/actions/hisc-action-videocd.svgz
new file mode 100644
index 0000000..9af309f
--- /dev/null
+++ b/src/icons/actions/hisc-action-videocd.svgz
Binary files differ
diff --git a/src/icons/actions/hisc-action-videodvd.svgz b/src/icons/actions/hisc-action-videodvd.svgz
new file mode 100644
index 0000000..1ec5b1f
--- /dev/null
+++ b/src/icons/actions/hisc-action-videodvd.svgz
Binary files differ
diff --git a/src/icons/hi128-app-k3b.png b/src/icons/hi128-app-k3b.png
new file mode 100644
index 0000000..278d6b1
--- /dev/null
+++ b/src/icons/hi128-app-k3b.png
Binary files differ
diff --git a/src/icons/hi16-app-k3b.png b/src/icons/hi16-app-k3b.png
new file mode 100644
index 0000000..7891dc0
--- /dev/null
+++ b/src/icons/hi16-app-k3b.png
Binary files differ
diff --git a/src/icons/hi22-app-k3b.png b/src/icons/hi22-app-k3b.png
new file mode 100644
index 0000000..43bf2f2
--- /dev/null
+++ b/src/icons/hi22-app-k3b.png
Binary files differ
diff --git a/src/icons/hi32-app-k3b.png b/src/icons/hi32-app-k3b.png
new file mode 100644
index 0000000..5c1cd8e
--- /dev/null
+++ b/src/icons/hi32-app-k3b.png
Binary files differ
diff --git a/src/icons/hi48-app-k3b.png b/src/icons/hi48-app-k3b.png
new file mode 100644
index 0000000..04c40a1
--- /dev/null
+++ b/src/icons/hi48-app-k3b.png
Binary files differ
diff --git a/src/icons/hi64-app-k3b.png b/src/icons/hi64-app-k3b.png
new file mode 100644
index 0000000..f1354cb
--- /dev/null
+++ b/src/icons/hi64-app-k3b.png
Binary files differ
diff --git a/src/k3b-cue.desktop b/src/k3b-cue.desktop
new file mode 100644
index 0000000..e1743f6
--- /dev/null
+++ b/src/k3b-cue.desktop
@@ -0,0 +1,14 @@
+# KDE Config File
+[Desktop Entry]
+Type=Application
+NoDisplay=true
+Exec=k3b --cdimage %U
+Icon=k3b
+Terminal=false
+Name=K3b
+Name[ar]= K3b
+Name[bn]=কে-থ্রি-বি
+Name[hi]=के3बी
+MimeType=application/x-cue;
+
+Encoding=UTF-8
diff --git a/src/k3b-iso.desktop b/src/k3b-iso.desktop
new file mode 100644
index 0000000..ff97f3e
--- /dev/null
+++ b/src/k3b-iso.desktop
@@ -0,0 +1,13 @@
+# KDE Config File
+[Desktop Entry]
+Type=Application
+NoDisplay=true
+Exec=k3b --image %U
+Icon=k3b
+Terminal=false
+Name=K3b
+Name[ar]= K3b
+Name[bn]=কে-থ্রি-বি
+Name[hi]=के3बी
+MimeType=application/x-iso;
+Encoding=UTF-8
diff --git a/src/k3b.cpp b/src/k3b.cpp
new file mode 100644
index 0000000..23a5cd6
--- /dev/null
+++ b/src/k3b.cpp
@@ -0,0 +1,1630 @@
+/*
+ *
+ * $Id: k3b.cpp 642063 2007-03-13 09:40:13Z trueg $
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+
+// include files for QT
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+#include <qtoolbutton.h>
+#include <qstring.h>
+#include <qsplitter.h>
+#include <qevent.h>
+#include <qvaluelist.h>
+#include <qfont.h>
+#include <qpalette.h>
+#include <qwidgetstack.h>
+#include <qtimer.h>
+
+#include <kdockwidget.h>
+#include <kkeydialog.h>
+// include files for KDE
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kmenubar.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kstdaction.h>
+#include <klineeditdlg.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+#include <kurl.h>
+#include <kurllabel.h>
+#include <ktoolbar.h>
+#include <kstatusbar.h>
+#include <kglobalsettings.h>
+#include <kdialog.h>
+#include <kedittoolbar.h>
+#include <ksystemtray.h>
+#include <kaboutdata.h>
+#include <ktip.h>
+#include <kxmlguifactory.h>
+#include <kstdguiitem.h>
+#include <kio/global.h>
+#include <kio/netaccess.h>
+#include <krecentdocument.h>
+
+#include <stdlib.h>
+
+// application specific includes
+#include "k3b.h"
+#include "k3bapplication.h"
+#include <k3bglobals.h>
+#include "k3bview.h"
+#include "k3bdirview.h"
+#include <k3baudiodoc.h>
+#include "k3baudioview.h"
+#include "k3bappdevicemanager.h"
+#include "k3baudiotrackdialog.h"
+#include "option/k3boptiondialog.h"
+#include "k3bprojectburndialog.h"
+#include <k3bdatadoc.h>
+#include "k3bdataview.h"
+#include <k3bdvddoc.h>
+#include "k3bdvdview.h"
+#include <k3bvideodvddoc.h>
+#include "k3bvideodvdview.h"
+#include <k3bmixeddoc.h>
+#include "k3bmixedview.h"
+#include <k3bvcddoc.h>
+#include "k3bvcdview.h"
+#include <k3bmovixdoc.h>
+#include "k3bmovixview.h"
+#include <k3bmovixdvddoc.h>
+#include "k3bmovixdvdview.h"
+#include "misc/k3bblankingdialog.h"
+#include "misc/k3bcdimagewritingdialog.h"
+#include "misc/k3bisoimagewritingdialog.h"
+#include <k3bexternalbinmanager.h>
+#include "k3bprojecttabwidget.h"
+#include "misc/k3bcdcopydialog.h"
+#include "k3btempdirselectionwidget.h"
+#include "k3bstatusbarmanager.h"
+#include "k3bfiletreecombobox.h"
+#include "k3bfiletreeview.h"
+#include "k3bsidepanel.h"
+#include "k3bstdguiitems.h"
+#include "misc/k3bdvdformattingdialog.h"
+#include "misc/k3bdvdcopydialog.h"
+//#include "dvdcopy/k3bvideodvdcopydialog.h"
+#include "k3bprojectmanager.h"
+#include "k3bwelcomewidget.h"
+#include <k3bpluginmanager.h>
+#include <k3bplugin.h>
+#include "k3bsystemproblemdialog.h"
+#include <k3baudiodecoder.h>
+#include <k3bthememanager.h>
+#include <k3biso9660.h>
+#include <k3bcuefileparser.h>
+#include <k3bdeviceselectiondialog.h>
+#include <k3bjob.h>
+#include <k3bsignalwaiter.h>
+#include "k3bmediaselectiondialog.h"
+#include "k3bmediacache.h"
+#include "k3bmedium.h"
+#include "projects/k3bdatasessionimportdialog.h"
+#include "k3bpassivepopup.h"
+#include "k3bthemedheader.h"
+#include <k3baudioserver.h>
+
+
+class K3bMainWindow::Private
+{
+public:
+ K3bDoc* lastDoc;
+
+ QWidgetStack* documentStack;
+ K3bWelcomeWidget* welcomeWidget;
+ QWidget* documentHull;
+
+ QLabel* leftDocPicLabel;
+ QLabel* centerDocLabel;
+ QLabel* rightDocPicLabel;
+};
+
+
+K3bMainWindow::K3bMainWindow()
+ : DockMainWindow(0,"K3bMainwindow")
+{
+ //setup splitter behavior
+ manager()->setSplitterHighResolution(true);
+ manager()->setSplitterOpaqueResize(true);
+ manager()->setSplitterKeepSize(true);
+
+ d = new Private;
+ d->lastDoc = 0;
+
+ setPlainCaption( i18n("K3b - The CD and DVD Kreator") );
+
+ m_config = kapp->config();
+
+ ///////////////////////////////////////////////////////////////////
+ // call inits to invoke all other construction parts
+ initActions();
+ initView();
+ initStatusBar();
+ createGUI(0L);
+
+ // we need the actions for the welcomewidget
+ d->welcomeWidget->loadConfig( config() );
+
+ // fill the tabs action menu
+ m_documentTab->insertAction( actionFileSave );
+ m_documentTab->insertAction( actionFileSaveAs );
+ m_documentTab->insertAction( actionFileClose );
+
+ // /////////////////////////////////////////////////////////////////
+ // disable actions at startup
+ slotStateChanged( "state_project_active", KXMLGUIClient::StateReverse );
+
+ connect( k3bappcore->projectManager(), SIGNAL(newProject(K3bDoc*)), this, SLOT(createClient(K3bDoc*)) );
+ connect( k3bcore->deviceManager(), SIGNAL(changed()), this, SLOT(slotCheckSystemTimed()) );
+ connect( K3bAudioServer::instance(), SIGNAL(error(const QString&)), this, SLOT(slotAudioServerError(const QString&)) );
+
+ // FIXME: now make sure the welcome screen is displayed completely
+ resize( 780, 550 );
+// getMainDockWidget()->resize( getMainDockWidget()->size().expandedTo( d->welcomeWidget->sizeHint() ) );
+// m_dirTreeDock->resize( QSize( m_dirTreeDock->sizeHint().width(), m_dirTreeDock->height() ) );
+
+ readOptions();
+}
+
+K3bMainWindow::~K3bMainWindow()
+{
+ delete mainDock;
+ delete m_contentsDock;
+
+ delete d;
+}
+
+
+void K3bMainWindow::showEvent( QShowEvent* e )
+{
+ slotCheckDockWidgetStatus();
+ KDockMainWindow::showEvent( e );
+}
+
+
+void K3bMainWindow::initActions()
+{
+ // merge in the device actions from the device manager
+ // operator+= is deprecated but I know no other way to do this. Why does the KDE app framework
+ // need to have all actions in the mainwindow's actioncollection anyway (or am I just to stupid to
+ // see the correct solution?)
+ *actionCollection() += *k3bappcore->appDeviceManager()->actionCollection();
+
+ actionFileOpen = KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
+ actionFileOpenRecent = KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)), actionCollection());
+ actionFileSave = KStdAction::save(this, SLOT(slotFileSave()), actionCollection());
+ actionFileSaveAs = KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
+ actionFileSaveAll = new KAction( i18n("Save All"), "save_all", 0, this, SLOT(slotFileSaveAll()),
+ actionCollection(), "file_save_all" );
+ actionFileClose = KStdAction::close(this, SLOT(slotFileClose()), actionCollection());
+ actionFileCloseAll = new KAction( i18n("Close All"), 0, 0, this, SLOT(slotFileCloseAll()),
+ actionCollection(), "file_close_all" );
+ actionFileQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
+ actionViewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection());
+ actionSettingsConfigure = KStdAction::preferences(this, SLOT(slotSettingsConfigure()), actionCollection() );
+
+ // the tip action
+ (void)KStdAction::tipOfDay(this, SLOT(slotShowTips()), actionCollection() );
+ (void)KStdAction::keyBindings( this, SLOT( slotConfigureKeys() ), actionCollection() );
+
+ KStdAction::configureToolbars(this, SLOT(slotEditToolbars()), actionCollection());
+ setStandardToolBarMenuEnabled(true);
+ KStdAction::showMenubar( this, SLOT(slotShowMenuBar()), actionCollection() );
+
+ actionFileNewMenu = new KActionMenu( i18n("&New Project"), "filenew", actionCollection(), "file_new" );
+ actionFileNewAudio = new KAction(i18n("New &Audio CD Project"), "audiocd", 0, this, SLOT(slotNewAudioDoc()),
+ actionCollection(), "file_new_audio");
+ actionFileNewData = new KAction(i18n("New Data &CD Project"), "datacd", 0, this, SLOT(slotNewDataDoc()),
+ actionCollection(), "file_new_data");
+ actionFileNewMixed = new KAction(i18n("New &Mixed Mode CD Project"), "mixedcd", 0, this, SLOT(slotNewMixedDoc()),
+ actionCollection(), "file_new_mixed");
+ actionFileNewVcd = new KAction(i18n("New &Video CD Project"), "videocd", 0, this, SLOT(slotNewVcdDoc()),
+ actionCollection(), "file_new_vcd");
+ actionFileNewMovix = new KAction(i18n("New &eMovix CD Project"), "emovix", 0, this, SLOT(slotNewMovixDoc()),
+ actionCollection(), "file_new_movix");
+ actionFileNewMovixDvd = new KAction(i18n("New &eMovix DVD Project"), "emovix", 0, this, SLOT(slotNewMovixDvdDoc()),
+ actionCollection(), "file_new_movix_dvd");
+ actionFileNewDvd = new KAction(i18n("New Data &DVD Project"), "datadvd", 0, this, SLOT(slotNewDvdDoc()),
+ actionCollection(), "file_new_dvd");
+ actionFileNewVideoDvd = new KAction(i18n("New V&ideo DVD Project"), "videodvd", 0, this, SLOT(slotNewVideoDvdDoc()),
+ actionCollection(), "file_new_video_dvd");
+ actionFileContinueMultisession = new KAction( i18n("Continue Multisession Project"), "datacd", 0, this, SLOT(slotContinueMultisession()),
+ actionCollection(), "file_continue_multisession" );
+
+ actionFileNewMenu->setDelayed( false );
+ actionFileNewMenu->insert( actionFileNewData );
+ actionFileNewMenu->insert( actionFileNewDvd );
+ actionFileNewMenu->insert( actionFileContinueMultisession );
+ actionFileNewMenu->insert( new KActionSeparator( this ) );
+ actionFileNewMenu->insert( actionFileNewAudio );
+ actionFileNewMenu->insert( new KActionSeparator( this ) );
+ actionFileNewMenu->insert( actionFileNewMixed );
+ actionFileNewMenu->insert( new KActionSeparator( this ) );
+ actionFileNewMenu->insert( actionFileNewVcd );
+ actionFileNewMenu->insert( actionFileNewVideoDvd );
+ actionFileNewMenu->insert( new KActionSeparator( this ) );
+ actionFileNewMenu->insert( actionFileNewMovix );
+ actionFileNewMenu->insert( actionFileNewMovixDvd );
+
+
+
+
+
+ actionProjectAddFiles = new KAction( i18n("&Add Files..."), "filenew", 0, this, SLOT(slotProjectAddFiles()),
+ actionCollection(), "project_add_files");
+
+ KAction* actionClearProject = new KAction( i18n("&Clear Project"), QApplication::reverseLayout() ? "clear_left" : "locationbar_erase", 0,
+ this, SLOT(slotClearProject()), actionCollection(), "project_clear_project" );
+
+ actionViewDirTreeView = new KToggleAction(i18n("Show Directories"), 0, this, SLOT(slotShowDirTreeView()),
+ actionCollection(), "view_dir_tree");
+
+ actionViewContentsView = new KToggleAction(i18n("Show Contents"), 0, this, SLOT(slotShowContentsView()),
+ actionCollection(), "view_contents");
+
+ actionViewDocumentHeader = new KToggleAction(i18n("Show Document Header"), 0, this, SLOT(slotViewDocumentHeader()),
+ actionCollection(), "view_document_header");
+
+ actionToolsBlankCdrw = new KAction( i18n("&Erase CD-RW..."), "erasecd", 0, this, SLOT(slotBlankCdrw()),
+ actionCollection(), "tools_blank_cdrw" );
+ KAction* actionToolsFormatDVD = new KAction( i18n("&Format DVD%1RW...").arg(""), "formatdvd", 0, this,
+ SLOT(slotFormatDvd()), actionCollection(), "tools_format_dvd" );
+ actionToolsWriteCdImage = new KAction(i18n("&Burn CD Image..."), "burn_cdimage", 0, this, SLOT(slotWriteCdImage()),
+ actionCollection(), "tools_write_cd_image" );
+ KAction* actionToolsWriteDvdImage = new KAction(i18n("&Burn DVD ISO Image..."), "burn_dvdimage", 0, this, SLOT(slotWriteDvdIsoImage()),
+ actionCollection(), "tools_write_dvd_iso" );
+
+ actionCdCopy = new KAction(i18n("&Copy CD..."), "cdcopy", 0, this, SLOT(slotCdCopy()),
+ actionCollection(), "tools_copy_cd" );
+
+ KAction* actionToolsDvdCopy = new KAction(i18n("Copy &DVD..."), "dvdcopy", 0, this, SLOT(slotDvdCopy()),
+ actionCollection(), "tools_copy_dvd" );
+
+ actionToolsCddaRip = new KAction( i18n("Rip Audio CD..."), "cddarip", 0, this, SLOT(slotCddaRip()),
+ actionCollection(), "tools_cdda_rip" );
+ actionToolsVideoDvdRip = new KAction( i18n("Rip Video DVD..."), "videodvd", 0, this, SLOT(slotVideoDvdRip()),
+ actionCollection(), "tools_videodvd_rip" );
+ actionToolsVideoCdRip = new KAction( i18n("Rip Video CD..."), "videocd", 0, this, SLOT(slotVideoCdRip()),
+ actionCollection(), "tools_videocd_rip" );
+
+ (void)new KAction( i18n("System Check"), 0, 0, this, SLOT(slotCheckSystem()),
+ actionCollection(), "help_check_system" );
+
+#ifdef HAVE_K3BSETUP
+ actionSettingsK3bSetup = new KAction(i18n("&Setup System Permissions..."), "configure", 0, this, SLOT(slotK3bSetup()),
+ actionCollection(), "settings_k3bsetup" );
+#endif
+
+#ifdef K3B_DEBUG
+ (void)new KAction( "Test Media Selection ComboBox", 0, 0, this,
+ SLOT(slotMediaSelectionTester()), actionCollection(),
+ "test_media_selection" );
+#endif
+
+ actionFileNewMenu->setToolTip(i18n("Creates a new project"));
+ actionFileNewData->setToolTip( i18n("Creates a new data CD project") );
+ actionFileNewAudio->setToolTip( i18n("Creates a new audio CD project") );
+ actionFileNewMovixDvd->setToolTip( i18n("Creates a new eMovix DVD project") );
+ actionFileNewDvd->setToolTip( i18n("Creates a new data DVD project") );
+ actionFileNewMovix->setToolTip( i18n("Creates a new eMovix CD project") );
+ actionFileNewVcd->setToolTip( i18n("Creates a new Video CD project") );
+ actionToolsBlankCdrw->setToolTip( i18n("Open the CD-RW erasing dialog") );
+ actionToolsFormatDVD->setToolTip( i18n("Open the DVD%1RW formatting dialog").arg("") );
+ actionCdCopy->setToolTip( i18n("Open the CD copy dialog") );
+ actionToolsWriteCdImage->setToolTip( i18n("Write an Iso9660, cue/bin, or cdrecord clone image to CD") );
+ actionToolsWriteDvdImage->setToolTip( i18n("Write an Iso9660 image to DVD") );
+ actionToolsDvdCopy->setToolTip( i18n("Open the DVD copy dialog") );
+ actionFileOpen->setToolTip(i18n("Opens an existing project"));
+ actionFileOpenRecent->setToolTip(i18n("Opens a recently used file"));
+ actionFileSave->setToolTip(i18n("Saves the current project"));
+ actionFileSaveAs->setToolTip(i18n("Saves the current project to a new url"));
+ actionFileSaveAll->setToolTip(i18n("Saves all open projects"));
+ actionFileClose->setToolTip(i18n("Closes the current project"));
+ actionFileCloseAll->setToolTip(i18n("Closes all open projects"));
+ actionFileQuit->setToolTip(i18n("Quits the application"));
+ actionSettingsConfigure->setToolTip( i18n("Configure K3b settings") );
+#ifdef HAVE_K3BSETUP
+ actionSettingsK3bSetup->setToolTip( i18n("Setup the system permissions (requires root privileges)") );
+#endif
+ actionToolsCddaRip->setToolTip( i18n("Digitally extract tracks from an audio CD") );
+ actionToolsVideoDvdRip->setToolTip( i18n("Transcode Video DVD titles") );
+ actionToolsVideoCdRip->setToolTip( i18n("Extract tracks from a Video CD") );
+ actionProjectAddFiles->setToolTip( i18n("Add files to the current project") );
+ actionClearProject->setToolTip( i18n("Clear the current project") );
+
+ // make sure the tooltips are used for the menu
+ actionCollection()->setHighlightingEnabled( true );
+}
+
+
+
+const QPtrList<K3bDoc>& K3bMainWindow::projects() const
+{
+ return k3bappcore->projectManager()->projects();
+}
+
+
+void K3bMainWindow::slotConfigureKeys()
+{
+ KKeyDialog::configure( actionCollection(), this );
+}
+
+void K3bMainWindow::initStatusBar()
+{
+ m_statusBarManager = new K3bStatusBarManager( this );
+}
+
+
+void K3bMainWindow::initView()
+{
+ // setup main docking things
+ mainDock = createDockWidget( "project_view", SmallIcon("idea"), 0,
+ kapp->makeStdCaption( i18n("Project View") ), i18n("Project View") );
+ mainDock->setDockSite( KDockWidget::DockCorner );
+ mainDock->setEnableDocking( KDockWidget::DockNone );
+ setView( mainDock );
+ setMainDockWidget( mainDock );
+
+ // --- Document Dock ----------------------------------------------------------------------------
+ d->documentStack = new QWidgetStack( mainDock );
+ mainDock->setWidget( d->documentStack );
+
+ d->documentHull = new QWidget( d->documentStack );
+ d->documentStack->addWidget( d->documentHull );
+ QGridLayout* documentHullLayout = new QGridLayout( d->documentHull );
+ documentHullLayout->setMargin( 2 );
+ documentHullLayout->setSpacing( 0 );
+
+ m_documentHeader = new K3bThemedHeader( d->documentHull );
+ m_documentHeader->setTitle( i18n("Current Projects") );
+ m_documentHeader->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ m_documentHeader->setLeftPixmap( K3bTheme::PROJECT_LEFT );
+ m_documentHeader->setRightPixmap( K3bTheme::PROJECT_RIGHT );
+
+ // add the document tab to the styled document box
+ m_documentTab = new K3bProjectTabWidget( d->documentHull );
+
+ documentHullLayout->addWidget( m_documentHeader, 0, 0 );
+ documentHullLayout->addWidget( m_documentTab, 1, 0 );
+
+ connect( m_documentTab, SIGNAL(currentChanged(QWidget*)), this, SLOT(slotCurrentDocChanged()) );
+
+ d->welcomeWidget = new K3bWelcomeWidget( this, m_documentTab );
+ m_documentTab->addTab( d->welcomeWidget, i18n("Quickstart") );
+
+// d->documentStack->addWidget( d->welcomeWidget );
+// d->documentStack->raiseWidget( d->welcomeWidget );
+ // ---------------------------------------------------------------------------------------------
+
+ // --- Directory Dock --------------------------------------------------------------------------
+ m_dirTreeDock = createDockWidget( "directory_tree", SmallIcon("folder"), 0,
+ kapp->makeStdCaption( i18n("Sidepanel") ), i18n("Sidepanel") );
+ m_dirTreeDock->setEnableDocking( KDockWidget::DockCorner );
+
+ K3bFileTreeView* sidePanel = new K3bFileTreeView( m_dirTreeDock );
+ //K3bSidePanel* sidePanel = new K3bSidePanel( this, m_dirTreeDock, "sidePanel" );
+
+ m_dirTreeDock->setWidget( sidePanel );
+ m_dirTreeDock->manualDock( mainDock, KDockWidget::DockTop, 4000 );
+ connect( m_dirTreeDock, SIGNAL(iMBeingClosed()), this, SLOT(slotDirTreeDockHidden()) );
+ connect( m_dirTreeDock, SIGNAL(hasUndocked()), this, SLOT(slotDirTreeDockHidden()) );
+ // ---------------------------------------------------------------------------------------------
+
+ // --- Contents Dock ---------------------------------------------------------------------------
+ m_contentsDock = createDockWidget( "contents_view", SmallIcon("idea"), 0,
+ kapp->makeStdCaption( i18n("Contents View") ), i18n("Contents View") );
+ m_contentsDock->setEnableDocking( KDockWidget::DockCorner );
+ m_dirView = new K3bDirView( sidePanel/*->fileTreeView()*/, m_contentsDock );
+ m_contentsDock->setWidget( m_dirView );
+ m_contentsDock->manualDock( m_dirTreeDock, KDockWidget::DockRight, 2000 );
+
+ connect( m_contentsDock, SIGNAL(iMBeingClosed()), this, SLOT(slotContentsDockHidden()) );
+ connect( m_contentsDock, SIGNAL(hasUndocked()), this, SLOT(slotContentsDockHidden()) );
+ // ---------------------------------------------------------------------------------------------
+
+ // --- filetreecombobox-toolbar ----------------------------------------------------------------
+ K3bFileTreeComboBox* m_fileTreeComboBox = new K3bFileTreeComboBox( 0 );
+ connect( m_fileTreeComboBox, SIGNAL(urlExecuted(const KURL&)), m_dirView, SLOT(showUrl(const KURL& )) );
+ connect( m_fileTreeComboBox, SIGNAL(deviceExecuted(K3bDevice::Device*)), m_dirView,
+ SLOT(showDevice(K3bDevice::Device* )) );
+ connect( m_dirView, SIGNAL(urlEntered(const KURL&)), m_fileTreeComboBox, SLOT(setUrl(const KURL&)) );
+ connect( m_dirView, SIGNAL(deviceSelected(K3bDevice::Device*)), m_fileTreeComboBox, SLOT(setDevice(K3bDevice::Device*)) );
+
+ KWidgetAction* fileTreeComboAction = new KWidgetAction( m_fileTreeComboBox,
+ i18n("&Quick Dir Selector"),
+ 0, 0, 0,
+ actionCollection(), "quick_dir_selector" );
+ fileTreeComboAction->setAutoSized(true);
+ (void)new KAction( i18n("Go"), "key_enter", 0, m_fileTreeComboBox, SLOT(slotGoUrl()), actionCollection(), "go_url" );
+ // ---------------------------------------------------------------------------------------------
+}
+
+
+void K3bMainWindow::createClient( K3bDoc* doc )
+{
+ // create the proper K3bView (maybe we should put this into some other class like K3bProjectManager)
+ K3bView* view = 0;
+ switch( doc->type() ) {
+ case K3bDoc::AUDIO:
+ view = new K3bAudioView( static_cast<K3bAudioDoc*>(doc), m_documentTab );
+ break;
+ case K3bDoc::DATA:
+ view = new K3bDataView( static_cast<K3bDataDoc*>(doc), m_documentTab );
+ break;
+ case K3bDoc::MIXED:
+ {
+ K3bMixedDoc* mixedDoc = static_cast<K3bMixedDoc*>(doc);
+ view = new K3bMixedView( mixedDoc, m_documentTab );
+ mixedDoc->dataDoc()->setView( view );
+ mixedDoc->audioDoc()->setView( view );
+ break;
+ }
+ case K3bDoc::VCD:
+ view = new K3bVcdView( static_cast<K3bVcdDoc*>(doc), m_documentTab );
+ break;
+ case K3bDoc::MOVIX:
+ view = new K3bMovixView( static_cast<K3bMovixDoc*>(doc), m_documentTab );
+ break;
+ case K3bDoc::MOVIX_DVD:
+ view = new K3bMovixDvdView( static_cast<K3bMovixDvdDoc*>(doc), m_documentTab );
+ break;
+ case K3bDoc::DVD:
+ view = new K3bDvdView( static_cast<K3bDvdDoc*>(doc), m_documentTab );
+ break;
+ case K3bDoc::VIDEODVD:
+ view = new K3bVideoDvdView( static_cast<K3bVideoDvdDoc*>(doc), m_documentTab );
+ break;
+ }
+
+ doc->setView( view );
+ view->setCaption( doc->URL().fileName() );
+
+ m_documentTab->insertTab( doc );
+ m_documentTab->showPage( view );
+
+ slotCurrentDocChanged();
+}
+
+
+K3bView* K3bMainWindow::activeView() const
+{
+ QWidget* w = m_documentTab->currentPage();
+ if( K3bView* view = dynamic_cast<K3bView*>(w) )
+ return view;
+ else
+ return 0;
+}
+
+
+K3bDoc* K3bMainWindow::activeDoc() const
+{
+ if( activeView() )
+ return activeView()->getDocument();
+ else
+ return 0;
+}
+
+
+K3bDoc* K3bMainWindow::openDocument(const KURL& url)
+{
+ slotStatusMsg(i18n("Opening file..."));
+
+ //
+ // First we check if this is an iso image in case someone wants to open one this way
+ //
+ if( !isCdDvdImageAndIfSoOpenDialog( url ) ) {
+
+ // see if it's an audio cue file
+ K3bCueFileParser parser( url.path() );
+ if( parser.isValid() && parser.toc().contentType() == K3bDevice::AUDIO ) {
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::AUDIO );
+ doc->addUrl( url );
+ return doc;
+ }
+ else {
+ // check, if document already open. If yes, set the focus to the first view
+ K3bDoc* doc = k3bappcore->projectManager()->findByUrl( url );
+ if( doc ) {
+ doc->view()->setFocus();
+ return doc;
+ }
+
+ doc = k3bappcore->projectManager()->openProject( url );
+
+ if( doc == 0 ) {
+ KMessageBox::error (this,i18n("Could not open document!"), i18n("Error!"));
+ return 0;
+ }
+
+ actionFileOpenRecent->addURL(url);
+
+ return doc;
+ }
+ }
+ else
+ return 0;
+}
+
+
+void K3bMainWindow::saveOptions()
+{
+ actionFileOpenRecent->saveEntries( config(), "Recent Files" );
+
+ // save dock positions!
+ manager()->writeConfig( config(), "Docking Config" );
+
+ m_dirView->saveConfig( config() );
+
+ saveMainWindowSettings( config(), "main_window_settings" );
+
+ k3bcore->saveSettings( config() );
+
+ d->welcomeWidget->saveConfig( config() );
+
+ KConfigGroup grp( m_config, "General Options" );
+ grp.writeEntry( "Show Document Header", actionViewDocumentHeader->isChecked() );
+}
+
+
+void K3bMainWindow::readOptions()
+{
+ KConfigGroup grp( m_config, "General Options" );
+
+ bool bViewDocumentHeader = grp.readBoolEntry("Show Document Header", true);
+ actionViewDocumentHeader->setChecked(bViewDocumentHeader);
+
+ // initialize the recent file list
+ actionFileOpenRecent->loadEntries( config(), "Recent Files" );
+
+ // do not read dock-positions from a config that has been saved by an old version
+ K3bVersion configVersion( grp.readEntry( "config version", "0.1" ) );
+ if( configVersion >= K3bVersion("0.12") )
+ manager()->readConfig( config(), "Docking Config" );
+ else
+ kdDebug() << "(K3bMainWindow) ignoring docking config from K3b version " << configVersion << endl;
+
+ applyMainWindowSettings( config(), "main_window_settings" );
+
+ m_dirView->readConfig( config() );
+
+ slotViewDocumentHeader();
+ slotCheckDockWidgetStatus();
+}
+
+
+void K3bMainWindow::saveProperties( KConfig* c )
+{
+ // 1. put saved projects in the config
+ // 2. save every modified project in "~/.kde/share/apps/k3b/sessions/" + KApp->sessionId()
+ // 3. save the url of the project (might be something like "AudioCD1") in the config
+ // 4. save the status of every project (modified/saved)
+
+ QString saveDir = KGlobal::dirs()->saveLocation( "appdata", "sessions/" + qApp->sessionId() + "/", true );
+
+ // FIXME: for some reason the config entries are not properly stored when using the default
+ // KMainWindow session config. Since I was not able to find the bug I use another config object
+ // ----------------------------------------------------------
+ c = new KSimpleConfig( saveDir + "list", false );
+ c->setGroup( "Saved Session" );
+ // ----------------------------------------------------------
+
+ const QPtrList<K3bDoc>& docs = k3bappcore->projectManager()->projects();
+ c->writeEntry( "Number of projects", docs.count() );
+
+ int cnt = 1;
+ for( QPtrListIterator<K3bDoc> it( docs ); *it; ++it ) {
+ // the "name" of the project (or the original url if isSaved())
+ c->writePathEntry( QString("%1 url").arg(cnt), (*it)->URL().url() );
+
+ // is the doc modified
+ c->writeEntry( QString("%1 modified").arg(cnt), (*it)->isModified() );
+
+ // has the doc already been saved?
+ c->writeEntry( QString("%1 saved").arg(cnt), (*it)->isSaved() );
+
+ // where does the session management save it? If it's not modified and saved this is
+ // the same as the url
+ KURL saveUrl = (*it)->URL();
+ if( !(*it)->isSaved() || (*it)->isModified() )
+ saveUrl = KURL::fromPathOrURL( saveDir + QString::number(cnt) );
+ c->writePathEntry( QString("%1 saveurl").arg(cnt), saveUrl.url() );
+
+ // finally save it
+ k3bappcore->projectManager()->saveProject( *it, saveUrl );
+
+ ++cnt;
+ }
+
+ // FIXME: for some reason the config entries are not properly stored when using the default
+ // KMainWindow session config. Since I was not able to find the bug I use another config object
+ // ----------------------------------------------------------
+ delete c;
+ // ----------------------------------------------------------
+}
+
+
+// FIXME:move this to K3bProjectManager
+void K3bMainWindow::readProperties( KConfig* c )
+{
+ // FIXME: do not delete the files here. rather do it when the app is exited normally
+ // since that's when we can be sure we never need the session stuff again.
+
+ // 1. read all projects from the config
+ // 2. simply open all of themg
+ // 3. reset the saved urls and the modified state
+ // 4. delete "~/.kde/share/apps/k3b/sessions/" + KApp->sessionId()
+
+ QString saveDir = KGlobal::dirs()->saveLocation( "appdata", "sessions/" + qApp->sessionId() + "/", true );
+
+ // FIXME: for some reason the config entries are not properly stored when using the default
+ // KMainWindow session config. Since I was not able to find the bug I use another config object
+ // ----------------------------------------------------------
+ c = new KSimpleConfig( saveDir + "list", true );
+ c->setGroup( "Saved Session" );
+ // ----------------------------------------------------------
+
+ int cnt = c->readNumEntry( "Number of projects", 0 );
+ kdDebug() << "(K3bMainWindow::readProperties) number of projects from last session in " << saveDir << ": " << cnt << endl
+ << " read from config group " << c->group() << endl;
+
+ for( int i = 1; i <= cnt; ++i ) {
+ // in this case the constructor works since we saved as url()
+ KURL url = c->readPathEntry( QString("%1 url").arg(i) );
+
+ bool modified = c->readBoolEntry( QString("%1 modified").arg(i) );
+
+ bool saved = c->readBoolEntry( QString("%1 saved").arg(i) );
+
+ KURL saveUrl = c->readPathEntry( QString("%1 saveurl").arg(i) );
+
+ // now load the project
+ if( K3bDoc* doc = k3bappcore->projectManager()->openProject( saveUrl ) ) {
+
+ // reset the url
+ doc->setURL( url );
+ doc->setModified( modified );
+ doc->setSaved( saved );
+ }
+ else
+ kdDebug() << "(K3bMainWindow) could not open session saved doc " << url.path() << endl;
+
+ // remove the temp file
+ if( !saved || modified )
+ QFile::remove( saveUrl.path() );
+ }
+
+ // and now remove the temp dir
+ KIO::del( KURL::fromPathOrURL(saveDir), false, false );
+
+ // FIXME: for some reason the config entries are not properly stored when using the default
+ // KMainWindow session config. Since I was not able to find the bug I use another config object
+ // ----------------------------------------------------------
+ delete c;
+ // ----------------------------------------------------------
+}
+
+
+bool K3bMainWindow::queryClose()
+{
+ //
+ // Check if a job is currently running
+ // For now K3b only allows for one major job at a time which means that we only need to cancel
+ // this one job.
+ //
+ if( k3bcore->jobsRunning() ) {
+
+ // pitty, but I see no possibility to make this work. It always crashes because of the event
+ // management thing mentioned below. So until I find a solution K3b simply will refuse to close
+ // while a job i running
+ return false;
+
+// kdDebug() << "(K3bMainWindow::queryClose) jobs running." << endl;
+// K3bJob* job = k3bcore->runningJobs().getFirst();
+
+// // now search for the major job (to be on the safe side although for now no subjobs register with the k3bcore)
+// K3bJobHandler* jh = job->jobHandler();
+// while( jh->isJob() ) {
+// job = static_cast<K3bJob*>( jh );
+// jh = job->jobHandler();
+// }
+
+// kdDebug() << "(K3bMainWindow::queryClose) main job found: " << job->jobDescription() << endl;
+
+// // now job is the major job and jh should be a widget
+// QWidget* progressDialog = dynamic_cast<QWidget*>( jh );
+
+// kdDebug() << "(K3bMainWindow::queryClose) job active: " << job->active() << endl;
+
+// // now ask the user if he/she really wants to cancel this job
+// if( job->active() ) {
+// if( KMessageBox::questionYesNo( progressDialog ? progressDialog : this,
+// i18n("Do you really want to cancel?"),
+// i18n("Cancel") ) == KMessageBox::Yes ) {
+// // cancel the job
+// kdDebug() << "(K3bMainWindow::queryClose) canceling job." << endl;
+// job->cancel();
+
+// // wait for the job to finish
+// kdDebug() << "(K3bMainWindow::queryClose) waiting for job to finish." << endl;
+// K3bSignalWaiter::waitForJob( job );
+
+// // close the progress dialog
+// if( progressDialog ) {
+// kdDebug() << "(K3bMainWindow::queryClose) closing progress dialog." << endl;
+// progressDialog->close();
+// //
+// // now here we have the problem that due to the whole Qt event thing the exec call (or
+// // in this case most likely the startJob call) does not return until we leave this method.
+// // That means that the progress dialog might be deleted by it's parent below (when we
+// // close docs) before it is deleted by the creator (most likely a projectburndialog).
+// // That would result in a double deletion and thus a crash.
+// // So we just reparent the dialog to 0 here so it's (former) parent won't delete it.
+// //
+// progressDialog->reparent( 0, QPoint(0,0) );
+// }
+
+// kdDebug() << "(K3bMainWindow::queryClose) job cleanup done." << endl;
+// }
+// else
+// return false;
+// }
+ }
+
+ //
+ // if we are closed by the session manager everything is fine since we store the
+ // current state in saveProperties
+ //
+ if( kapp->sessionSaving() )
+ return true;
+
+ // FIXME: do not close the docs here. Just ask for them to be saved and return false
+ // if the user chose cancel for some doc
+
+ // ---------------------------------
+ // we need to manually close all the views to ensure that
+ // each of them receives a close-event and
+ // the user is asked for every modified doc to save the changes
+ // ---------------------------------
+
+ while( K3bView* view = activeView() ) {
+ if( !canCloseDocument(view->doc()) )
+ return false;
+ closeProject(view->doc());
+ }
+
+ return true;
+}
+
+
+bool K3bMainWindow::canCloseDocument( K3bDoc* doc )
+{
+ if( !doc->isModified() )
+ return true;
+
+ if( !KConfigGroup( config(), "General Options" ).readBoolEntry( "ask_for_saving_changes_on_exit", true ) )
+ return true;
+
+ switch ( KMessageBox::warningYesNoCancel( this,
+ i18n("%1 has unsaved data.").arg( doc->URL().fileName() ),
+ i18n("Closing Project"),
+ KStdGuiItem::save(),
+ KGuiItem( i18n("&Discard"), "editshred" ) ) )
+ {
+ case KMessageBox::Yes:
+ fileSave( doc );
+ case KMessageBox::No:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool K3bMainWindow::queryExit()
+{
+ // TODO: call this in K3bApplication somewhere
+ saveOptions();
+ return true;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// SLOT IMPLEMENTATION
+/////////////////////////////////////////////////////////////////////
+
+
+void K3bMainWindow::slotFileOpen()
+{
+ slotStatusMsg(i18n("Opening file..."));
+
+ KURL::List urls = KFileDialog::getOpenURLs( ":k3b-projects-folder",
+ i18n("*.k3b|K3b Projects"),
+ this,
+ i18n("Open Files") );
+ for( KURL::List::iterator it = urls.begin(); it != urls.end(); ++it ) {
+ openDocument( *it );
+ actionFileOpenRecent->addURL( *it );
+ }
+}
+
+void K3bMainWindow::slotFileOpenRecent(const KURL& url)
+{
+ slotStatusMsg(i18n("Opening file..."));
+
+ openDocument(url);
+}
+
+
+void K3bMainWindow::slotFileSaveAll()
+{
+ for( QPtrListIterator<K3bDoc> it( k3bappcore->projectManager()->projects() );
+ *it; ++it ) {
+ fileSave( *it );
+ }
+}
+
+
+void K3bMainWindow::slotFileSave()
+{
+ if( K3bDoc* doc = activeDoc() ) {
+ fileSave( doc );
+ }
+}
+
+void K3bMainWindow::fileSave( K3bDoc* doc )
+{
+ slotStatusMsg(i18n("Saving file..."));
+
+ if( doc == 0 ) {
+ doc = activeDoc();
+ }
+ if( doc != 0 ) {
+ if( !doc->isSaved() )
+ fileSaveAs( doc );
+ else if( !k3bappcore->projectManager()->saveProject( doc, doc->URL()) )
+ KMessageBox::error (this,i18n("Could not save the current document!"), i18n("I/O Error"));
+ }
+}
+
+
+void K3bMainWindow::slotFileSaveAs()
+{
+ if( K3bDoc* doc = activeDoc() ) {
+ fileSaveAs( doc );
+ }
+}
+
+
+void K3bMainWindow::fileSaveAs( K3bDoc* doc )
+{
+ slotStatusMsg(i18n("Saving file with a new filename..."));
+
+ if( doc == 0 ) {
+ doc = activeDoc();
+ }
+
+ if( doc != 0 ) {
+ // we do not use the static KFileDialog method here to be able to specify a filename suggestion
+ KFileDialog dlg( ":k3b-projects-folder", i18n("*.k3b|K3b Projects"), this, "filedialog", true );
+ dlg.setCaption( i18n("Save As") );
+ dlg.setOperationMode( KFileDialog::Saving );
+ dlg.setSelection( doc->name() );
+ dlg.exec();
+ KURL url = dlg.selectedURL();
+
+ if( url.isValid() ) {
+ KRecentDocument::add( url );
+
+ bool exists = KIO::NetAccess::exists( url, false, 0 );
+ if( !exists ||
+ ( exists &&
+ KMessageBox::warningContinueCancel( this, i18n("Do you want to overwrite %1?").arg( url.prettyURL() ),
+ i18n("File Exists"), i18n("Overwrite") )
+ == KMessageBox::Continue ) ) {
+
+ if( !k3bappcore->projectManager()->saveProject( doc, url ) ) {
+ KMessageBox::error (this,i18n("Could not save the current document!"), i18n("I/O Error"));
+ return;
+ }
+ else
+ actionFileOpenRecent->addURL(url);
+ }
+ }
+ }
+}
+
+
+void K3bMainWindow::slotFileClose()
+{
+ slotStatusMsg(i18n("Closing file..."));
+ if( K3bView* pView = activeView() ) {
+ if( pView ) {
+ K3bDoc* pDoc = pView->doc();
+
+ if( canCloseDocument(pDoc) ) {
+ closeProject(pDoc);
+ }
+ }
+ }
+
+ slotCurrentDocChanged();
+}
+
+
+void K3bMainWindow::slotFileCloseAll()
+{
+ while( K3bView* pView = activeView() ) {
+ if( pView ) {
+ K3bDoc* pDoc = pView->doc();
+
+ if( canCloseDocument(pDoc) )
+ closeProject(pDoc);
+ else
+ break;
+ }
+ }
+
+ slotCurrentDocChanged();
+}
+
+
+void K3bMainWindow::closeProject( K3bDoc* doc )
+{
+ // unplug the actions
+ if( factory() ) {
+ if( d->lastDoc == doc ) {
+ factory()->removeClient( static_cast<K3bView*>(d->lastDoc->view()) );
+ d->lastDoc = 0;
+ }
+ }
+
+ // remove the view from the project tab
+ m_documentTab->removePage( doc->view() );
+
+ // remove the project from the manager
+ k3bappcore->projectManager()->removeProject( doc );
+
+ // delete view and doc
+ delete doc->view();
+ delete doc;
+}
+
+
+void K3bMainWindow::slotFileQuit()
+{
+ close();
+}
+
+
+void K3bMainWindow::slotViewStatusBar()
+{
+ //turn Statusbar on or off
+ if(actionViewStatusBar->isChecked()) {
+ statusBar()->show();
+ }
+ else {
+ statusBar()->hide();
+ }
+}
+
+
+void K3bMainWindow::slotStatusMsg(const QString &text)
+{
+ ///////////////////////////////////////////////////////////////////
+ // change status message permanently
+// statusBar()->clear();
+// statusBar()->changeItem(text,1);
+
+ statusBar()->message( text, 2000 );
+}
+
+
+void K3bMainWindow::slotSettingsConfigure()
+{
+ K3bOptionDialog d( this, "SettingsDialog", true );
+
+ d.exec();
+
+ // emit a changed signal every time since we do not know if the user selected
+ // "apply" and "cancel" or "ok"
+ emit configChanged( m_config );
+}
+
+
+void K3bMainWindow::showOptionDialog( int index )
+{
+ K3bOptionDialog d( this, "SettingsDialog", true );
+
+ d.showPage( index );
+
+ d.exec();
+
+ // emit a changed signal every time since we do not know if the user selected
+ // "apply" and "cancel" or "ok"
+ emit configChanged( m_config );
+}
+
+
+K3bDoc* K3bMainWindow::slotNewAudioDoc()
+{
+ slotStatusMsg(i18n("Creating new Audio CD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::AUDIO );
+
+ return doc;
+}
+
+K3bDoc* K3bMainWindow::slotNewDataDoc()
+{
+ slotStatusMsg(i18n("Creating new Data CD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::DATA );
+
+ return doc;
+}
+
+
+K3bDoc* K3bMainWindow::slotNewDvdDoc()
+{
+ slotStatusMsg(i18n("Creating new Data DVD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::DVD );
+
+ return doc;
+}
+
+
+K3bDoc* K3bMainWindow::slotContinueMultisession()
+{
+ return K3bDataSessionImportDialog::importSession( 0, this );
+}
+
+
+K3bDoc* K3bMainWindow::slotNewVideoDvdDoc()
+{
+ slotStatusMsg(i18n("Creating new VideoDVD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::VIDEODVD );
+
+ return doc;
+}
+
+
+K3bDoc* K3bMainWindow::slotNewMixedDoc()
+{
+ slotStatusMsg(i18n("Creating new Mixed Mode CD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::MIXED );
+
+ return doc;
+}
+
+K3bDoc* K3bMainWindow::slotNewVcdDoc()
+{
+ slotStatusMsg(i18n("Creating new Video CD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::VCD );
+
+ return doc;
+}
+
+
+K3bDoc* K3bMainWindow::slotNewMovixDoc()
+{
+ slotStatusMsg(i18n("Creating new eMovix CD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::MOVIX );
+
+ return doc;
+}
+
+
+K3bDoc* K3bMainWindow::slotNewMovixDvdDoc()
+{
+ slotStatusMsg(i18n("Creating new eMovix DVD Project."));
+
+ K3bDoc* doc = k3bappcore->projectManager()->createProject( K3bDoc::MOVIX_DVD );
+
+ return doc;
+}
+
+
+void K3bMainWindow::slotCurrentDocChanged()
+{
+ // check the doctype
+ K3bView* v = activeView();
+ if( v ) {
+ k3bappcore->projectManager()->setActive( v->doc() );
+
+ //
+ // There are two possiblities to plug the project actions:
+ // 1. Through KXMLGUIClient::plugActionList
+ // This way we just ask the View for the actionCollection (which it should merge with
+ // the doc's) and plug it into the project menu.
+ // Advantage: easy and clear to handle
+ // Disadvantage: we may only plug all actions at once into one menu
+ //
+ // 2. Through merging the doc as a KXMLGUIClient
+ // This way every view is a KXMLGUIClient and it's GUI is just merged into the MainWindow's.
+ // Advantage: flexible
+ // Disadvantage: every view needs it's own XML file
+ //
+ //
+
+ if( factory() ) {
+ if( d->lastDoc )
+ factory()->removeClient( static_cast<K3bView*>(d->lastDoc->view()) );
+ factory()->addClient( v );
+ d->lastDoc = v->doc();
+ }
+ else
+ kdDebug() << "(K3bMainWindow) ERROR: could not get KXMLGUIFactory instance." << endl;
+ }
+ else
+ k3bappcore->projectManager()->setActive( 0L );
+
+ if( k3bappcore->projectManager()->isEmpty() ) {
+ slotStateChanged( "state_project_active", KXMLGUIClient::StateReverse );
+ }
+ else {
+ d->documentStack->raiseWidget( d->documentHull );
+ slotStateChanged( "state_project_active", KXMLGUIClient::StateNoReverse );
+ }
+
+ // make sure the document header is shown (or not)
+ slotViewDocumentHeader();
+}
+
+
+void K3bMainWindow::slotEditToolbars()
+{
+ saveMainWindowSettings( m_config, "main_window_settings" );
+ KEditToolbar dlg( factory() );
+ connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(slotNewToolBarConfig()));
+ dlg.exec();
+}
+
+
+void K3bMainWindow::slotNewToolBarConfig()
+{
+ applyMainWindowSettings( m_config, "main_window_settings" );
+}
+
+
+bool K3bMainWindow::eject()
+{
+ KConfigGroup c( config(), "General Options" );
+ return !c.readBoolEntry( "No cd eject", false );
+}
+
+
+void K3bMainWindow::slotErrorMessage(const QString& message)
+{
+ KMessageBox::error( this, message );
+}
+
+
+void K3bMainWindow::slotWarningMessage(const QString& message)
+{
+ KMessageBox::sorry( this, message );
+}
+
+
+void K3bMainWindow::slotWriteCdImage()
+{
+ K3bCdImageWritingDialog d( this );
+ d.exec(false);
+}
+
+
+void K3bMainWindow::slotWriteDvdIsoImage()
+{
+ K3bIsoImageWritingDialog d( this );
+ d.exec(false);
+}
+
+
+void K3bMainWindow::slotWriteDvdIsoImage( const KURL& url )
+{
+ K3bIsoImageWritingDialog d( this );
+ d.setImage( url );
+ d.exec(false);
+}
+
+
+void K3bMainWindow::slotWriteCdImage( const KURL& url )
+{
+ K3bCdImageWritingDialog d( this );
+ d.setImage( url );
+ d.exec(false);
+}
+
+
+void K3bMainWindow::slotProjectAddFiles()
+{
+ K3bView* view = activeView();
+
+ if( view ) {
+ QStringList files = KFileDialog::getOpenFileNames( ":k3b-project-add-files",
+ i18n("*|All Files"),
+ this,
+ i18n("Select Files to Add to Project") );
+
+ KURL::List urls;
+ for( QStringList::ConstIterator it = files.begin();
+ it != files.end(); it++ ) {
+ KURL url;
+ url.setPath(*it);
+ urls.append( url );
+ }
+
+ if( !urls.isEmpty() )
+ view->addUrls( urls );
+ }
+ else
+ KMessageBox::error( this, i18n("Please create a project before adding files"), i18n("No Active Project"));
+}
+
+
+void K3bMainWindow::slotK3bSetup()
+{
+ KProcess p;
+ p << "kdesu" << "kcmshell k3bsetup2 --lang " + KGlobal::locale()->language();
+ if( !p.start( KProcess::DontCare ) )
+ KMessageBox::error( 0, i18n("Could not find kdesu to run K3bSetup with root privileges. "
+ "Please run it manually as root.") );
+}
+
+
+void K3bMainWindow::blankCdrw( K3bDevice::Device* dev )
+{
+ K3bBlankingDialog dlg( this, "blankingdialog" );
+ dlg.setDevice( dev );
+ dlg.exec(false);
+}
+
+
+void K3bMainWindow::slotBlankCdrw()
+{
+ blankCdrw( 0 );
+}
+
+
+void K3bMainWindow::formatDvd( K3bDevice::Device* dev )
+{
+ K3bDvdFormattingDialog d( this );
+ d.setDevice( dev );
+ d.exec(false);
+}
+
+
+void K3bMainWindow::slotFormatDvd()
+{
+ formatDvd( 0 );
+}
+
+
+void K3bMainWindow::cdCopy( K3bDevice::Device* dev )
+{
+ K3bCdCopyDialog d( this );
+ d.setReadingDevice( dev );
+ d.exec(false);
+}
+
+
+void K3bMainWindow::slotCdCopy()
+{
+ cdCopy( 0 );
+}
+
+
+void K3bMainWindow::dvdCopy( K3bDevice::Device* dev )
+{
+ K3bDvdCopyDialog d( this );
+ d.setReadingDevice( dev );
+ d.exec(false);
+}
+
+
+void K3bMainWindow::slotDvdCopy()
+{
+ dvdCopy( 0 );
+}
+
+
+// void K3bMainWindow::slotVideoDvdCopy()
+// {
+// K3bVideoDvdCopyDialog d( this );
+// d.exec();
+// }
+
+
+void K3bMainWindow::slotShowDirTreeView()
+{
+ m_dirTreeDock->changeHideShowState();
+ slotCheckDockWidgetStatus();
+}
+
+
+void K3bMainWindow::slotShowContentsView()
+{
+ m_contentsDock->changeHideShowState();
+ slotCheckDockWidgetStatus();
+}
+
+
+void K3bMainWindow::slotShowMenuBar()
+{
+ if( menuBar()->isVisible() )
+ menuBar()->hide();
+ else
+ menuBar()->show();
+}
+
+
+void K3bMainWindow::slotShowTips()
+{
+ KTipDialog::showTip( this, QString::null, true );
+}
+
+
+void K3bMainWindow::slotDirTreeDockHidden()
+{
+ actionViewDirTreeView->setChecked( false );
+}
+
+
+void K3bMainWindow::slotContentsDockHidden()
+{
+ actionViewContentsView->setChecked( false );
+}
+
+
+void K3bMainWindow::slotCheckDockWidgetStatus()
+{
+ actionViewContentsView->setChecked( m_contentsDock->isVisible() );
+ actionViewDirTreeView->setChecked( m_dirTreeDock->isVisible() );
+}
+
+
+void K3bMainWindow::slotViewDocumentHeader()
+{
+ if( actionViewDocumentHeader->isChecked() &&
+ !k3bappcore->projectManager()->isEmpty() ) {
+ m_documentHeader->show();
+ }
+ else {
+ m_documentHeader->hide();
+ }
+}
+
+
+K3bExternalBinManager* K3bMainWindow::externalBinManager() const
+{
+ return k3bcore->externalBinManager();
+}
+
+
+K3bDevice::DeviceManager* K3bMainWindow::deviceManager() const
+{
+ return k3bcore->deviceManager();
+}
+
+
+void K3bMainWindow::slotDataImportSession()
+{
+ if( activeView() ) {
+ if( K3bDataView* view = dynamic_cast<K3bDataView*>(activeView()) ) {
+ view->importSession();
+ }
+ }
+}
+
+
+void K3bMainWindow::slotDataClearImportedSession()
+{
+ if( activeView() ) {
+ if( K3bDataView* view = dynamic_cast<K3bDataView*>(activeView()) ) {
+ view->clearImportedSession();
+ }
+ }
+}
+
+
+void K3bMainWindow::slotEditBootImages()
+{
+ if( activeView() ) {
+ if( K3bDataView* view = dynamic_cast<K3bDataView*>(activeView()) ) {
+ view->editBootImages();
+ }
+ }
+}
+
+
+void K3bMainWindow::slotCheckSystemTimed()
+{
+ // run the system check from the event queue so we do not
+ // mess with the device state resetting throughout the app
+ // when called from K3bDeviceManager::changed
+ QTimer::singleShot( 0, this, SLOT(slotCheckSystem()) );
+}
+
+
+void K3bMainWindow::slotCheckSystem()
+{
+ K3bSystemProblemDialog::checkSystem( this );
+}
+
+
+void K3bMainWindow::addUrls( const KURL::List& urls )
+{
+ if( K3bView* view = activeView() ) {
+ view->addUrls( urls );
+ }
+ else {
+ // check if the files are all audio we can handle. If so create an audio project
+ bool audio = true;
+ QPtrList<K3bPlugin> fl = k3bcore->pluginManager()->plugins( "AudioDecoder" );
+ for( KURL::List::const_iterator it = urls.begin(); it != urls.end(); ++it ) {
+ const KURL& url = *it;
+
+ if( QFileInfo(url.path()).isDir() ) {
+ audio = false;
+ break;
+ }
+
+ bool a = false;
+ for( QPtrListIterator<K3bPlugin> it( fl ); it.current(); ++it ) {
+ if( static_cast<K3bAudioDecoderFactory*>(it.current())->canDecode( url ) ) {
+ a = true;
+ break;
+ }
+ }
+ if( !a ) {
+ audio = a;
+ break;
+ }
+ }
+
+ if( !audio && urls.count() == 1 ) {
+ // see if it's an audio cue file
+ K3bCueFileParser parser( urls.first().path() );
+ if( parser.isValid() && parser.toc().contentType() == K3bDevice::AUDIO ) {
+ audio = true;
+ }
+ }
+
+ if( audio )
+ static_cast<K3bView*>(slotNewAudioDoc()->view())->addUrls( urls );
+ else if( urls.count() > 1 || !isCdDvdImageAndIfSoOpenDialog( urls.first() ) )
+ static_cast<K3bView*>(slotNewDataDoc()->view())->addUrls( urls );
+ }
+}
+
+
+void K3bMainWindow::slotClearProject()
+{
+ K3bDoc* doc = k3bappcore->projectManager()->activeDoc();
+ if( doc ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you really want to clear the current project?"),
+ i18n("Clear Project"),
+ i18n("Clear"),
+ "clear_current_project_dontAskAgain" ) == KMessageBox::Continue ) {
+ doc->newDocument();
+ k3bappcore->projectManager()->loadDefaults( doc );
+ }
+ }
+}
+
+
+bool K3bMainWindow::isCdDvdImageAndIfSoOpenDialog( const KURL& url )
+{
+ K3bIso9660 iso( url.path() );
+ if( iso.open() ) {
+ iso.close();
+ // very rough dvd image size test
+ if( K3b::filesize( url ) > 1000*1024*1024 )
+ slotWriteDvdIsoImage( url );
+ else
+ slotWriteCdImage( url );
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+void K3bMainWindow::slotCddaRip()
+{
+ cddaRip( 0 );
+}
+
+
+void K3bMainWindow::cddaRip( K3bDevice::Device* dev )
+{
+ if( !dev ||
+ !(k3bappcore->mediaCache()->medium( dev ).content() & K3bMedium::CONTENT_AUDIO ) )
+ dev = K3bMediaSelectionDialog::selectMedium( K3bDevice::MEDIA_CD_ALL,
+ K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE,
+ K3bMedium::CONTENT_AUDIO,
+ this,
+ i18n("Audio CD Rip") );
+
+ if( dev )
+ m_dirView->showDevice( dev );
+}
+
+
+void K3bMainWindow::videoDvdRip( K3bDevice::Device* dev )
+{
+ if( !dev ||
+ !(k3bappcore->mediaCache()->medium( dev ).content() & K3bMedium::CONTENT_VIDEO_DVD ) )
+ dev = K3bMediaSelectionDialog::selectMedium( K3bDevice::MEDIA_DVD_ALL,
+ K3bDevice::STATE_COMPLETE,
+ K3bMedium::CONTENT_VIDEO_DVD,
+ this,
+ i18n("Video DVD Rip") );
+
+ if( dev )
+ m_dirView->showDevice( dev );
+}
+
+
+void K3bMainWindow::slotVideoDvdRip()
+{
+ videoDvdRip( 0 );
+}
+
+
+void K3bMainWindow::videoCdRip( K3bDevice::Device* dev )
+{
+ if( !dev ||
+ !(k3bappcore->mediaCache()->medium( dev ).content() & K3bMedium::CONTENT_VIDEO_CD ) )
+ dev = K3bMediaSelectionDialog::selectMedium( K3bDevice::MEDIA_CD_ALL,
+ K3bDevice::STATE_COMPLETE,
+ K3bMedium::CONTENT_VIDEO_CD,
+ this,
+ i18n("Video CD Rip") );
+
+ if( dev )
+ m_dirView->showDevice( dev );
+}
+
+
+void K3bMainWindow::slotVideoCdRip()
+{
+ videoCdRip( 0 );
+}
+
+
+void K3bMainWindow::slotAudioServerError( const QString& error )
+{
+ K3bPassivePopup::showPopup( error, i18n("Audio Output Problem") );
+}
+
+#include "k3b.moc"
+
diff --git a/src/k3b.desktop b/src/k3b.desktop
new file mode 100644
index 0000000..e6c107b
--- /dev/null
+++ b/src/k3b.desktop
@@ -0,0 +1,123 @@
+[Desktop Entry]
+Type=Application
+Exec=k3b %U
+Icon=k3b
+DocPath=k3b/index.html
+GenericName=CD & DVD Burning
+GenericName[af]=CD & DVD Skrywer
+GenericName[ar]= اعداد كتابة القرص المدمج(CD) و القرص المرئي الرقمي (DVD)
+GenericName[bg]=Запис на CD и DVD
+GenericName[bn]=সিডি এবং ডিভিডি লিখন
+GenericName[br]=Skrivañ CD ha DVD
+GenericName[bs]=CD & DVD prženje
+GenericName[ca]=Programa per gravar CDs i DVDs
+GenericName[cs]=Vypalování CD a DVD
+GenericName[da]=Cd & dvd-skriveprogram
+GenericName[de]=CD & DVD-Brennen
+GenericName[el]=Εγγραφή CD & DVD
+GenericName[eo]=KD & DVD enskribo
+GenericName[es]=Grabación de CD y DVD
+GenericName[et]=CD ja DVD kirjutamine
+GenericName[fa]=سوزاندن دیسک فشرده و دی وی دی
+GenericName[fi]=Poltto-ohjelma
+GenericName[fr]=Gravure de CD et DVD
+GenericName[gl]=Gravazón de CDs e DVDs
+GenericName[he]=צרינת תקליטורי CD & DVD
+GenericName[hi]=सीडी & डीवीडी बर्निंग
+GenericName[hu]=CD- és DVD-író
+GenericName[is]=CD og DVD brennsla
+GenericName[it]=Masterizzazione CD e DVD
+GenericName[ja]=CD / DVD 作成
+GenericName[ka]=CD-ის და DVD-ის ჩანაწერა
+GenericName[km]=ការ​ដុត​ស៊ីឌី & ឌីវីឌី
+GenericName[lt]=CD ir DVD kūrimas
+GenericName[mk]=Снимање на CD и DVD
+GenericName[ms]=Membakar CD & DVD
+GenericName[nb]=CD- og DVD-brenning
+GenericName[nds]=Brennen vun CD & DVD
+GenericName[ne]=सीडी र डीभीडी बर्निङ
+GenericName[nl]=CD- en dvd-brandprogramma
+GenericName[nn]=CD- og DVD-brenning
+GenericName[pa]=CD & DVD ਲਿਖਣ ਲਈ
+GenericName[pl]=Nagrywanie płyt CD i DVD
+GenericName[pt]=Gravação de CDs e DVDs
+GenericName[pt_BR]=Queima de CD & DVD
+GenericName[ru]=Запись CD и DVD
+GenericName[sk]=Napaľovanie CD & DVD
+GenericName[sl]=Pisanje CD-jev in DVD-jev
+GenericName[sr]=Резање CD-а и DVD-а
+GenericName[sr@Latn]=Rezanje CD-a i DVD-a
+GenericName[sv]=Cd och dvd-brännprogram
+GenericName[ta]=சிடி எழுதும் தகவல்
+GenericName[tg]=Сабти CD ва DVD
+GenericName[tr]=CD ve DVD Kaydedici
+GenericName[uk]=Запис КД та DVD
+GenericName[uz]=CD va DVD disklarga yozish
+GenericName[uz@cyrillic]=CD ва DVD дискларга ёзиш
+GenericName[zh_CN]=CD & DVD 烧录程序
+GenericName[zh_TW]=CD & DVD 燒錄
+Comment=CD writing program
+Comment[af]=CD skryf program
+Comment[ar]=برنامج لكتابة الاقراص المدمجة CD
+Comment[bg]=Програма за запис на CD
+Comment[bn]=সিডি লিখন প্রোগ্র্যাম
+Comment[br]=Program skriver CD
+Comment[bs]=Program za prženje CDova
+Comment[ca]=Programa gravador de CDs
+Comment[cs]=Program pro vypalování CD
+Comment[da]=Cd-skriveprogram
+Comment[de]=CD-Brennprogramm
+Comment[el]=Πρόγραμμα εγγραφής CD
+Comment[eo]=KD skribilo
+Comment[es]=Programa de grabación de CD
+Comment[et]=CD kirjutamise rakendus
+Comment[fa]=برنامۀ نوشتن دیسک فشرده
+Comment[fi]=Poltto-ohjelma
+Comment[fr]=Programme de gravure de CD
+Comment[gl]=Un programa de gravazón de CDs
+Comment[he]=תוכנית צריבת תקליטורים
+Comment[hi]=सीडी लिखने का प्रोग्राम
+Comment[hu]=CD-író program
+Comment[is]=CD skrifunarforrit
+Comment[it]=Programma di masterizzazione
+Comment[ja]=CD 書き込みプログラム
+Comment[ka]=CD-ის ჩამწერი პროგრამა
+Comment[km]=កម្មវិធី​សរសេរ​ស៊ីឌី
+Comment[lt]=CD įrašymo programa
+Comment[mk]=Програма за снимање на CD
+Comment[ms]=Program menulis CD
+Comment[nb]=CD-brenningsprogram
+Comment[nds]=CD-Schriefprogramm
+Comment[ne]=सीडी लेख्ने कार्यक्रम
+Comment[nl]=CD-brandprogramma
+Comment[nn]=CD-brenneprogram
+Comment[pa]=CD ਲਿਖਣ ਕਾਰਜ
+Comment[pl]=Program do nagrywania płyt CD
+Comment[pt]=Um programa de gravação de CDs
+Comment[pt_BR]=Programa de gravação em CD
+Comment[ru]=Программа записи на CD
+Comment[sk]=CD vypaľovací program
+Comment[sl]=Program za pisanje CD-jev
+Comment[sr]=Програм за писање CD-а
+Comment[sr@Latn]=Program za pisanje CD-a
+Comment[sv]=Cd-brännprogram
+Comment[ta]=குறுந்தகட்டில் எழுதும் நிரல்
+Comment[tg]=Барномаи сабти компакт-дискҳо
+Comment[tr]=CD yazdırma programı
+Comment[uk]=Програма запису КД
+Comment[uz]=Kompakt-diskka yozish dasturi
+Comment[uz@cyrillic]=Компакт-дискка ёзиш дастури
+Comment[xh]=Ubhalo lwe Cd lodweiso Iwenkqubo
+Comment[zh_CN]=CD 刻录程序
+Comment[zh_TW]=CD 燒錄程式
+Comment[zu]=Uhlelo lwemisebenzi olubhala i-CD
+Terminal=false
+Name=K3b
+Name[ar]= K3b
+Name[bn]=কে-থ্রি-বি
+Name[hi]=के3बी
+MimeType=application/x-k3b;application/x-iso;application/x-cue
+X-KDE-StartupNotify=true
+X-KDE-NativeMimeType=application/x-k3b;application/x-iso;application/x-cue
+Categories=KDE;Application;AudioVideo;DiscBurning;
+X-DCOP-ServiceType=Unique
diff --git a/src/k3b.h b/src/k3b.h
new file mode 100644
index 0000000..37532b0
--- /dev/null
+++ b/src/k3b.h
@@ -0,0 +1,330 @@
+/*
+ *
+ * $Id: k3b.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef K3B_H
+#define K3B_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// include files for Qt
+#include <qstrlist.h>
+#include <qworkspace.h>
+#include <qptrlist.h>
+
+// include files for KDE
+#include <kapplication.h>
+#include <kparts/dockmainwindow.h>
+#include <kdockwidget.h>
+#include <kaction.h>
+#include <kurl.h>
+
+class QVBox;
+
+
+// forward declaration of the K3b classes
+class K3bMainWindow;
+class K3bDoc;
+class K3bView;
+class K3bDirView;
+class K3bExternalBinManager;
+class K3bOptionDialog;
+class K3bJob;
+class K3bProjectTabWidget;
+class K3bSongManager;
+class KSystemTray;
+class K3bStatusBarManager;
+class K3bProjectInterface;
+class K3bThemedHeader;
+
+namespace K3bDevice {
+ class DeviceManager;
+ class Device;
+}
+
+
+class K3bMainWindow : public KParts::DockMainWindow
+{
+ Q_OBJECT
+
+ public:
+ /** construtor of K3bMainWindow, calls all init functions to create the application.
+ * @see initMenuBar initToolBar
+ */
+ K3bMainWindow();
+ ~K3bMainWindow();
+
+ /** opens a file specified by commandline option */
+ K3bDoc* openDocument( const KURL& url = KURL() );
+
+ K3bDevice::DeviceManager* deviceManager() const;
+ K3bExternalBinManager* externalBinManager() const;
+ KConfig* config() const { return m_config; }
+ // return main window with browser/cd/dvd view, used for DND
+ K3bDirView* mainWindow() const { return m_dirView; }
+ /**
+ * @returns a pointer to the currently visible view or 0 if no project was created
+ */
+ K3bView* activeView() const;
+ /**
+ * @returns a pointer to the doc associated with the currently visible view or 0 if no project was created
+ */
+ K3bDoc* activeDoc() const;
+
+ const QPtrList<K3bDoc>& projects() const;
+
+ bool eject();
+ void showOptionDialog( int = 0 );
+
+ /** Creates the main view of the KDockMainWindow instance and initializes the MDI view area including any needed
+ * connections.
+ * must be called after construction
+ */
+ void initView();
+
+ KSystemTray* systemTray() const { return m_systemTray; }
+
+ public slots:
+ K3bDoc* slotNewAudioDoc();
+ K3bDoc* slotNewDataDoc();
+ K3bDoc* slotNewMixedDoc();
+ K3bDoc* slotNewVcdDoc();
+ K3bDoc* slotNewMovixDoc();
+ K3bDoc* slotNewMovixDvdDoc();
+ K3bDoc* slotNewDvdDoc();
+ K3bDoc* slotNewVideoDvdDoc();
+ K3bDoc* slotContinueMultisession();
+
+ void slotClearProject();
+
+ void blankCdrw( K3bDevice::Device* );
+ void slotBlankCdrw();
+ void formatDvd( K3bDevice::Device* );
+ void slotFormatDvd();
+ void slotWriteCdImage();
+ void slotWriteCdImage( const KURL& url );
+ void slotWriteDvdIsoImage();
+ void slotWriteDvdIsoImage( const KURL& url );
+ void cdCopy( K3bDevice::Device* );
+ void slotCdCopy();
+ void dvdCopy( K3bDevice::Device* );
+ void slotDvdCopy();
+ void cddaRip( K3bDevice::Device* );
+ void slotCddaRip();
+ void videoDvdRip( K3bDevice::Device* );
+ void slotVideoDvdRip();
+ void videoCdRip( K3bDevice::Device* );
+ void slotVideoCdRip();
+ void slotK3bSetup();
+
+ void slotErrorMessage(const QString&);
+ void slotWarningMessage(const QString&);
+
+ void slotConfigureKeys();
+ void slotShowTips();
+ void slotCheckSystem();
+
+ void addUrls( const KURL::List& urls );
+
+ signals:
+ void initializationInfo( const QString& );
+ void configChanged( KConfig* c );
+
+ protected:
+ /** queryClose is called by KTMainWindow on each closeEvent of a window. Against the
+ * default implementation (only returns true), this overridden function retrieves all modified documents
+ * from the open document list and asks the user to select which files to save before exiting the application.
+ * @see KTMainWindow#queryClose
+ * @see KTMainWindow#closeEvent
+ */
+ virtual bool queryClose();
+
+ /** queryExit is called by KTMainWindow when the last window of the application is going to be closed during the closeEvent().
+ * Against the default implementation that just returns true, this calls saveOptions() to save the settings of the last window's
+ * properties.
+ * @see KTMainWindow#queryExit
+ * @see KTMainWindow#closeEvent
+ */
+ virtual bool queryExit();
+
+ /** saves the window properties for each open window during session end to the session config file, including saving the currently
+ * opened file by a temporary filename provided by KApplication.
+ * @see KTMainWindow#saveProperties
+ */
+ virtual void saveProperties(KConfig *_cfg);
+
+ /** reads the session config file and restores the application's state including the last opened files and documents by reading the
+ * temporary files saved by saveProperties()
+ * @see KTMainWindow#readProperties
+ */
+ virtual void readProperties(KConfig *_cfg);
+
+ /**
+ * checks if doc is modified and asks the user for saving if so.
+ * returns false if the user chose cancel.
+ */
+ bool canCloseDocument( K3bDoc* );
+
+ virtual void showEvent( QShowEvent* e );
+
+ private slots:
+ /** open a file and load it into the document*/
+ void slotFileOpen();
+ /** opens a file from the recent files menu */
+ void slotFileOpenRecent(const KURL& url);
+ /** save a document */
+ void slotFileSave();
+ /** save a document by a new filename*/
+ void slotFileSaveAs();
+ void slotFileSaveAll();
+ /** asks for saving if the file is modified, then closes the actual file and window*/
+ void slotFileClose();
+ void slotFileCloseAll();
+
+ void slotDirTreeDockHidden();
+ void slotContentsDockHidden();
+
+ void slotSettingsConfigure();
+
+ /** checks if the currently visible tab is a k3bview
+ or not and dis- or enables some actions */
+ void slotCurrentDocChanged();
+
+ void slotFileQuit();
+
+ /** toggles the statusbar
+ */
+ void slotViewStatusBar();
+
+ void slotViewDocumentHeader();
+
+ void slotCheckDockWidgetStatus();
+
+ /** changes the statusbar contents for the standard label permanently, used to indicate current actions.
+ * @param text the text that is displayed in the statusbar
+ */
+ void slotStatusMsg(const QString &text);
+
+ void slotShowDirTreeView();
+ void slotShowContentsView();
+ void slotShowMenuBar();
+
+ void slotProjectAddFiles();
+
+ void slotEditToolbars();
+ void slotNewToolBarConfig();
+
+ void slotDataImportSession();
+ void slotDataClearImportedSession();
+ void slotEditBootImages();
+
+ void slotAudioServerError( const QString& error );
+
+ void createClient(K3bDoc* doc);
+
+ /**
+ * Run slotCheckSystem with a timer
+ */
+ void slotCheckSystemTimed();
+
+ private:
+ void fileSave( K3bDoc* doc = 0 );
+ void fileSaveAs( K3bDoc* doc = 0 );
+ void closeProject( K3bDoc* );
+
+ /** save general Options like all bar positions and status as well as the geometry and the recent file list to the configuration
+ * file
+ */
+ void saveOptions();
+ /** read general Options again and initialize all variables like the recent file list */
+ void readOptions();
+
+ /** initializes the KActions of the application */
+ void initActions();
+
+ /** sets up the statusbar for the main window by initialzing a statuslabel.
+ */
+ void initStatusBar();
+
+ bool isCdDvdImageAndIfSoOpenDialog( const KURL& url );
+
+ /** the configuration object of the application */
+ KConfig *m_config;
+
+ /** The MDI-Interface is managed by this tabbed view */
+ K3bProjectTabWidget* m_documentTab;
+
+ // KAction pointers to enable/disable actions
+ KActionMenu* actionFileNewMenu;
+ KAction* actionFileNewAudio;
+ KAction* actionFileNewData;
+ KAction* actionFileNewMixed;
+ KAction* actionFileNewVcd;
+ KAction* actionFileNewMovix;
+ KAction* actionFileNewMovixDvd;
+ KAction* actionFileNewDvd;
+ KAction* actionFileNewVideoDvd;
+ KAction* actionFileContinueMultisession;
+ KAction* actionFileOpen;
+ KRecentFilesAction* actionFileOpenRecent;
+ KAction* actionFileSave;
+ KAction* actionFileSaveAs;
+ KAction* actionFileSaveAll;
+ KAction* actionFileClose;
+ KAction* actionFileCloseAll;
+ KAction* actionFileQuit;
+ KAction* actionSettingsConfigure;
+ KAction* actionSettingsK3bSetup;
+ KAction* actionToolsBlankCdrw;
+ KAction* actionToolsWriteCdImage;
+ KAction* actionToolsCddaRip;
+ KAction* actionToolsVideoDvdRip;
+ KAction* actionToolsVideoCdRip;
+ KAction* actionCdCopy;
+ KAction* actionProjectAddFiles;
+ KToggleAction* actionViewStatusBar;
+ KToggleAction* actionViewDirTreeView;
+ KToggleAction* actionViewContentsView;
+ KToggleAction* actionViewDocumentHeader;
+
+ // project actions
+ QPtrList<KAction> m_dataProjectActions;
+
+ KDockWidget* mainDock;
+ KDockWidget* m_contentsDock;
+ KDockWidget* m_dirTreeDock;
+
+ // The K3b-specific widgets
+ K3bDirView* m_dirView;
+ K3bOptionDialog* m_optionDialog;
+
+ K3bStatusBarManager* m_statusBarManager;
+
+ KSystemTray* m_systemTray;
+
+ bool m_initialized;
+
+ // the funny header
+ K3bThemedHeader* m_documentHeader;
+
+ class Private;
+ Private* d;
+};
+
+#endif // K3B_H
diff --git a/src/k3bappdevicemanager.cpp b/src/k3bappdevicemanager.cpp
new file mode 100644
index 0000000..c21f746
--- /dev/null
+++ b/src/k3bappdevicemanager.cpp
@@ -0,0 +1,304 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bappdevicemanager.h"
+
+#include <k3bdevice.h>
+#include <k3bdevicehandler.h>
+#include <k3bglobals.h>
+#include <k3bapplication.h>
+#include <k3bmediacache.h>
+
+#include <kaction.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <kio/job.h>
+#include <klocale.h>
+#include <kio/global.h>
+#include <kpopupmenu.h>
+
+
+K3bAppDeviceManager::K3bAppDeviceManager( QObject* parent, const char* name )
+ : K3bDevice::DeviceManager( parent, name ),
+ m_currentDevice(0),
+ m_ejectRequested(false)
+{
+ // FIXME: should we pass the mainwindow as watch window here?
+ // Is there a proper way to insert this actioncollection into the mainwindow's?
+ m_actionCollection = new KActionCollection( this );
+
+ // setup actions
+ KActionMenu* devicePopupMenu = new KActionMenu( m_actionCollection, "device_popup" );
+ m_actionDiskInfo = new KAction( i18n("Media &Info"), "info", 0, this, SLOT(diskInfo()),
+ m_actionCollection, "device_diskinfo");
+ m_actionUnmount = new KAction( i18n("&Unmount"), "cdrom_unmount", 0, this, SLOT(unmountDisk()),
+ m_actionCollection, "device_unmount");
+ m_actionMount = new KAction( i18n("&Mount"), "cdrom_mount", 0, this, SLOT(mountDisk()),
+ m_actionCollection, "device_mount");
+ m_actionEject = new KAction( i18n("&Eject"), "", 0, this, SLOT(ejectDisk()),
+ m_actionCollection, "device_eject");
+ m_actionLoad = new KAction( i18n("L&oad"), "", 0, this, SLOT(loadDisk()),
+ m_actionCollection, "device_load");
+// KAction* actionUnlock = new KAction( i18n("Un&lock"), "", 0, this, SLOT(unlockDevice()),
+// m_actionCollection, "device_unlock" );
+// KAction* actionlock = new KAction( i18n("Loc&k"), "", 0, this, SLOT(lockDevice()),
+// m_actionCollection, "device_lock" );
+ m_actionSetReadSpeed = new KAction( i18n("Set Read Speed..."), "", 0, this, SLOT(setReadSpeed()),
+ m_actionCollection, "device_set_read_speed" );
+
+ m_actionDiskInfo->setToolTip( i18n("Display generic medium information") );
+ m_actionUnmount->setToolTip( i18n("Unmount the medium") );
+ m_actionMount->setToolTip( i18n("Mount the medium") );
+ m_actionEject->setToolTip( i18n("Eject the medium") );
+ m_actionLoad->setToolTip( i18n("(Re)Load the medium") );
+ m_actionSetReadSpeed->setToolTip( i18n("Force the drive's read speed") );
+
+ devicePopupMenu->insert( m_actionDiskInfo );
+ devicePopupMenu->insert( new KActionSeparator( this ) );
+ devicePopupMenu->insert( m_actionUnmount );
+ devicePopupMenu->insert( m_actionMount );
+ devicePopupMenu->insert( new KActionSeparator( this ) );
+ devicePopupMenu->insert( m_actionEject );
+ devicePopupMenu->insert( m_actionLoad );
+// devicePopupMenu->insert( new KActionSeparator( this ) );
+// devicePopupMenu->insert( actionUnlock );
+// devicePopupMenu->insert( actionlock );
+ devicePopupMenu->insert( new KActionSeparator( this ) );
+ devicePopupMenu->insert( m_actionSetReadSpeed );
+
+ setCurrentDevice( 0 );
+}
+
+
+void K3bAppDeviceManager::setMediaCache( K3bMediaCache* c )
+{
+ connect( c, SIGNAL(mediumChanged(K3bDevice::Device*)),
+ this, SLOT(slotMediumChanged(K3bDevice::Device*)) );
+}
+
+
+int K3bAppDeviceManager::scanBus()
+{
+ return K3bDevice::DeviceManager::scanBus();
+}
+
+
+K3bDevice::Device* K3bAppDeviceManager::currentDevice() const
+{
+ return m_currentDevice;
+}
+
+
+void K3bAppDeviceManager::clear()
+{
+ // make sure we do not use a deleted device
+ m_currentDevice = 0;
+ K3bDevice::DeviceManager::clear();
+}
+
+
+void K3bAppDeviceManager::removeDevice( const QString& dev )
+{
+ if( m_currentDevice == findDevice(dev) )
+ m_currentDevice = 0;
+
+ K3bDevice::DeviceManager::removeDevice( dev );
+
+ if( !m_currentDevice )
+ setCurrentDevice( allDevices().getFirst() );
+}
+
+
+K3bAppDeviceManager::~K3bAppDeviceManager()
+{
+}
+
+
+void K3bAppDeviceManager::slotMediumChanged( K3bDevice::Device* dev )
+{
+ m_actionDiskInfo->setEnabled( dev != 0 );
+ m_actionUnmount->setEnabled( dev != 0 );
+ m_actionMount->setEnabled( dev != 0 );
+ m_actionEject->setEnabled( dev != 0 );
+ m_actionLoad->setEnabled( dev != 0 );
+ m_actionSetReadSpeed->setEnabled( dev != 0 );
+
+ if( dev && dev == currentDevice() ) {
+ bool mounted = K3b::isMounted( dev );
+ bool mediumMountable = k3bappcore->mediaCache()->medium( dev ).content() & K3bMedium::CONTENT_DATA;
+ m_actionMount->setEnabled( !mounted && mediumMountable );
+ m_actionUnmount->setEnabled( mounted );
+ }
+}
+
+
+void K3bAppDeviceManager::setCurrentDevice( K3bDevice::Device* dev )
+{
+ if( dev && dev != m_currentDevice ) {
+ m_currentDevice = dev;
+ emit currentDeviceChanged( dev );
+ }
+
+ slotMediumChanged( dev );
+}
+
+
+void K3bAppDeviceManager::diskInfo()
+{
+ if( currentDevice() ) {
+ emit detectingDiskInfo( currentDevice() );
+ }
+}
+
+
+void K3bAppDeviceManager::unlockDevice()
+{
+ if( currentDevice() )
+ K3bDevice::unblock( currentDevice() );
+}
+
+
+void K3bAppDeviceManager::lockDevice()
+{
+ if( currentDevice() )
+ K3bDevice::block( currentDevice() );
+}
+
+
+void K3bAppDeviceManager::mountDisk()
+{
+ if ( currentDevice() ) {
+ // FIXME: make this non-blocking
+ if( !K3b::isMounted( currentDevice() ) )
+ K3b::mount( currentDevice() );
+
+ emit mountFinished( KIO::findDeviceMountPoint( currentDevice()->blockDeviceName() ) );
+ }
+}
+
+
+void K3bAppDeviceManager::unmountDisk()
+{
+ if ( currentDevice() ) {
+ // FIXME: make this non-blocking
+ if( K3b::isMounted( currentDevice() ) )
+ emit unmountFinished( K3b::unmount( currentDevice() ) );
+ else
+ emit unmountFinished( true );
+ }
+}
+
+
+void K3bAppDeviceManager::ejectDisk()
+{
+ // FIXME: make this non-blocking
+ if ( currentDevice() )
+ K3b::eject( currentDevice() ); // just ignore errors here
+}
+
+
+void K3bAppDeviceManager::loadDisk()
+{
+ if( currentDevice() )
+ K3bDevice::reload( currentDevice() );
+}
+
+
+void K3bAppDeviceManager::setReadSpeed()
+{
+ if( currentDevice() ) {
+ bool ok = false;
+ int s = KInputDialog::getInteger( i18n("CD Read Speed"),
+ i18n("<p>Please enter the preferred read speed for <b>%1</b>. "
+ "This speed will be used for the currently mounted "
+ "medium."
+ "<p>This is especially useful to slow down the drive when "
+ "watching movies which are read directly from the drive "
+ "and the spinning noise is intrusive."
+ "<p>Be aware that this has no influence on K3b since it will "
+ "change the reading speed again when copying CDs or DVDs.")
+ .arg(currentDevice()->vendor() + " " + currentDevice()->description()),
+ 12,
+ 1,
+ currentDevice()->maxReadSpeed(),
+ 1,
+ 10,
+ &ok,
+ 0 );
+ if( ok ) {
+ if( !currentDevice()->setSpeed( s*175, 0xFFFF ) )
+ KMessageBox::error( 0, i18n("Setting the read speed failed.") );
+ }
+ }
+}
+
+
+void K3bAppDeviceManager::diskInfo( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ diskInfo();
+}
+
+
+void K3bAppDeviceManager::unlockDevice( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ unlockDevice();
+}
+
+
+void K3bAppDeviceManager::lockDevice( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ lockDevice();
+}
+
+
+void K3bAppDeviceManager::mountDisk( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ mountDisk();
+}
+
+
+void K3bAppDeviceManager::unmountDisk( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ unmountDisk();
+}
+
+
+void K3bAppDeviceManager::ejectDisk( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ ejectDisk();
+}
+
+
+void K3bAppDeviceManager::loadDisk( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ loadDisk();
+}
+
+
+void K3bAppDeviceManager::setReadSpeed( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ setReadSpeed();
+}
+
+#include "k3bappdevicemanager.moc"
diff --git a/src/k3bappdevicemanager.h b/src/k3bappdevicemanager.h
new file mode 100644
index 0000000..419a8b3
--- /dev/null
+++ b/src/k3bappdevicemanager.h
@@ -0,0 +1,119 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_APP_DEVICE_MANAGER_H_
+#define _K3B_APP_DEVICE_MANAGER_H_
+
+class KActionCollection;
+class KAction;
+class K3bMediaCache;
+
+namespace K3bDevice {
+ class Device;
+ class DiskInfo;
+ class DiskInfoDetector;
+}
+
+namespace KIO {
+ class Job;
+}
+
+#include <k3bdevicemanager.h>
+
+
+/**
+ * Enhanced device manager which can do some additional actions
+ * and maintains a current device
+ */
+class K3bAppDeviceManager : public K3bDevice::DeviceManager
+{
+ Q_OBJECT
+
+ public:
+ K3bAppDeviceManager( QObject* parent = 0, const char* name = 0 );
+ ~K3bAppDeviceManager();
+
+ K3bDevice::Device* currentDevice() const;
+ KActionCollection* actionCollection() const { return m_actionCollection; }
+ void setMediaCache( K3bMediaCache* c );
+
+ signals:
+ void currentDeviceChanged( K3bDevice::Device* );
+
+ /**
+ * Emitted when starting to detect the diskinfo. This may be used to show some info
+ * to the user since deteting the diskinfo might take some time.
+ */
+ void detectingDiskInfo( K3bDevice::Device* );
+ void diskInfoReady( K3bDevice::DiskInfoDetector* );
+
+ void mountFinished( const QString& mountPoint );
+ void unmountFinished( bool success );
+
+ public slots:
+ /**
+ * \reimplemeted for internal reasons. The API is unaffected.
+ */
+ void clear();
+
+ /**
+ * \reimplemeted for internal reasons. The API is unaffected.
+ */
+ void removeDevice( const QString& );
+
+ /**
+ * \reimplemeted for internal reasons. The API is unaffected.
+ */
+ int scanBus();
+
+ void setCurrentDevice( K3bDevice::Device* );
+
+ void diskInfo();
+ void unlockDevice();
+ void lockDevice();
+ void mountDisk();
+ void unmountDisk();
+ void ejectDisk();
+ void loadDisk();
+ void setReadSpeed();
+
+ void diskInfo( K3bDevice::Device* );
+ void unlockDevice( K3bDevice::Device* );
+ void lockDevice( K3bDevice::Device* );
+ void mountDisk( K3bDevice::Device* );
+ void unmountDisk( K3bDevice::Device* );
+ void ejectDisk( K3bDevice::Device* );
+ void loadDisk( K3bDevice::Device* );
+ void setReadSpeed( K3bDevice::Device* );
+
+ private slots:
+ void slotMediumChanged( K3bDevice::Device* dev );
+
+ private:
+ KAction* m_actionDiskInfo;
+ KAction* m_actionUnmount;
+ KAction* m_actionMount;
+ KAction* m_actionEject;
+ KAction* m_actionLoad;
+ KAction* m_actionSetReadSpeed;
+
+ mutable K3bDevice::Device* m_currentDevice;
+ KActionCollection* m_actionCollection;
+ K3bDevice::DiskInfoDetector* m_diskInfoDetector;
+
+ bool m_ejectRequested;
+};
+
+#endif
diff --git a/src/k3bapplication.cpp b/src/k3bapplication.cpp
new file mode 100644
index 0000000..4b517ea
--- /dev/null
+++ b/src/k3bapplication.cpp
@@ -0,0 +1,451 @@
+/*
+ *
+ * $Id: k3bapplication.cpp 802344 2008-04-29 07:45:46Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bapplication.h"
+#include "k3b.h"
+#include "k3bsplash.h"
+#include "k3baudioserver.h"
+#include "k3binterface.h"
+#include "k3bjobinterface.h"
+#include "k3bprojectmanager.h"
+#include "k3bappdevicemanager.h"
+#include "k3bmediacache.h"
+#include "k3bpassivepopup.h"
+#include "k3blsofwrapperdialog.h"
+#include "k3bfirstrun.h"
+
+#include <k3bcore.h>
+#include <k3bdevicemanager.h>
+#include <k3bhalconnection.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bdefaultexternalprograms.h>
+#include <k3bglobals.h>
+#include <k3bversion.h>
+#include <k3bdoc.h>
+#include "k3bsystemproblemdialog.h"
+#include <k3bthread.h>
+#include <k3bpluginmanager.h>
+#include <k3bthememanager.h>
+#include <k3bmsf.h>
+#include <k3bmovixprogram.h>
+#include <k3bview.h>
+#include <k3bjob.h>
+
+#include <ktip.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <dcopclient.h>
+#include <kstandarddirs.h>
+#include <kstartupinfo.h>
+#include <kmessagebox.h>
+
+#include <qguardedptr.h>
+#include <qtimer.h>
+#include <qvaluelist.h>
+#include <qcstring.h>
+
+
+K3bApplication::Core* K3bApplication::Core::s_k3bAppCore = 0;
+
+
+K3bApplication::K3bApplication()
+ : KUniqueApplication(),
+ m_mainWindow(0),
+ m_needToInit(true)
+{
+ // insert library i18n data
+ KGlobal::locale()->insertCatalogue( "libk3bdevice" );
+ KGlobal::locale()->insertCatalogue( "libk3b" );
+
+ m_core = new Core( this );
+
+ // TODO: move to K3bCore?
+ // from this point on available through K3bAudioServer::instance()
+ m_audioServer = new K3bAudioServer( this, "K3bAudioServer" );
+
+ connect( m_core, SIGNAL(initializationInfo(const QString&)),
+ SIGNAL(initializationInfo(const QString&)) );
+
+ connect( this, SIGNAL(shutDown()), SLOT(slotShutDown()) );
+}
+
+
+K3bApplication::~K3bApplication()
+{
+ // we must not delete m_mainWindow here, QApplication takes care of it
+}
+
+
+void K3bApplication::init()
+{
+ KConfigGroup generalOptions( config(), "General Options" );
+
+ QGuardedPtr<K3bSplash> splash;
+ if( !isRestored() ) {
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if( generalOptions.readBoolEntry("Show splash", true) && args->isSet( "splash" ) ) {
+ // we need the correct splash pic
+ m_core->m_themeManager->readConfig( config() );
+
+ splash = new K3bSplash( 0 );
+ splash->connect( this, SIGNAL(initializationInfo(const QString&)), SLOT(addInfo(const QString&)) );
+
+ // kill the splash after 5 seconds
+ QTimer::singleShot( 5000, splash, SLOT(close()) );
+
+ splash->show();
+ qApp->processEvents();
+ }
+ }
+
+ //
+ // Load device, external programs, and stuff.
+ //
+ m_core->init();
+ m_core->readSettings( config() );
+
+ m_core->deviceManager()->printDevices();
+
+ m_audioServer->setOutputMethod( generalOptions.readEntry( "Audio Output System", "arts" ).local8Bit() );
+
+ emit initializationInfo( i18n("Creating GUI...") );
+
+ m_mainWindow = new K3bMainWindow();
+ m_core->m_mainWindow = m_mainWindow;
+ m_core->interface()->setMainWindow( m_mainWindow );
+
+ if( isRestored() ) {
+ // we only have one single mainwindow to restore
+ m_mainWindow->restore(1);
+ }
+ else {
+ setMainWidget( m_mainWindow );
+
+ m_mainWindow->show();
+
+ emit initializationInfo( i18n("Ready.") );
+
+ emit initializationDone();
+
+ //K3bFirstRun::run( m_mainWindow );
+
+ if( K3bSystemProblemDialog::readCheckSystemConfig() ) {
+ emit initializationInfo( i18n("Checking System") );
+ K3bSystemProblemDialog::checkSystem( m_mainWindow );
+ }
+
+ if( processCmdLineArgs() )
+ KTipDialog::showTip( m_mainWindow );
+ }
+
+ // write the current version to make sure checks such as K3bSystemProblemDialog::readCheckSystemConfig
+ // use a proper value
+ generalOptions.writeEntry( "config version", m_core->version() );
+}
+
+
+int K3bApplication::newInstance()
+{
+ if( m_needToInit ) {
+ // init();
+ m_needToInit = false;
+ }
+ else
+ processCmdLineArgs();
+
+ return KUniqueApplication::newInstance();
+}
+
+
+bool K3bApplication::processCmdLineArgs()
+{
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ bool showTips = true;
+ bool dialogOpen = false;
+
+ if( k3bcore->jobsRunning() > 0 ) {
+ K3bPassivePopup::showPopup( i18n("K3b is currently busy and cannot start any other operations."),
+ i18n("K3b is busy"),
+ K3bPassivePopup::Information );
+ return true;
+ }
+
+ K3bDoc* doc = 0;
+ if( args->isSet( "datacd" ) ) {
+ doc = m_mainWindow->slotNewDataDoc();
+ }
+ else if( args->isSet( "audiocd" ) ) {
+ doc = m_mainWindow->slotNewAudioDoc();
+ }
+ else if( args->isSet( "mixedcd" ) ) {
+ doc = m_mainWindow->slotNewMixedDoc();
+ }
+ else if( args->isSet( "videocd" ) ) {
+ doc = m_mainWindow->slotNewVcdDoc();
+ }
+ else if( args->isSet( "emovixcd" ) ) {
+ doc = m_mainWindow->slotNewMovixDoc();
+ }
+ else if( args->isSet( "datadvd" ) ) {
+ doc = m_mainWindow->slotNewDvdDoc();
+ }
+ else if( args->isSet( "emovixdvd" ) ) {
+ doc = m_mainWindow->slotNewMovixDvdDoc();
+ }
+ else if( args->isSet( "videodvd" ) ) {
+ doc = m_mainWindow->slotNewVideoDvdDoc();
+ }
+
+ // if we created a doc the urls are used to populate it
+ if( doc ) {
+ KURL::List urls;
+ for( int i = 0; i < args->count(); i++ )
+ urls.append( args->url(i) );
+ dynamic_cast<K3bView*>( doc->view() )->addUrls( urls );
+ }
+ // otherwise we open them as documents
+ else {
+ for( int i = 0; i < args->count(); i++ ) {
+ m_mainWindow->openDocument( args->url(i) );
+ }
+ }
+
+ // we only allow one dialog to be opened
+ if( args->isSet( "cdimage" ) ) {
+ showTips = false;
+ dialogOpen = true;
+ if( k3bcore->jobsRunning() == 0 ) {
+ m_mainWindow->slotWriteCdImage( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "cdimage" ) ) ) );
+ }
+ }
+ else if( args->isSet( "dvdimage" ) ) {
+ showTips = false;
+ dialogOpen = true;
+ if( k3bcore->jobsRunning() == 0 ) {
+ m_mainWindow->slotWriteDvdIsoImage( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "dvdimage" ) ) ) );
+ }
+ }
+ else if( args->isSet( "image" ) ) {
+ showTips = false;
+ dialogOpen = true;
+ KURL url = KURL::fromPathOrURL( QFile::decodeName( args->getOption( "image" ) ) );
+ if( k3bcore->jobsRunning() == 0 ) {
+ if( K3b::filesize( url ) > 1000*1024*1024 )
+ m_mainWindow->slotWriteDvdIsoImage( url );
+ else
+ m_mainWindow->slotWriteCdImage( url );
+ }
+ }
+ else if( args->isSet("copycd") ) {
+ showTips = false;
+ dialogOpen = true;
+ qApp->processEvents();
+ m_mainWindow->cdCopy( K3b::urlToDevice( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "copycd" ) ) ) ) );
+ }
+ else if( args->isSet("copydvd") ) {
+ showTips = false;
+ dialogOpen = true;
+ m_mainWindow->dvdCopy( K3b::urlToDevice( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "copydvd" ) ) ) ) );
+ }
+ else if( args->isSet("erasecd") ) {
+ showTips = false;
+ dialogOpen = true;
+ m_mainWindow->blankCdrw( K3b::urlToDevice( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "erasecd" ) ) ) ) );
+ }
+ else if( args->isSet("formatdvd") ) {
+ showTips = false;
+ dialogOpen = true;
+ m_mainWindow->formatDvd( K3b::urlToDevice( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "formatdvd" ) ) ) ) );
+ }
+
+ // no dialog used here
+ if( args->isSet( "cddarip" ) ) {
+ m_mainWindow->cddaRip( K3b::urlToDevice( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "cddarip" ) ) ) ) );
+ }
+ else if( args->isSet( "videodvdrip" ) ) {
+ m_mainWindow->videoDvdRip( K3b::urlToDevice( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "videodvdrip" ) ) ) ) );
+ }
+ else if( args->isSet( "videocdrip" ) ) {
+ m_mainWindow->videoCdRip( K3b::urlToDevice( KURL::fromPathOrURL( QFile::decodeName( args->getOption( "videocdrip" ) ) ) ) );
+ }
+
+ if( !dialogOpen && args->isSet( "burn" ) ) {
+ if( m_core->projectManager()->activeDoc() ) {
+ showTips = false;
+ dialogOpen = true;
+ static_cast<K3bView*>( m_core->projectManager()->activeDoc()->view() )->slotBurn();
+ }
+ }
+
+ // FIXME: seems not like the right place...
+ if( args->isSet( "ao" ) )
+ if( !m_audioServer->setOutputMethod( args->getOption( "ao" ) ) )
+ K3bPassivePopup::showPopup( i18n("Could not find Audio Output plugin '%1'").arg( args->getOption("ao") ),
+ i18n("Initialization Problem"),
+ K3bPassivePopup::Warning );
+
+ args->clear();
+
+ return showTips;
+}
+
+
+void K3bApplication::slotShutDown()
+{
+ k3bappcore->mediaCache()->clearDeviceList();
+ K3bThread::waitUntilFinished();
+}
+
+
+
+K3bApplication::Core::Core( QObject* parent )
+ : K3bCore( parent ),
+ m_appDeviceManager(0),
+ m_mediaCache(0)
+{
+ s_k3bAppCore = this;
+ m_themeManager = new K3bThemeManager( this );
+ m_projectManager = new K3bProjectManager( this );
+ // we need the themes on startup (loading them is fast anyway :)
+ m_themeManager->loadThemes();
+
+ m_jobInterface = new K3bJobInterface( this );
+ m_interface = new K3bInterface();
+ dcopClient()->setDefaultObject( m_interface->objId() );
+}
+
+
+K3bApplication::Core::~Core()
+{
+}
+
+
+void K3bApplication::Core::initDeviceManager()
+{
+ if( !m_appDeviceManager ) {
+ // our very own special device manager
+ m_appDeviceManager = new K3bAppDeviceManager( this );
+ }
+ if( !m_mediaCache ) {
+ // create the media cache but do not connect it to the device manager
+ // yet to speed up application start. We connect it in init()
+ // once the devicemanager has scanned for devices.
+ m_mediaCache = new K3bMediaCache( this );
+ }
+
+ m_appDeviceManager->setMediaCache( m_mediaCache );
+}
+
+
+K3bDevice::DeviceManager* K3bApplication::Core::deviceManager() const
+{
+ return appDeviceManager();
+}
+
+
+KConfig* K3bApplication::Core::config() const
+{
+ return kapp->config();
+}
+
+
+void K3bApplication::Core::init()
+{
+ //
+ // The eMovix program is a special case which is not part of
+ // the default programs handled by K3bCore
+ //
+ initExternalBinManager();
+ externalBinManager()->addProgram( new K3bMovixProgram() );
+ externalBinManager()->addProgram( new K3bNormalizeProgram() );
+ K3b::addTranscodePrograms( externalBinManager() );
+ K3b::addVcdimagerPrograms( externalBinManager() );
+
+ K3bCore::init();
+
+ mediaCache()->buildDeviceList( deviceManager() );
+
+ connect( deviceManager(), SIGNAL(changed(K3bDevice::DeviceManager*)),
+ mediaCache(), SLOT(buildDeviceList(K3bDevice::DeviceManager*)) );
+}
+
+
+void K3bApplication::Core::readSettings( KConfig* cnf )
+{
+ K3bCore::readSettings( cnf );
+
+ KConfig* c = cnf;
+ if( !c )
+ c = config();
+
+ m_themeManager->readConfig( config() );
+}
+
+
+void K3bApplication::Core::saveSettings( KConfig* cnf )
+{
+ if( !cnf )
+ cnf = config();
+
+ K3bCore::saveSettings( cnf );
+ m_themeManager->saveConfig( cnf );
+}
+
+
+bool K3bApplication::Core::internalBlockDevice( K3bDevice::Device* dev )
+{
+ if( K3bCore::internalBlockDevice( dev ) ) {
+ if( mediaCache() ) {
+ m_deviceBlockMap[dev] = mediaCache()->blockDevice( dev );
+ }
+
+#ifdef HAVE_HAL
+ if( K3bDevice::HalConnection::instance()->lock( dev ) != K3bDevice::HalConnection::org_freedesktop_Hal_Success )
+ kdDebug() << "(K3bInterferingSystemsHandler) HAL lock failed." << endl;
+#endif
+
+ //
+ // Check if the device is in use
+ //
+ // FIXME: Use the top level widget as parent
+ K3bLsofWrapperDialog::checkDevice( dev );
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+void K3bApplication::Core::internalUnblockDevice( K3bDevice::Device* dev )
+{
+ if( mediaCache() ) {
+ mediaCache()->unblockDevice( dev, m_deviceBlockMap[dev] );
+ m_deviceBlockMap.erase( dev );
+ }
+
+#ifdef HAVE_HAL
+ K3bDevice::HalConnection::instance()->unlock( dev );
+#endif
+
+ K3bCore::internalUnblockDevice( dev );
+}
+
+#include "k3bapplication.moc"
diff --git a/src/k3bapplication.h b/src/k3bapplication.h
new file mode 100644
index 0000000..8dafac1
--- /dev/null
+++ b/src/k3bapplication.h
@@ -0,0 +1,156 @@
+/*
+ *
+ * $Id: k3bapplication.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_APPLICATION_H_
+#define _K3B_APPLICATION_H_
+
+#include <kuniqueapplication.h>
+#include <k3bcore.h>
+
+#include <qmap.h>
+
+#define k3bappcore K3bApplication::Core::k3bAppCore()
+
+
+class K3bMainWindow;
+class K3bInterface;
+class K3bJobInterface;
+class K3bAudioServer;
+class K3bThemeManager;
+class K3bProjectManager;
+class K3bAppDeviceManager;
+class K3bMediaCache;
+
+
+class K3bApplication : public KUniqueApplication
+{
+ Q_OBJECT
+
+ public:
+ K3bApplication();
+ ~K3bApplication();
+
+ int newInstance();
+
+ class Core;
+
+ public slots:
+ void init();
+
+ signals:
+ void initializationInfo( const QString& );
+ void initializationDone();
+
+ private slots:
+ void slotShutDown();
+
+ private:
+ bool processCmdLineArgs();
+
+ Core* m_core;
+ K3bAudioServer* m_audioServer;
+ K3bMainWindow* m_mainWindow;
+
+ bool m_needToInit;
+};
+
+
+/**
+ * The application's core which extends K3bCore with some additional features
+ * like the thememanager or an enhanced device manager.
+ */
+class K3bApplication::Core : public K3bCore
+{
+ Q_OBJECT
+
+ public:
+ Core( QObject* parent );
+ ~Core();
+
+ void init();
+
+ // make sure the libk3b uses the same configuration
+ // needed since the lib still depends on K3bCore::config
+ // the goal is to make the lib independent from the config
+ KConfig* config() const;
+
+ void readSettings( KConfig* c = 0 );
+ void saveSettings( KConfig* c = 0 );
+
+ /**
+ * \reimplemented from K3bCore. We use our own devicemanager here.
+ */
+ K3bDevice::DeviceManager* deviceManager() const;
+
+ K3bAppDeviceManager* appDeviceManager() const { return m_appDeviceManager; }
+
+ K3bThemeManager* themeManager() const { return m_themeManager; }
+
+ K3bProjectManager* projectManager() const { return m_projectManager; }
+
+ K3bMediaCache* mediaCache() const { return m_mediaCache; }
+
+ K3bMainWindow* k3bMainWindow() const { return m_mainWindow; }
+
+ K3bInterface* interface() const { return m_interface; }
+
+ K3bJobInterface* jobInterface() const { return m_jobInterface; }
+
+ static Core* k3bAppCore() { return s_k3bAppCore; }
+
+ signals:
+ /**
+ * This is used for showing info in the K3b splashscreen
+ */
+ void initializationInfo( const QString& );
+
+ /**
+ * Any component may request busy info
+ * In the K3b main app this will be displayed
+ * as a moving square in the taskbar
+ *
+ * FIXME: this is bad design
+ */
+ void busyInfoRequested( const QString& );
+
+ /**
+ * FIXME: this is bad design
+ */
+ void busyFinishRequested();
+
+ private:
+ void initDeviceManager();
+
+ bool internalBlockDevice( K3bDevice::Device* );
+ void internalUnblockDevice( K3bDevice::Device* );
+
+ K3bInterface* m_interface;
+ K3bJobInterface* m_jobInterface;
+
+ K3bThemeManager* m_themeManager;
+ K3bMainWindow* m_mainWindow;
+ K3bProjectManager* m_projectManager;
+ K3bAppDeviceManager* m_appDeviceManager;
+ K3bMediaCache* m_mediaCache;
+
+ QMap<K3bDevice::Device*, int> m_deviceBlockMap;
+
+ static Core* s_k3bAppCore;
+
+ friend class K3bApplication;
+};
+
+#endif
diff --git a/src/k3baudioplayer.cpp b/src/k3baudioplayer.cpp
new file mode 100644
index 0000000..645b3cf
--- /dev/null
+++ b/src/k3baudioplayer.cpp
@@ -0,0 +1,663 @@
+/*
+ *
+ * $Id: k3baudioplayer.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3baudioplayer.h"
+#include <k3bmsf.h>
+#include "kcutlabel.h"
+
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qdatetime.h>
+#include <qfont.h>
+#include <qslider.h>
+#include <qlistview.h>
+#include <qfile.h>
+#include <qpalette.h>
+#include <qheader.h>
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qptrlist.h>
+#include <kurldrag.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kaction.h>
+
+#include <string.h>
+
+#ifdef WITH_ARTS
+#include <arts/artsflow.h>
+#endif
+
+#include <kdebug.h>
+
+using namespace std;
+
+K3bPlayListViewItem::K3bPlayListViewItem( const QString& filename, QListView* parent )
+ : KListViewItem( parent ), m_filename( filename )
+{
+ m_length = 0;
+ m_bActive = false;
+}
+
+
+K3bPlayListViewItem::K3bPlayListViewItem( const QString& filename, QListView* parent, QListViewItem* after )
+ : KListViewItem( parent, after ), m_filename( filename )
+{
+ m_length = 0;
+ m_bActive = false;
+}
+
+
+K3bPlayListViewItem::~K3bPlayListViewItem()
+{
+}
+
+
+QString K3bPlayListViewItem::text( int c ) const
+{
+ switch( c ) {
+ case 0:
+ {
+ int pos = m_filename.findRev("/");
+ if( pos >= 0 )
+ return m_filename.mid(pos+1);
+ return m_filename;
+ }
+
+ case 1:
+ if( m_length > 0 )
+ return K3b::Msf(m_length).toString(false);
+
+ default:
+ return "";
+ }
+}
+
+
+void K3bPlayListViewItem::paintCell( QPainter* p, const QColorGroup& cg, int c, int w, int a )
+{
+ if( m_bActive ) {
+ // change the color of the text:
+ // change roles: Text, HighlightedText, HighLight
+ QColorGroup newCg( cg );
+
+ // we assume the user has not configured a very dark color as base color
+ newCg.setColor( QColorGroup::Text, red );
+ newCg.setColor( QColorGroup::Highlight, red );
+ newCg.setColor( QColorGroup::HighlightedText, white );
+
+ KListViewItem::paintCell( p, newCg, c, w, a );
+ }
+ else
+ KListViewItem::paintCell( p, cg, c, w, a );
+}
+
+
+K3bPlayListView::K3bPlayListView( QWidget* parent, const char* name )
+ : KListView( parent, name )
+{
+ addColumn( i18n("Filename") );
+ addColumn( i18n("Length") );
+ setAllColumnsShowFocus( true );
+ setAcceptDrops( true );
+ setDropVisualizer( true );
+ setDragEnabled(true);
+ setItemsMovable( true );
+ header()->setClickEnabled( false );
+ setSorting( -1 );
+}
+
+
+K3bPlayListView::~K3bPlayListView()
+{
+}
+
+
+bool K3bPlayListView::acceptDrag( QDropEvent* e ) const
+{
+ // we accept textdrag (urls) and moved items (supported by KListView)
+ return KURLDrag::canDecode(e) || KListView::acceptDrag(e);
+}
+
+
+QDragObject* K3bPlayListView::dragObject()
+{
+ QPtrList<QListViewItem> list = selectedItems();
+
+ if( list.isEmpty() )
+ return 0;
+
+ QPtrListIterator<QListViewItem> it(list);
+ KURL::List urls;
+
+ for( ; it.current(); ++it )
+ urls.append( KURL( ((K3bPlayListViewItem*)it.current())->filename() ) );
+
+ return KURLDrag::newDrag( urls, viewport() );
+}
+
+
+K3bAudioPlayer::K3bAudioPlayer( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+#ifdef WITH_ARTS
+, m_playObject( Arts::PlayObject::null() )
+#endif
+{
+ m_currentItem = 0L;
+ // initialize
+ // ------------------------------------------------------------------------
+ m_labelFilename = new KCutLabel( i18n("no file"), this );
+ m_labelOverallTime = new QLabel( "00:00", this );
+ m_labelCurrentTime = new QLabel( "00:00", this );
+
+ m_viewPlayList = new K3bPlayListView( this );
+
+ m_labelOverallTime->setAlignment( AlignHCenter | AlignVCenter );
+ m_labelCurrentTime->setAlignment( AlignHCenter | AlignVCenter );
+ m_labelOverallTime->setFrameStyle( QFrame::StyledPanel | QFrame::Plain );
+ m_labelCurrentTime->setFrameStyle( QFrame::StyledPanel | QFrame::Plain );
+ m_labelFilename->setFrameStyle( QFrame::StyledPanel | QFrame::Plain );
+ m_labelOverallTime->setPalette( QPalette( QColor(238, 238, 205) ) );
+ m_labelCurrentTime->setPalette( QPalette( QColor(238, 238, 205) ) );
+ m_labelFilename->setPalette( QPalette( QColor(238, 238, 205) ) );
+
+ m_buttonPlay = new QToolButton( this );
+ m_buttonPause = new QToolButton( this );
+ m_buttonStop = new QToolButton( this );
+ m_buttonPlay->setIconSet( SmallIconSet("player_play") );
+ m_buttonPause->setIconSet( SmallIconSet("player_pause") );
+ m_buttonStop->setIconSet( SmallIconSet("player_stop") );
+ m_buttonForward = new QToolButton( this );
+ m_buttonBack = new QToolButton( this );
+ m_buttonForward->setIconSet( SmallIconSet("player_end") );
+ m_buttonBack->setIconSet( SmallIconSet("player_start") );
+
+ m_seekSlider = new QSlider( QSlider::Horizontal, this );
+
+ m_updateTimer = new QTimer( this );
+ // ------------------------------------------------------------------------
+
+ // layout
+ // ------------------------------------------------------------------------
+ QGridLayout* grid = new QGridLayout( this );
+ grid->setSpacing( 2 );
+ grid->setMargin( 0 );
+
+ grid->addWidget( m_buttonPlay, 1, 0 );
+ grid->addWidget( m_buttonPause, 1, 1 );
+ grid->addWidget( m_buttonStop, 1, 2 );
+ grid->addColSpacing( 3, 5 );
+ grid->addWidget( m_buttonBack, 1, 4 );
+ grid->addWidget( m_buttonForward, 1, 5 );
+
+ grid->addMultiCellWidget( m_labelFilename, 0, 0, 0, 6 );
+
+ grid->addMultiCellWidget( m_seekSlider, 1, 1, 6, 8 );
+
+ grid->addWidget( m_labelCurrentTime, 0, 7 );
+ grid->addWidget( m_labelOverallTime, 0, 8 );
+
+ grid->addMultiCellWidget( m_viewPlayList, 2, 2, 0, 8 );
+ grid->setRowStretch( 2, 1 );
+ grid->setColStretch( 6, 1 );
+ // ------------------------------------------------------------------------
+
+
+ // actions
+ // ------------------------------------------------------------------------
+ m_actionRemove = new KAction( i18n( "Remove" ), "editdelete",
+ Key_Delete, this, SLOT(slotRemoveSelected()),
+ this, "audioplayer_remove" );
+ m_actionClear = new KAction( i18n( "Clear List" ), "editclear",
+ 0, this, SLOT(clear()),
+ this, "audioplayer_clear" );
+
+ m_contextMenu = new KActionMenu( this, "audio_player_menu" );
+ m_contextMenu->insert(m_actionRemove);
+ m_contextMenu->insert(m_actionClear);
+ // ------------------------------------------------------------------------
+
+
+ // connections
+ // ------------------------------------------------------------------------
+ connect( m_viewPlayList, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotShowContextMenu(KListView*, QListViewItem*, const QPoint&)) );
+
+ connect( m_buttonPlay, SIGNAL(clicked()), this, SLOT(play()) );
+ connect( m_buttonStop, SIGNAL(clicked()), this, SLOT(stop()) );
+ connect( m_buttonPause, SIGNAL(clicked()), this, SLOT(pause()) );
+
+ connect( m_buttonForward, SIGNAL(clicked()), this, SLOT(forward()) );
+ connect( m_buttonBack, SIGNAL(clicked()), this, SLOT(back()) );
+
+ connect( m_seekSlider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int)) );
+ connect( m_seekSlider, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateCurrentTime(int)) );
+
+ connect( m_updateTimer, SIGNAL(timeout()), this, SLOT(slotUpdateDisplay()) );
+ connect( m_updateTimer, SIGNAL(timeout()), this, SLOT(slotCheckEnd()) );
+
+ connect( m_viewPlayList, SIGNAL(doubleClicked(QListViewItem*)),
+ this, SLOT(slotPlayItem(QListViewItem*)) );
+ connect( m_viewPlayList, SIGNAL(dropped(QDropEvent*,QListViewItem*)),
+ this, SLOT(slotDropped(QDropEvent*,QListViewItem*)) );
+ // ------------------------------------------------------------------------
+
+
+ m_bLengthReady = false;
+}
+
+
+K3bAudioPlayer::~K3bAudioPlayer()
+{
+ // we remove the reference to the play object
+ // if we don't do this it won't be removed and K3b will crash (not sure why)
+#ifdef WITH_ARTS
+ m_playObject = Arts::PlayObject::null();
+#endif
+}
+
+
+int K3bAudioPlayer::state()
+{
+#ifdef WITH_ARTS
+ if( !m_playObject.isNull() ) {
+ switch( m_playObject.state() ) {
+ case Arts::posIdle:
+ return STOPPED;
+ case Arts::posPlaying:
+ return PLAYING;
+ case Arts::posPaused:
+ return PAUSED;
+ }
+ }
+ else if( m_currentItem )
+ return STOPPED;
+#endif
+
+ return EMPTY;
+}
+
+
+void K3bAudioPlayer::playFile( const QString& filename )
+{
+ clear();
+ if( QFile::exists( filename ) ) {
+ K3bPlayListViewItem* item = new K3bPlayListViewItem( filename, m_viewPlayList );
+ setCurrentItem( item );
+ play();
+ emit started( filename );
+ }
+}
+
+
+void K3bAudioPlayer::playFiles( const QStringList& files )
+{
+ clear();
+ QStringList::ConstIterator it = files.begin();
+ playFile( *it );
+ ++it;
+
+ for( ; it != files.end(); ++it )
+ enqueueFile( *it );
+}
+
+
+void K3bAudioPlayer::enqueueFile( const QString& filename )
+{
+ if( QFile::exists( filename ) )
+ (void)new K3bPlayListViewItem( filename, m_viewPlayList, m_viewPlayList->lastChild() );
+}
+
+
+void K3bAudioPlayer::enqueueFiles( const QStringList& files )
+{
+ for( QStringList::ConstIterator it = files.begin(); it != files.end(); ++it )
+ enqueueFile( *it );
+}
+
+
+void K3bAudioPlayer::play()
+{
+#ifdef WITH_ARTS
+ if( !m_currentItem ) {
+ setCurrentItem( m_viewPlayList->firstChild() );
+ }
+
+ if( m_currentItem ) {
+ if( m_playObject.isNull() ) {
+ Arts::PlayObjectFactory factory = Arts::Reference("global:Arts_PlayObjectFactory");
+ if( factory.isNull() ) {
+ kdDebug() << "(K3bAudioPlayer) could not create PlayObjectFactory. Possibly no artsd running." << endl;
+ m_labelFilename->setText( i18n("No running aRtsd found") );
+ return;
+ }
+
+ m_playObject = factory.createPlayObject( string(QFile::encodeName(m_currentItem->filename()) ) );
+ if( m_playObject.isNull() ) {
+ kdDebug() << "(K3bAudioPlayer) no aRts module available for: " << m_currentItem->filename() << endl;
+ m_labelFilename->setText( i18n("Unknown file format") );
+
+ // play the next if there is any
+ if( m_currentItem->itemBelow() ) {
+ setCurrentItem( m_currentItem->itemBelow() );
+ play();
+ }
+ return;
+ }
+ }
+ if( m_playObject.state() != Arts::posPlaying ) {
+ m_playObject.play();
+ emit started();
+ m_updateTimer->start( 1000 );
+ }
+
+ slotUpdateFilename();
+ }
+#endif
+}
+
+
+void K3bAudioPlayer::slotPlayItem( QListViewItem* item )
+{
+ setCurrentItem( item );
+ play();
+}
+
+
+void K3bAudioPlayer::stop()
+{
+#ifdef WITH_ARTS
+ if( !m_playObject.isNull() ) {
+ m_updateTimer->stop();
+ m_playObject.halt();
+ m_playObject = Arts::PlayObject::null();
+ m_bLengthReady = false;
+
+ emit stopped();
+ }
+#endif
+
+ m_seekSlider->setValue(0);
+ slotUpdateFilename();
+ slotUpdateCurrentTime(0);
+}
+
+
+void K3bAudioPlayer::pause()
+{
+#ifdef WITH_ARTS
+ if( !m_playObject.isNull() ) {
+ if( m_playObject.state() == Arts::posPlaying ) {
+ m_updateTimer->stop();
+ m_playObject.pause();
+ emit paused();
+ }
+
+ slotUpdateFilename();
+ }
+#endif
+}
+
+
+void K3bAudioPlayer::seek( long pos )
+{
+#ifdef WITH_ARTS
+ if( !m_playObject.isNull() ) {
+ if( m_playObject.state() != Arts::posIdle ) {
+ if( pos < 0 ) {
+ m_playObject.seek( Arts::poTime() );
+ }
+ else if( m_playObject.overallTime().seconds < pos ) {
+ m_playObject.seek( m_playObject.overallTime() );
+ }
+ else if( pos != m_playObject.currentTime().seconds ) {
+ m_playObject.seek( Arts::poTime( pos, 0, -1, "" ) );
+ }
+ }
+ }
+ else {
+ m_seekSlider->setValue(0);
+ slotUpdateCurrentTime(0);
+ }
+#endif
+}
+
+
+
+void K3bAudioPlayer::seek( int pos )
+{
+ seek( (long)pos );
+}
+
+
+void K3bAudioPlayer::forward()
+{
+ if( m_currentItem ) {
+ if( m_currentItem->itemBelow() ) {
+ bool bPlay = false;
+ if( state() == PLAYING )
+ bPlay = true;
+
+ setCurrentItem( m_currentItem->itemBelow() );
+
+ if( bPlay )
+ play();
+ }
+ }
+}
+
+
+void K3bAudioPlayer::back()
+{
+ if( m_currentItem ) {
+ if( m_currentItem->itemAbove() ) {
+ bool bPlay = false;
+ if( state() == PLAYING )
+ bPlay = true;
+
+ setCurrentItem( m_currentItem->itemAbove() );
+
+ if( bPlay )
+ play();
+ }
+ }
+}
+
+
+void K3bAudioPlayer::clear()
+{
+ setCurrentItem( 0 );
+ m_viewPlayList->clear();
+}
+
+
+long K3bAudioPlayer::length()
+{
+#ifdef WITH_ARTS
+ if( !m_playObject.isNull() ) {
+ return m_playObject.overallTime().seconds;
+ }
+#endif
+ return 0;
+}
+
+
+long K3bAudioPlayer::position()
+{
+#ifdef WITH_ARTS
+ if( !m_playObject.isNull() ) {
+ return m_playObject.currentTime().seconds;
+ }
+#endif
+ return 0;
+}
+
+
+// FIXME: let my do some useful stuff!
+bool K3bAudioPlayer::supportsMimetype( const QString& mimetype )
+{
+ if( mimetype.contains("audio") || mimetype.contains("ogg") )
+ return true;
+ else
+ return false;
+}
+
+
+void K3bAudioPlayer::slotCheckEnd()
+{
+#ifdef WITH_ARTS
+ if( !m_playObject.isNull() ) {
+ if( m_playObject.state() == Arts::posIdle ) {
+ if( m_currentItem->nextSibling() ) {
+ setCurrentItem( m_currentItem->nextSibling() );
+ play();
+ }
+ else {
+ stop();
+ }
+ emit ended();
+ }
+ }
+#endif
+}
+
+
+void K3bAudioPlayer::setCurrentItem( QListViewItem* item )
+{
+ if( item == 0 ) {
+ stop();
+ m_labelOverallTime->setText("00:00");
+ m_labelFilename->setText( i18n("no file") );
+ m_currentItem = 0;
+ }
+ else if( K3bPlayListViewItem* playItem = dynamic_cast<K3bPlayListViewItem*>(item) ) {
+ if( m_currentItem ) {
+ // reset m_currentItem
+ m_currentItem->setActive( false );
+ stop();
+ }
+ m_currentItem = playItem;
+ m_currentItem->setActive( true );
+
+ // paint the activity changes
+ m_viewPlayList->viewport()->update();
+
+ slotUpdateFilename();
+ }
+}
+
+
+void K3bAudioPlayer::slotUpdateCurrentTime( int time )
+{
+ m_labelCurrentTime->setText( K3b::Msf( time*75 ).toString(false) );
+}
+
+
+void K3bAudioPlayer::slotUpdateLength( long time )
+{
+ m_labelOverallTime->setText( K3b::Msf( time*75 ).toString(false) );
+}
+
+
+void K3bAudioPlayer::slotUpdateFilename()
+{
+ if( m_currentItem ) {
+ QString display = m_currentItem->filename();
+ int pos = display.findRev("/");
+ if( pos >= 0 )
+ display = display.mid(pos+1);
+
+ switch( state() ) {
+ case PLAYING:
+ display.prepend( QString("(%1) ").arg(i18n("playing")) );
+ break;
+ case PAUSED:
+ display.prepend( QString("(%1) ").arg(i18n("paused")) );
+ break;
+ case STOPPED:
+ display.prepend( QString("(%1) ").arg(i18n("stopped")) );
+ break;
+ default:
+ break;
+ }
+
+ m_labelFilename->setText( display );
+ }
+}
+
+
+void K3bAudioPlayer::slotUpdateDisplay()
+{
+ if( m_currentItem ) {
+ // we need to set the length here because sometimes it is not ready in the beginning (?)
+ if( !m_bLengthReady && length() > 0 ) {
+ slotUpdateLength( length() );
+ m_seekSlider->setMaxValue( length() );
+ m_currentItem->setLength( 75 * length() );
+ m_bLengthReady = true;
+
+ m_viewPlayList->viewport()->update();
+ }
+
+ m_seekSlider->setValue( position() );
+ }
+}
+
+
+void K3bAudioPlayer::slotDropped( QDropEvent* e, QListViewItem* after )
+{
+ if( !after )
+ after = m_viewPlayList->lastChild();
+
+ KURL::List urls;
+ KURLDrag::decode( e, urls );
+
+ for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it ) {
+ if( QFile::exists( (*it).path() ) ) {
+ QListViewItem* newItem = new K3bPlayListViewItem( (*it).path(), m_viewPlayList, after );
+ after = newItem;
+ }
+ }
+}
+
+
+void K3bAudioPlayer::slotRemoveSelected()
+{
+ QPtrList<QListViewItem> selected = m_viewPlayList->selectedItems();
+ for( QListViewItem* item = selected.first(); item; item = selected.next() ) {
+ if( item == m_currentItem )
+ setCurrentItem(0);
+ delete item;
+ }
+}
+
+
+void K3bAudioPlayer::slotShowContextMenu( KListView*, QListViewItem* item, const QPoint& p )
+{
+ if( item )
+ m_actionRemove->setEnabled( true );
+ else
+ m_actionRemove->setEnabled( false );
+
+ m_contextMenu->popup(p);
+}
+
+
+#include "k3baudioplayer.moc"
diff --git a/src/k3baudioplayer.h b/src/k3baudioplayer.h
new file mode 100644
index 0000000..1bc28a9
--- /dev/null
+++ b/src/k3baudioplayer.h
@@ -0,0 +1,208 @@
+/*
+ *
+ * $Id: k3baudioplayer.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BAUDIOPLAYER_H
+#define K3BAUDIOPLAYER_H
+
+#include <klistview.h>
+
+#include <config.h>
+
+#ifdef WITH_ARTS
+#include <arts/kmedia2.h>
+#include <arts/kartsdispatcher.h>
+#endif
+
+class QTimer;
+class QLabel;
+class QToolButton;
+class QSlider;
+class QPainter;
+class QColorGroup;
+class QDropEvent;
+class QDragObject;
+class KAction;
+class KActionMenu;
+
+
+/**
+ * Special ListViewItem for the K3bAudioPlayer playlist
+ * @author Sebastian Trueg
+ */
+class K3bPlayListViewItem : public KListViewItem
+{
+ public:
+ K3bPlayListViewItem( const QString&, QListView* parent );
+ K3bPlayListViewItem( const QString&, QListView* parent, QListViewItem* after );
+ ~K3bPlayListViewItem();
+
+ /** @returns the filename for the first column and the
+ * length in format 00:00.00 for the second column
+ */
+ virtual QString text( int c ) const;
+
+ void setLength( unsigned long l ) { m_length = l; }
+ unsigned long length() const { return m_length; }
+ const QString& filename() const { return m_filename; }
+
+ /**
+ * reimplemented from QListViewItem
+ * takes the m_bActive flag into account.
+ */
+ virtual void paintCell( QPainter*, const QColorGroup&, int, int, int );
+
+ void setActive( bool a ) { m_bActive = a; }
+
+ protected:
+ /** path to the associated file */
+ QString m_filename;
+
+ /** length in frames (1/75 second) */
+ unsigned long m_length;
+
+ bool m_bActive;
+};
+
+
+
+/**
+ * Playlistview just needed to accept
+ * url drags
+ */
+class K3bPlayListView : public KListView
+{
+Q_OBJECT
+
+ public:
+ K3bPlayListView( QWidget* parent = 0, const char* name = 0 );
+ ~K3bPlayListView();
+
+ protected:
+ bool acceptDrag( QDropEvent* e ) const;
+ QDragObject* dragObject();
+};
+
+
+
+
+/**
+ * @author Sebastian Trueg
+ */
+class K3bAudioPlayer : public QWidget
+{
+Q_OBJECT
+
+ public:
+ K3bAudioPlayer( QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioPlayer();
+
+ bool supportsMimetype( const QString& mimetype );
+
+ /**
+ * length of current playing in seconds
+ */
+ long length();
+
+ /**
+ * current position in seconds
+ */
+ long position();
+
+ /**
+ * EMPTY - no file loaded
+ */
+ enum player_state { PLAYING, PAUSED, STOPPED, EMPTY };
+
+ int state();
+
+ signals:
+ void started( const QString& filename );
+ void started();
+ void stopped();
+ void paused();
+ void ended();
+
+ public slots:
+ void playFile( const QString& filename );
+ void playFiles( const QStringList& files );
+ void enqueueFile( const QString& filename );
+ void enqueueFiles( const QStringList& files );
+
+ /** clears the playlist */
+ void clear();
+ void play();
+ void forward();
+ void back();
+ void stop();
+ void pause();
+ void seek( long pos );
+ void seek( int pos );
+
+/* protected: */
+/* void dragEnterEvent( QDragEnterEvent* e ); */
+/* void dropEvent( QDropEvent* e ); */
+
+ private slots:
+ void slotCheckEnd();
+ void slotUpdateDisplay();
+ void slotUpdateCurrentTime( int time );
+ void slotUpdateLength( long time );
+ void slotUpdateFilename();
+ void slotPlayItem( QListViewItem* item );
+ void slotDropped( QDropEvent* e, QListViewItem* after );
+
+ /**
+ * set the actual item. Will set m_currentItem and
+ * handle highlighting of the current item
+ */
+ void setCurrentItem( QListViewItem* item );
+ void slotRemoveSelected();
+ void slotShowContextMenu( KListView*, QListViewItem* item, const QPoint& p );
+
+ private:
+#ifdef WITH_ARTS
+ Arts::PlayObject m_playObject;
+ KArtsDispatcher m_dispatcher;
+#endif
+ QString m_filename;
+
+ QLabel* m_labelFilename;
+ QLabel* m_labelCurrentTime;
+ QLabel* m_labelOverallTime;
+
+ QToolButton* m_buttonPlay;
+ QToolButton* m_buttonPause;
+ QToolButton* m_buttonStop;
+ QToolButton* m_buttonForward;
+ QToolButton* m_buttonBack;
+
+ K3bPlayListView* m_viewPlayList;
+
+ QSlider* m_seekSlider;
+
+ QTimer* m_updateTimer;
+
+ K3bPlayListViewItem* m_currentItem;
+
+ bool m_bLengthReady;
+
+ KAction* m_actionRemove;
+ KAction* m_actionClear;
+ KActionMenu* m_contextMenu;
+};
+
+
+#endif
diff --git a/src/k3baudioprojectinterface.cpp b/src/k3baudioprojectinterface.cpp
new file mode 100644
index 0000000..1d06d5a
--- /dev/null
+++ b/src/k3baudioprojectinterface.cpp
@@ -0,0 +1,92 @@
+/*
+ *
+ * $Id: k3baudioprojectinterface.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudioprojectinterface.h"
+
+#include <k3baudiodoc.h>
+#include <k3baudiotrack.h>
+
+
+K3bAudioProjectInterface::K3bAudioProjectInterface( K3bAudioDoc* doc, const char* name )
+ : K3bProjectInterface( doc, name ),
+ m_audioDoc(doc)
+{
+}
+
+
+int K3bAudioProjectInterface::trackCount() const
+{
+ return m_audioDoc->numOfTracks();
+}
+
+
+QString K3bAudioProjectInterface::title() const
+{
+ return m_audioDoc->title();
+}
+
+
+QString K3bAudioProjectInterface::artist() const
+{
+ return m_audioDoc->artist();
+}
+
+
+QString K3bAudioProjectInterface::trackTitle( int trackNum ) const
+{
+ K3bAudioTrack* track = m_audioDoc->getTrack( trackNum );
+ if( track )
+ return track->title();
+ else
+ return QString::null;
+}
+
+
+QString K3bAudioProjectInterface::trackArtist( int trackNum ) const
+{
+ K3bAudioTrack* track = m_audioDoc->getTrack( trackNum );
+ if( track )
+ return track->artist();
+ else
+ return QString::null;
+}
+
+
+void K3bAudioProjectInterface::setTitle( const QString& title )
+{
+ m_audioDoc->setTitle( title );
+}
+
+
+void K3bAudioProjectInterface::setArtist( const QString& artist )
+{
+ m_audioDoc->setArtist( artist );
+}
+
+
+void K3bAudioProjectInterface::setTrackTitle( int trackNum, const QString& title )
+{
+ K3bAudioTrack* track = m_audioDoc->getTrack( trackNum );
+ if( track )
+ track->setTitle( title );
+}
+
+
+void K3bAudioProjectInterface::setTrackArtist( int trackNum, const QString& artist )
+{
+ K3bAudioTrack* track = m_audioDoc->getTrack( trackNum );
+ if( track )
+ track->setArtist( artist );
+}
diff --git a/src/k3baudioprojectinterface.h b/src/k3baudioprojectinterface.h
new file mode 100644
index 0000000..e7d649e
--- /dev/null
+++ b/src/k3baudioprojectinterface.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * $Id: k3baudioprojectinterface.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_AUDIO_PROJECT_INTERFACE_H_
+#define _K3B_AUDIO_PROJECT_INTERFACE_H_
+
+#include "k3bprojectinterface.h"
+
+class K3bAudioDoc;
+
+
+class K3bAudioProjectInterface : public K3bProjectInterface
+{
+ K_DCOP
+
+ public:
+ K3bAudioProjectInterface( K3bAudioDoc*, const char* name = 0 );
+
+ k_dcop:
+ int trackCount() const;
+ QString title() const;
+ QString artist() const;
+ QString trackTitle( int trackNum ) const;
+ QString trackArtist( int trackNum ) const;
+
+ /**
+ * Set the global CD-Text title field.
+ */
+ void setTitle( const QString& title );
+
+ /**
+ * Set the global CD-Text artist field.
+ */
+ void setArtist( const QString& artist );
+
+ /**
+ * Set the track CD-Text title field.
+ */
+ void setTrackTitle( int trackNum, const QString& title );
+
+ /**
+ * Set the track CD-Text artist field.
+ */
+ void setTrackArtist( int trackNum, const QString& artist );
+
+ private:
+ K3bAudioDoc* m_audioDoc;
+};
+
+#endif
diff --git a/src/k3bburnprogressdialog.cpp b/src/k3bburnprogressdialog.cpp
new file mode 100644
index 0000000..a5ad3a4
--- /dev/null
+++ b/src/k3bburnprogressdialog.cpp
@@ -0,0 +1,134 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bburnprogressdialog.h"
+
+#include "k3bapplication.h"
+#include "k3bjob.h"
+#include <k3bdevice.h>
+#include "k3bstdguiitems.h"
+#include "k3bthemedlabel.h"
+#include <k3bthememanager.h>
+
+#include <kglobal.h>
+#include <kprogress.h>
+#include <klocale.h>
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qframe.h>
+
+
+K3bBurnProgressDialog::K3bBurnProgressDialog( QWidget *parent, const char *name, bool showSubProgress,
+ bool modal, WFlags wf )
+ : K3bJobProgressDialog(parent,name, showSubProgress, modal, wf)
+{
+ m_labelWritingSpeed = new QLabel( m_frameExtraInfo, "m_labelWritingSpeed" );
+ // m_labelWritingSpeed->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+ m_frameExtraInfoLayout->addWidget( m_labelWritingSpeed, 2, 0 );
+ m_frameExtraInfoLayout->addWidget( new QLabel( i18n("Estimated writing speed:"), m_frameExtraInfo ), 1, 0 );
+
+ m_labelWriter = new K3bThemedLabel( m_frameExtraInfo );
+ m_labelWriter->setFrameShape( QFrame::StyledPanel );
+ m_labelWriter->setFrameShadow( QFrame::Sunken );
+ m_labelWriter->setLineWidth( 1 );
+ m_labelWriter->setMargin( 5 );
+ QFont textLabel14_font( m_labelWriter->font() );
+ textLabel14_font.setBold( true );
+ m_labelWriter->setFont( textLabel14_font );
+
+ m_frameExtraInfoLayout->addMultiCellWidget( m_labelWriter, 0, 0, 0, 3 );
+ m_frameExtraInfoLayout->addWidget( new QLabel( i18n("Software buffer:"), m_frameExtraInfo ), 1, 2 );
+ m_frameExtraInfoLayout->addWidget( new QLabel( i18n("Device buffer:"), m_frameExtraInfo ), 2, 2 );
+
+ m_progressWritingBuffer = new KProgress( m_frameExtraInfo, "m_progressWritingBuffer" );
+ m_frameExtraInfoLayout->addWidget( m_progressWritingBuffer, 1, 3 );
+
+ m_progressDeviceBuffer = new KProgress( m_frameExtraInfo );
+ m_frameExtraInfoLayout->addWidget( m_progressDeviceBuffer, 2, 3 );
+ m_frameExtraInfoLayout->addMultiCellWidget( K3bStdGuiItems::verticalLine( m_frameExtraInfo ), 1, 2, 1, 1 );
+}
+
+K3bBurnProgressDialog::~K3bBurnProgressDialog()
+{
+}
+
+
+void K3bBurnProgressDialog::setJob( K3bJob* job )
+{
+ if( K3bBurnJob* burnJob = dynamic_cast<K3bBurnJob*>(job) )
+ setBurnJob(burnJob);
+ else
+ K3bJobProgressDialog::setJob(job);
+}
+
+
+void K3bBurnProgressDialog::setBurnJob( K3bBurnJob* burnJob )
+{
+ K3bJobProgressDialog::setJob(burnJob);
+
+ if( burnJob ) {
+ connect( burnJob, SIGNAL(bufferStatus(int)), this, SLOT(slotBufferStatus(int)) );
+ connect( burnJob, SIGNAL(deviceBuffer(int)), this, SLOT(slotDeviceBuffer(int)) );
+ connect( burnJob, SIGNAL(writeSpeed(int, int)), this, SLOT(slotWriteSpeed(int, int)) );
+ connect( burnJob, SIGNAL(burning(bool)), m_progressWritingBuffer, SLOT(setEnabled(bool)) );
+ connect( burnJob, SIGNAL(burning(bool)), m_progressDeviceBuffer, SLOT(setEnabled(bool)) );
+ connect( burnJob, SIGNAL(burning(bool)), m_labelWritingSpeed, SLOT(setEnabled(bool)) );
+
+ if( burnJob->writer() )
+ m_labelWriter->setText( i18n("Writer: %1 %2").arg(burnJob->writer()->vendor()).
+ arg(burnJob->writer()->description()) );
+
+ m_labelWritingSpeed->setText( i18n("no info") );
+ m_progressWritingBuffer->setFormat( i18n("no info") );
+ m_progressDeviceBuffer->setFormat( i18n("no info") );
+ }
+}
+
+
+void K3bBurnProgressDialog::slotFinished( bool success )
+{
+ K3bJobProgressDialog::slotFinished( success );
+ if( success ) {
+ m_labelWritingSpeed->setEnabled( false );
+ m_progressWritingBuffer->setEnabled( false );
+ m_progressDeviceBuffer->setEnabled( false );
+ }
+}
+
+
+void K3bBurnProgressDialog::slotBufferStatus( int b )
+{
+ m_progressWritingBuffer->setFormat( "%p%" );
+ m_progressWritingBuffer->setValue( b );
+}
+
+
+void K3bBurnProgressDialog::slotDeviceBuffer( int b )
+{
+ m_progressDeviceBuffer->setFormat( "%p%" );
+ m_progressDeviceBuffer->setValue( b );
+}
+
+
+void K3bBurnProgressDialog::slotWriteSpeed( int s, int multiplicator )
+{
+ m_labelWritingSpeed->setText( QString("%1 KB/s (%2x)").arg(s).arg(KGlobal::locale()->formatNumber((double)s/(double)multiplicator,2)) );
+}
+
+#include "k3bburnprogressdialog.moc"
diff --git a/src/k3bburnprogressdialog.h b/src/k3bburnprogressdialog.h
new file mode 100644
index 0000000..db27ddb
--- /dev/null
+++ b/src/k3bburnprogressdialog.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id: k3bburnprogressdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BBURNPROGRESSDIALOG_H
+#define K3BBURNPROGRESSDIALOG_H
+
+#include <k3bjobprogressdialog.h>
+
+class K3bBurnJob;
+class KProgress;
+class QLabel;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bBurnProgressDialog : public K3bJobProgressDialog {
+
+ Q_OBJECT
+
+ public:
+ K3bBurnProgressDialog( QWidget* parent = 0, const char* name = 0, bool showSubProgress = true,
+ bool modal = true, WFlags = 0 );
+ ~K3bBurnProgressDialog();
+
+ void setJob( K3bJob* );
+ void setBurnJob( K3bBurnJob* );
+
+ protected slots:
+ void slotWriteSpeed( int, int );
+ void slotBufferStatus( int );
+ void slotDeviceBuffer( int );
+ void slotFinished(bool);
+
+ protected:
+ QLabel* m_labelWriter;
+ KProgress* m_progressWritingBuffer;
+ KProgress* m_progressDeviceBuffer;
+ QLabel* m_labelWritingSpeed;
+};
+
+#endif
diff --git a/src/k3bcontentsview.cpp b/src/k3bcontentsview.cpp
new file mode 100644
index 0000000..304ae0d
--- /dev/null
+++ b/src/k3bcontentsview.cpp
@@ -0,0 +1,86 @@
+/*
+ *
+ * $Id: k3bcdcontentsview.cpp 582796 2006-09-10 15:31:38Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bcontentsview.h"
+
+#include <k3bthemedheader.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+
+
+K3bContentsView::K3bContentsView( bool withHeader,
+ QWidget* parent,
+ const char* name )
+ : QWidget( parent, name ),
+ m_header(0),
+ m_centerWidget(0)
+{
+ if( withHeader ) {
+ QVBoxLayout* lay = new QVBoxLayout( this );
+ lay->setMargin( 2 );
+ lay->setSpacing( 0 );
+
+ m_header = new K3bThemedHeader( this );
+ lay->addWidget( m_header );
+
+ m_header->setLeftPixmap( K3bTheme::MEDIA_LEFT );
+ m_header->setRightPixmap( K3bTheme::MEDIA_NONE );
+ }
+}
+
+
+K3bContentsView::~K3bContentsView()
+{
+}
+
+
+void K3bContentsView::setMainWidget( QWidget* w )
+{
+ m_centerWidget = w;
+ ((QVBoxLayout*)layout())->addWidget( w );
+}
+
+
+QWidget* K3bContentsView::mainWidget()
+{
+ if( !m_centerWidget )
+ setMainWidget( new QWidget( this ) );
+ return m_centerWidget;
+}
+
+
+void K3bContentsView::setTitle( const QString& s )
+{
+ if( m_header )
+ m_header->setTitle( s );
+}
+
+
+void K3bContentsView::setLeftPixmap( K3bTheme::PixmapType s )
+{
+ if( m_header )
+ m_header->setLeftPixmap( s );
+}
+
+
+void K3bContentsView::setRightPixmap( K3bTheme::PixmapType s )
+{
+ if( m_header )
+ m_header->setRightPixmap( s );
+}
+
+#include "k3bcontentsview.moc"
diff --git a/src/k3bcontentsview.h b/src/k3bcontentsview.h
new file mode 100644
index 0000000..a3b6f45
--- /dev/null
+++ b/src/k3bcontentsview.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * $Id: k3bcdcontentsview.h 576315 2006-08-23 19:32:42Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_CONTENTS_VIEW_H_
+#define _K3B_CONTENTS_VIEW_H_
+
+#include <qwidget.h>
+#include <k3bthememanager.h>
+
+class K3bThemedHeader;
+
+
+class K3bContentsView : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ virtual ~K3bContentsView();
+
+ protected:
+ K3bContentsView( bool withHeader,
+ QWidget* parent = 0,
+ const char* name = 0 );
+
+ QWidget* mainWidget();
+ void setMainWidget( QWidget* );
+ void setTitle( const QString& );
+ void setLeftPixmap( K3bTheme::PixmapType );
+ void setRightPixmap( K3bTheme::PixmapType );
+
+ private:
+ K3bThemedHeader* m_header;
+ QWidget* m_centerWidget;
+};
+
+#endif
diff --git a/src/k3bdatamodewidget.cpp b/src/k3bdatamodewidget.cpp
new file mode 100644
index 0000000..669da59
--- /dev/null
+++ b/src/k3bdatamodewidget.cpp
@@ -0,0 +1,106 @@
+/*
+ *
+ * $Id: k3bdatamodewidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdatamodewidget.h"
+#include <k3bglobals.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+
+static const int s_autoIndex = 0;
+static const int s_mode1Index = 1;
+static const int s_mode2Index = 2;
+
+
+K3bDataModeWidget::K3bDataModeWidget( QWidget* parent, const char* name )
+ : QComboBox( false, parent, name )
+{
+ insertItem( i18n("Auto"), s_autoIndex );
+ insertItem( i18n("Mode1"), s_mode1Index );
+ insertItem( i18n("Mode2"), s_mode2Index );
+
+ QToolTip::add( this,i18n("Select the mode for the data-track") );
+ QWhatsThis::add( this, i18n("<p><b>Data Mode</b>"
+ "<p>Data tracks may be written in two different modes:</p>"
+ "<p><b>Auto</b><br>"
+ "Let K3b select the best suited data mode.</p>"
+ "<p><b>Mode 1</b><br>"
+ "This is the <em>original</em> writing mode as introduced in the "
+ "<em>Yellow Book</em> standard. It is the preferred mode when writing "
+ "pure data CDs.</p>"
+ "<p><b>Mode 2</b><br>"
+ "To be exact <em>XA Mode 2 Form 1</em>, but since the "
+ "other modes are rarely used it is common to refer to it as <em>Mode 2</em>.</p>"
+ "<p><b>Be aware:</b> Do not mix different modes on one CD. "
+ "Some older drives may have problems reading mode 1 multisession CDs.") );
+}
+
+
+K3bDataModeWidget::~K3bDataModeWidget()
+{
+}
+
+
+int K3bDataModeWidget::dataMode() const
+{
+ if( currentItem() == s_autoIndex )
+ return K3b::DATA_MODE_AUTO;
+ else if( currentItem() == s_mode1Index )
+ return K3b::MODE1;
+ else
+ return K3b::MODE2;
+}
+
+
+void K3bDataModeWidget::setDataMode( int mode )
+{
+ if( mode == K3b::MODE1 )
+ setCurrentItem( s_mode1Index );
+ else if( mode == K3b::MODE2 )
+ setCurrentItem( s_mode2Index );
+ else
+ setCurrentItem( s_autoIndex );
+}
+
+
+void K3bDataModeWidget::saveConfig( KConfigBase* c )
+{
+ QString datamode;
+ if( dataMode() == K3b::MODE1 )
+ datamode = "mode1";
+ else if( dataMode() == K3b::MODE2 )
+ datamode = "mode2";
+ else
+ datamode = "auto";
+ c->writeEntry( "data_track_mode", datamode );
+}
+
+
+void K3bDataModeWidget::loadConfig( KConfigBase* c )
+{
+ QString datamode = c->readEntry( "data_track_mode" );
+ if( datamode == "mode1" )
+ setDataMode( K3b::MODE1 );
+ else if( datamode == "mode2" )
+ setDataMode( K3b::MODE2 );
+ else
+ setDataMode( K3b::DATA_MODE_AUTO );
+}
+
+#include "k3bdatamodewidget.moc"
diff --git a/src/k3bdatamodewidget.h b/src/k3bdatamodewidget.h
new file mode 100644
index 0000000..647225f
--- /dev/null
+++ b/src/k3bdatamodewidget.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * $Id: k3bdatamodewidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_DATAMODE_WIDGET_H_
+#define _K3B_DATAMODE_WIDGET_H_
+
+#include <qcombobox.h>
+
+
+class KConfigBase;
+
+
+class K3bDataModeWidget : public QComboBox
+{
+ Q_OBJECT
+
+ public:
+ K3bDataModeWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bDataModeWidget();
+
+ /**
+ * returnes K3b::DataMode
+ */
+ int dataMode() const;
+
+ void saveConfig( KConfigBase* );
+ void loadConfig( KConfigBase* );
+
+ public slots:
+ void setDataMode( int );
+};
+
+#endif
diff --git a/src/k3bdataprojectinterface.cpp b/src/k3bdataprojectinterface.cpp
new file mode 100644
index 0000000..6adf07d
--- /dev/null
+++ b/src/k3bdataprojectinterface.cpp
@@ -0,0 +1,128 @@
+/*
+ *
+ * $Id: k3bdataprojectinterface.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdataprojectinterface.h"
+
+#include <k3bdatadoc.h>
+#include <k3bdiritem.h>
+#include <k3bisooptions.h>
+
+
+K3bDataProjectInterface::K3bDataProjectInterface( K3bDataDoc* doc, const char* name )
+ : K3bProjectInterface( doc, name ),
+ m_dataDoc(doc)
+{
+}
+
+
+K3bDataProjectInterface::~K3bDataProjectInterface()
+{
+}
+
+
+bool K3bDataProjectInterface::createFolder( const QString& name )
+{
+ return createFolder( name, "/" );
+}
+
+
+bool K3bDataProjectInterface::createFolder( const QString& name, const QString& parent )
+{
+ K3bDataItem* p = m_dataDoc->root()->findByPath( parent );
+ if( p && p->isDir() && !static_cast<K3bDirItem*>(p)->find( name ) ) {
+ m_dataDoc->addEmptyDir( name, static_cast<K3bDirItem*>(p) );
+ return true;
+ }
+ return false;
+}
+
+
+void K3bDataProjectInterface::addUrl( const QString& url, const QString& parent )
+{
+ addUrls( QStringList(url), parent );
+}
+
+
+void K3bDataProjectInterface::addUrls( const QStringList& urls, const QString& parent )
+{
+ K3bDataItem* p = m_dataDoc->root()->findByPath( parent );
+ if( p && p->isDir() )
+ m_dataDoc->addUrls( KURL::List(urls), static_cast<K3bDirItem*>(p) );
+}
+
+
+bool K3bDataProjectInterface::removeItem( const QString& path )
+{
+ K3bDataItem* p = m_dataDoc->root()->findByPath( path );
+ if( p && p->isRemoveable() ) {
+ m_dataDoc->removeItem( p );
+ return true;
+ }
+ else
+ return false;
+}
+
+
+bool K3bDataProjectInterface::renameItem( const QString& path, const QString& newName )
+{
+ K3bDataItem* p = m_dataDoc->root()->findByPath( path );
+ if( p && p->isRenameable() && !newName.isEmpty() ) {
+ p->setK3bName( newName );
+ return true;
+ }
+ else
+ return false;
+}
+
+
+void K3bDataProjectInterface::setVolumeID( const QString& id )
+{
+ m_dataDoc->setVolumeID( id );
+}
+
+bool K3bDataProjectInterface::isFolder( const QString& path ) const
+{
+ K3bDataItem* p = m_dataDoc->root()->findByPath( path );
+ if( p )
+ return p->isDir();
+ else
+ return false;
+}
+
+
+QStringList K3bDataProjectInterface::children( const QString& path ) const
+{
+ QStringList l;
+ K3bDataItem* item = m_dataDoc->root()->findByPath( path );
+ if( item && item->isDir() ) {
+ const QPtrList<K3bDataItem>& cl = static_cast<K3bDirItem*>(item)->children();
+ for( QPtrListIterator<K3bDataItem> it( cl ); *it; ++it )
+ l.append( it.current()->k3bName() );
+ }
+
+ return l;
+}
+
+
+bool K3bDataProjectInterface::setSortWeight( const QString& path, long weight ) const
+{
+ K3bDataItem* item = m_dataDoc->root()->findByPath( path );
+ if( item ) {
+ item->setSortWeight( weight );
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/src/k3bdataprojectinterface.h b/src/k3bdataprojectinterface.h
new file mode 100644
index 0000000..689455b
--- /dev/null
+++ b/src/k3bdataprojectinterface.h
@@ -0,0 +1,105 @@
+/*
+ *
+ * $Id: k3bdataprojectinterface.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_DATA_PROJECT_INTERFACE_H_
+#define _K3B_DATA_PROJECT_INTERFACE_H_
+
+#include "k3bprojectinterface.h"
+
+#include <qstringlist.h>
+
+class K3bDataDoc;
+
+
+class K3bDataProjectInterface : public K3bProjectInterface
+{
+ K_DCOP
+
+ public:
+ K3bDataProjectInterface( K3bDataDoc*, const char* name = 0 );
+ ~K3bDataProjectInterface();
+
+ k_dcop:
+ /**
+ * Create a new folder in the root of the doc.
+ * This is the same as calling createFolder( name, "/" )
+ */
+ bool createFolder( const QString& name );
+
+ /**
+ * Create a new folder with name @p name in the folder with the
+ * absolute path @p parent.
+ *
+ * \return true if the folder was created successfully, false if
+ * an item with the same name already exists or the parent
+ * directory could not be found.
+ *
+ * Example: createFolder( "test", "/foo/bar" ) will create the
+ * folder /foo/bar/test.
+ */
+ bool createFolder( const QString& name, const QString& parent );
+
+ /**
+ * Add urls to a specific folder in the project.
+ *
+ * Example: addUrl( "test.txt", "/foo/bar" ) will add the file test.txt
+ * to folder /foo/bar.
+ */
+ void addUrl( const QString& url, const QString& parent );
+
+ void addUrls( const QStringList& urls, const QString& parent );
+
+ /**
+ * Remove an item
+ * \return true if the item was successfully removed.
+ */
+ bool removeItem( const QString& path );
+
+ /**
+ * Rename an item
+ * \return true if the item was successfully renamed, false if
+ * no item could be found at \p path, \p newName is empty,
+ * or the item cannot be renamed for some reason.
+ */
+ bool renameItem( const QString& path, const QString& newName );
+
+ /**
+ * Set the volume ID of the data project. This is the name shown by Windows
+ * when the CD is inserted.
+ */
+ void setVolumeID( const QString& id );
+
+ /**
+ * \return true if the specified path exists in the project and it is a folder.
+ */
+ bool isFolder( const QString& path ) const;
+
+ /**
+ * \return the names of the child elements of the item determined by path.
+ */
+ QStringList children( const QString& path ) const;
+
+ /**
+ * Set the sort weight of an item
+ * \return false if the item at \p could not be found.
+ */
+ bool setSortWeight( const QString& path, long weight ) const;
+
+ private:
+ K3bDataDoc* m_dataDoc;
+};
+
+#endif
diff --git a/src/k3bdebuggingoutputdialog.cpp b/src/k3bdebuggingoutputdialog.cpp
new file mode 100644
index 0000000..7ffe84c
--- /dev/null
+++ b/src/k3bdebuggingoutputdialog.cpp
@@ -0,0 +1,162 @@
+/*
+ *
+ * $Id: k3bdebuggingoutputdialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdebuggingoutputdialog.h"
+
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bdeviceglobals.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+#include <k3bglobals.h>
+
+#include <qtextedit.h>
+#include <qcursor.h>
+#include <qfile.h>
+#include <qclipboard.h>
+
+#include <klocale.h>
+#include <kstdguiitem.h>
+#include <kglobalsettings.h>
+#include <kapplication.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+
+
+K3bDebuggingOutputDialog::K3bDebuggingOutputDialog( QWidget* parent )
+ : KDialogBase( parent, "debugViewDialog", true, i18n("Debugging Output"), Close|User1|User2, Close,
+ false,
+ KStdGuiItem::saveAs(),
+ KGuiItem( i18n("Copy"), "editcopy" ) )
+{
+ setButtonTip( User1, i18n("Save to file") );
+ setButtonTip( User2, i18n("Copy to clipboard") );
+
+ debugView = new QTextEdit( this );
+ debugView->setReadOnly(true);
+ debugView->setTextFormat( QTextEdit::PlainText );
+ debugView->setCurrentFont( KGlobalSettings::fixedFont() );
+ debugView->setWordWrap( QTextEdit::NoWrap );
+
+ setMainWidget( debugView );
+
+ resize( 600, 300 );
+}
+
+
+void K3bDebuggingOutputDialog::setOutput( const QMap<QString, QStringList>& map )
+{
+ // the following may take some time
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+
+ clear();
+
+ // add the debugging output
+ for( QMap<QString, QStringList>::ConstIterator itMap = map.begin(); itMap != map.end(); ++itMap ) {
+ const QStringList& list = itMap.data();
+ debugView->append( itMap.key() + "\n" );
+ debugView->append( "-----------------------\n" );
+ for( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) {
+ QStringList lines = QStringList::split( "\n", *it );
+ // do every line
+ QStringList::ConstIterator end( lines.end() );
+ for( QStringList::ConstIterator str = lines.begin(); str != end; ++str )
+ debugView->append( *str + "\n" );
+ }
+ m_paragraphMap[itMap.key()] = debugView->paragraphs();
+ debugView->append( "\n" );
+ }
+
+ QApplication::restoreOverrideCursor();
+}
+
+
+void K3bDebuggingOutputDialog::addOutput( const QString& app, const QString& msg )
+{
+ QMap<QString, int>::Iterator it = m_paragraphMap.find( app );
+
+ if( it == m_paragraphMap.end() ) {
+ // create new section
+ debugView->append( app + "\n" );
+ debugView->append( "-----------------------\n" );
+ debugView->append( msg + "\n" );
+ m_paragraphMap[app] = debugView->paragraphs();
+ debugView->append( "\n" );
+ }
+ else {
+ debugView->insertParagraph( msg, *it );
+ // update the paragraphs map
+ // FIXME: we cannot count on the map to be sorted properly!
+ while( it != m_paragraphMap.end() ) {
+ it.data() += 1;
+ ++it;
+ }
+ }
+}
+
+
+void K3bDebuggingOutputDialog::clear()
+{
+ debugView->clear();
+ m_paragraphMap.clear();
+
+ addOutput( "System", "K3b Version: " + k3bcore->version() );
+ addOutput( "System", "KDE Version: " + QString(KDE::versionString()) );
+ addOutput( "System", "QT Version: " + QString(qVersion()) );
+ addOutput( "System", "Kernel: " + K3b::kernelVersion() );
+
+ // devices in the logfile
+ for( QPtrListIterator<K3bDevice::Device> it( k3bcore->deviceManager()->allDevices() ); *it; ++it ) {
+ K3bDevice::Device* dev = *it;
+ addOutput( "Devices",
+ QString( "%1 (%2, %3) [%5] [%6] [%7]" )
+ .arg( dev->vendor() + " " + dev->description() + " " + dev->version() )
+ .arg( dev->blockDeviceName() )
+ .arg( dev->genericDevice() )
+ .arg( K3bDevice::deviceTypeString( dev->type() ) )
+ .arg( K3bDevice::mediaTypeString( dev->supportedProfiles() ) )
+ .arg( K3bDevice::writingModeString( dev->writingModes() ) ) );
+ }
+}
+
+
+void K3bDebuggingOutputDialog::slotUser1()
+{
+ QString filename = KFileDialog::getSaveFileName();
+ if( !filename.isEmpty() ) {
+ QFile f( filename );
+ if( !f.exists() || KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(filename),
+ i18n("File Exists"), i18n("Overwrite") )
+ == KMessageBox::Continue ) {
+
+ if( f.open( IO_WriteOnly ) ) {
+ QTextStream t( &f );
+ t << debugView->text();
+ }
+ else {
+ KMessageBox::error( this, i18n("Could not open file %1").arg(filename) );
+ }
+ }
+ }
+}
+
+
+void K3bDebuggingOutputDialog::slotUser2()
+{
+ QApplication::clipboard()->setText( debugView->text(), QClipboard::Clipboard );
+}
+
+#include "k3bdebuggingoutputdialog.moc"
diff --git a/src/k3bdebuggingoutputdialog.h b/src/k3bdebuggingoutputdialog.h
new file mode 100644
index 0000000..0e74b71
--- /dev/null
+++ b/src/k3bdebuggingoutputdialog.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * $Id: k3bdebuggingoutputdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_DEBUGGING_OUTPUT_DIALOG_H_
+#define _K3B_DEBUGGING_OUTPUT_DIALOG_H_
+
+#include <kdialogbase.h>
+#include <qmap.h>
+
+class QTextEdit;
+
+class K3bDebuggingOutputDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bDebuggingOutputDialog( QWidget* parent );
+
+ public slots:
+ void setOutput( const QMap<QString, QStringList>& );
+ void addOutput( const QString&, const QString& );
+ void clear();
+
+ private:
+ void slotUser1();
+ void slotUser2();
+
+ QTextEdit* debugView;
+ QMap<QString, int> m_paragraphMap;
+};
+
+
+
+#endif
diff --git a/src/k3bdebuggingoutputfile.cpp b/src/k3bdebuggingoutputfile.cpp
new file mode 100644
index 0000000..2f99e96
--- /dev/null
+++ b/src/k3bdebuggingoutputfile.cpp
@@ -0,0 +1,75 @@
+/*
+ *
+ * $Id: k3bdebuggingoutputfile.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdebuggingoutputfile.h"
+
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+#include <k3bdeviceglobals.h>
+#include <k3bglobals.h>
+
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <kapplication.h>
+
+#include <qtextstream.h>
+
+
+K3bDebuggingOutputFile::K3bDebuggingOutputFile()
+ : QFile( locateLocal( "appdata", "lastlog.log", true ) )
+{
+}
+
+
+bool K3bDebuggingOutputFile::open()
+{
+ if( !QFile::open( IO_WriteOnly ) )
+ return false;
+
+ addOutput( "System", "K3b Version: " + k3bcore->version() );
+ addOutput( "System", "KDE Version: " + QString(KDE::versionString()) );
+ addOutput( "System", "QT Version: " + QString(qVersion()) );
+ addOutput( "System", "Kernel: " + K3b::kernelVersion() );
+
+ // devices in the logfile
+ for( QPtrListIterator<K3bDevice::Device> it( k3bcore->deviceManager()->allDevices() ); *it; ++it ) {
+ K3bDevice::Device* dev = *it;
+ addOutput( "Devices",
+ QString( "%1 (%2, %3) [%5] [%6] [%7]" )
+ .arg( dev->vendor() + " " + dev->description() + " " + dev->version() )
+ .arg( dev->blockDeviceName() )
+ .arg( dev->genericDevice() )
+ .arg( K3bDevice::deviceTypeString( dev->type() ) )
+ .arg( K3bDevice::mediaTypeString( dev->supportedProfiles() ) )
+ .arg( K3bDevice::writingModeString( dev->writingModes() ) ) );
+ }
+
+ return true;
+}
+
+
+void K3bDebuggingOutputFile::addOutput( const QString& app, const QString& msg )
+{
+ if( !isOpen() )
+ open();
+
+ QTextStream s( this );
+ s << "[" << app << "] " << msg << endl;
+ flush();
+}
+
+#include "k3bdebuggingoutputfile.moc"
diff --git a/src/k3bdebuggingoutputfile.h b/src/k3bdebuggingoutputfile.h
new file mode 100644
index 0000000..c0af0e5
--- /dev/null
+++ b/src/k3bdebuggingoutputfile.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * $Id: k3bdebuggingoutputfile.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_DEBUGGING_OUTPUT_FILE_H_
+#define _K3B_DEBUGGING_OUTPUT_FILE_H_
+
+#include <qfile.h>
+#include <qobject.h>
+
+class K3bDebuggingOutputFile : public QObject, public QFile
+{
+ Q_OBJECT
+
+ public:
+ K3bDebuggingOutputFile();
+
+ /**
+ * Open the default output file and write some system information.
+ */
+ bool open();
+
+ public slots:
+ void addOutput( const QString&, const QString& );
+};
+
+
+#endif
diff --git a/src/k3bdiroperator.cpp b/src/k3bdiroperator.cpp
new file mode 100644
index 0000000..12c6ba4
--- /dev/null
+++ b/src/k3bdiroperator.cpp
@@ -0,0 +1,159 @@
+
+/*
+ *
+ * $Id: k3bdiroperator.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdiroperator.h"
+
+#include <k3bapplication.h>
+#include <k3b.h>
+#include <k3bcore.h>
+
+#include <kcombiview.h>
+#include <kfilepreview.h>
+#include <kaction.h>
+#include <kbookmarkmenu.h>
+#include <kstandarddirs.h>
+#include <kpopupmenu.h>
+
+#include <qdir.h>
+
+
+K3bDirOperator::K3bDirOperator(const KURL& url, QWidget* parent, const char* name )
+ : KDirOperator( url, parent, name )
+{
+ setViewConfig( k3bcore->config(), "file view" );
+ setMode( KFile::Files );
+
+ // disable the del-key since we still have a focus problem and users keep
+ // deleting files when they want to remove project entries
+ KAction* aDelete = actionCollection()->action("delete");
+ if( aDelete )
+ aDelete->setShortcut( 0 );
+
+ // add the bookmark stuff
+ KBookmarkManager* bmMan = KBookmarkManager::managerForFile( locateLocal( "data", "k3b/bookmarks.xml" ), false );
+ bmMan->setEditorOptions( i18n("K3b Bookmarks"), false );
+ bmMan->setUpdate( true );
+ bmMan->setShowNSBookmarks( false );
+
+ m_bmPopup = new KActionMenu( i18n("Bookmarks"), "bookmark", this, "bookmarks" );
+ m_bmMenu = new KBookmarkMenu( bmMan, this, m_bmPopup->popupMenu(), actionCollection(), true );
+
+ (void)new KAction( i18n("&Add to Project"), SHIFT+Key_Return,
+ this, SLOT(slotAddFilesToProject()),
+ actionCollection(), "add_file_to_project");
+}
+
+
+K3bDirOperator::~K3bDirOperator()
+{
+ delete m_bmMenu;
+}
+
+
+void K3bDirOperator::readConfig( KConfig* cfg, const QString& group )
+{
+ QString oldGroup = cfg->group();
+ cfg->setGroup( group );
+
+ KDirOperator::readConfig( cfg, group );
+ setView( KFile::Default );
+
+ //
+ // There seems to be a bug in the KDELibs which makes setURL crash on
+ // some systems when used with a non-existing url
+ //
+ QString lastUrl = cfg->readPathEntry( "last url", QDir::home().absPath() );
+ while( !QFile::exists(lastUrl) ) {
+ QString urlUp = lastUrl.section( '/', 0, -2 );
+ if( urlUp == lastUrl )
+ lastUrl = QDir::home().absPath();
+ else
+ lastUrl = urlUp;
+ }
+
+ setURL( KURL::fromPathOrURL(lastUrl), true );
+
+ cfg->setGroup( oldGroup );
+
+ emit urlEntered( url() );
+}
+
+
+void K3bDirOperator::writeConfig( KConfig* cfg, const QString& group )
+{
+ QString oldGroup = cfg->group();
+ cfg->setGroup( group );
+
+ KDirOperator::writeConfig( cfg, group );
+ cfg->writePathEntry( "last url", url().path() );
+
+ cfg->setGroup( oldGroup );
+}
+
+
+void K3bDirOperator::openBookmarkURL( const QString& url )
+{
+ setURL( KURL::fromPathOrURL( url ), true );
+}
+
+
+QString K3bDirOperator::currentTitle() const
+{
+ return url().path(-1);
+}
+
+
+QString K3bDirOperator::currentURL() const
+{
+ return url().path(-1);
+}
+
+
+void K3bDirOperator::activatedMenu( const KFileItem*, const QPoint& pos )
+{
+ // both from KDirOperator
+ setupMenu();
+ updateSelectionDependentActions();
+
+ // insert our own actions
+ KActionMenu* dirOpMenu = (KActionMenu*)actionCollection()->action("popupMenu");
+ dirOpMenu->insert( new KActionSeparator( actionCollection() ) );
+ dirOpMenu->insert( m_bmPopup );
+
+ dirOpMenu->insert( actionCollection()->action("add_file_to_project"), 0 );
+ dirOpMenu->insert( new KActionSeparator( actionCollection() ), 1 );
+
+ bool hasSelection = view() && view()->selectedItems() &&
+ !view()->selectedItems()->isEmpty();
+ actionCollection()->action("add_file_to_project")->setEnabled( hasSelection && k3bappcore->k3bMainWindow()->activeView() != 0 );
+
+ dirOpMenu->popup( pos );
+}
+
+
+void K3bDirOperator::slotAddFilesToProject()
+{
+ KURL::List files;
+ for( QPtrListIterator<KFileItem> it( *(selectedItems()) ); it.current(); ++it ) {
+ files.append( it.current()->url() );
+ }
+ if( !files.isEmpty() )
+ k3bappcore->k3bMainWindow()->addUrls( files );
+}
+
+#include "k3bdiroperator.moc"
+
diff --git a/src/k3bdiroperator.h b/src/k3bdiroperator.h
new file mode 100644
index 0000000..b231a8d
--- /dev/null
+++ b/src/k3bdiroperator.h
@@ -0,0 +1,82 @@
+/*
+ *
+ * $Id: k3bdiroperator.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDIROPERATOR_H
+#define K3BDIROPERATOR_H
+
+#include <kdiroperator.h>
+#include <kbookmarkmanager.h>
+
+class QIconViewItem;
+class QListViewItem;
+class KBookmarkMenu;
+class KActionMenu;
+
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bDirOperator : public KDirOperator, public KBookmarkOwner
+{
+ Q_OBJECT
+
+ public:
+ K3bDirOperator( const KURL& urlName = KURL(), QWidget* parent = 0, const char* name = 0 );
+ ~K3bDirOperator();
+
+ /**
+ * reimplemented from KDirOperator
+ */
+ void readConfig( KConfig* cfg, const QString& group );
+
+ /**
+ * reimplemented from KDirOperator
+ */
+ void writeConfig( KConfig* cfg, const QString& group );
+
+ /**
+ * reimplemented from KBookmarkOwner
+ */
+ void openBookmarkURL( const QString& url );
+
+ /**
+ * reimplemented from KBookmarkOwner
+ */
+ QString currentTitle() const;
+
+ /**
+ * reimplemented from KBookmarkOwner
+ */
+ QString currentURL() const;
+
+ KActionMenu* bookmarkMenu() const { return m_bmPopup; }
+
+ public slots:
+ void slotAddFilesToProject();
+
+ protected slots:
+ /**
+ * reimplemented from KDirOperator
+ */
+ void activatedMenu( const KFileItem*, const QPoint& );
+
+ private:
+ KBookmarkMenu* m_bmMenu;
+ KActionMenu* m_bmPopup;
+};
+
+#endif
diff --git a/src/k3bdirview.cpp b/src/k3bdirview.cpp
new file mode 100644
index 0000000..d711300
--- /dev/null
+++ b/src/k3bdirview.cpp
@@ -0,0 +1,367 @@
+/*
+ *
+ * $Id: k3bdirview.cpp 627621 2007-01-27 12:31:44Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3bdirview.h"
+#include "k3bapplication.h"
+#include "k3b.h"
+
+#include "rip/k3baudiocdview.h"
+#include "rip/k3bvideocdview.h"
+#ifdef HAVE_LIBDVDREAD
+#include "rip/videodvd/k3bvideodvdrippingview.h"
+#endif
+#include "k3bfileview.h"
+#include "k3bfiletreeview.h"
+#include "k3bappdevicemanager.h"
+#include "k3bdiskinfoview.h"
+#include <k3bdevicehandler.h>
+#include <k3bdevice.h>
+#include <k3bthememanager.h>
+#include <k3bmediacache.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bpassivepopup.h>
+
+#include <unistd.h>
+// QT-includes
+#include <qdir.h>
+#include <qlistview.h>
+#include <qstring.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qpixmap.h>
+#include <qstringlist.h>
+#include <qstrlist.h>
+#include <qheader.h>
+#include <qsplitter.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qiconset.h>
+#include <qvaluelist.h>
+#include <qlabel.h>
+#include <qwidgetstack.h>
+#include <qscrollview.h>
+#include <qpainter.h>
+#include <qsimplerichtext.h>
+
+// KDE-includes
+#include <kmimetype.h>
+#include <kcursor.h>
+#include <kfiledetailview.h>
+#include <ktoolbar.h>
+#include <kiconloader.h>
+#include <kurl.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kio/file.h>
+#include <kio/global.h>
+#include <krun.h>
+#include <kprocess.h>
+#include <kio/job.h>
+#include <kcombobox.h>
+#include <kfiletreeview.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+#include <kstdaction.h>
+#include <kconfig.h>
+#include <kaction.h>
+#include <kinputdialog.h>
+
+
+
+class K3bDirView::Private
+{
+public:
+ bool contextMediaInfoRequested;
+};
+
+
+
+K3bDirView::K3bDirView(K3bFileTreeView* treeView, QWidget *parent, const char *name )
+ : QVBox(parent, name),
+ m_fileTreeView(treeView),
+ m_bViewDiskInfo(false)
+{
+ d = new Private;
+ d->contextMediaInfoRequested = false;
+
+ if( !m_fileTreeView ) {
+ m_mainSplitter = new QSplitter( this );
+ m_fileTreeView = new K3bFileTreeView( m_mainSplitter );
+ m_viewStack = new QWidgetStack( m_mainSplitter );
+ }
+ else {
+ m_viewStack = new QWidgetStack( this );
+ m_mainSplitter = 0;
+ }
+
+ m_fileTreeView->header()->hide();
+
+ m_fileView = new K3bFileView(m_viewStack, "fileView");
+ m_cdView = new K3bAudioCdView(m_viewStack, "cdview");
+ m_videoView = new K3bVideoCdView(m_viewStack, "videoview");
+ m_infoView = new K3bDiskInfoView(m_viewStack, "infoView");
+#ifdef HAVE_LIBDVDREAD
+ m_movieView = new K3bVideoDVDRippingView(m_viewStack, "movieview");
+#endif
+
+ m_viewStack->raiseWidget( m_fileView );
+
+ m_fileTreeView->addDefaultBranches();
+ m_fileTreeView->addCdDeviceBranches( k3bcore->deviceManager() );
+ m_fileTreeView->setCurrentDevice( k3bappcore->appDeviceManager()->currentDevice() );
+
+ m_fileView->setAutoUpdate( true ); // in case we look at the mounted path
+
+ if( m_mainSplitter ) {
+ // split
+ QValueList<int> sizes = m_mainSplitter->sizes();
+ int all = sizes[0] + sizes[1];
+ sizes[1] = all*2/3;
+ sizes[0] = all - sizes[1];
+ m_mainSplitter->setSizes( sizes );
+ }
+
+ connect( m_fileTreeView, SIGNAL(urlExecuted(const KURL&)),
+ this, SLOT(slotDirActivated(const KURL&)) );
+ connect( m_fileTreeView, SIGNAL(deviceExecuted(K3bDevice::Device*)),
+ this, SLOT(showDevice(K3bDevice::Device*)) );
+ connect( m_fileTreeView, SIGNAL(deviceExecuted(K3bDevice::Device*)),
+ this, SIGNAL(deviceSelected(K3bDevice::Device*)) );
+ connect( m_fileTreeView, SIGNAL(contextMenu(K3bDevice::Device*, const QPoint&)),
+ this, SLOT(slotFileTreeContextMenu(K3bDevice::Device*, const QPoint&)) );
+
+ connect( m_fileView, SIGNAL(urlEntered(const KURL&)), m_fileTreeView, SLOT(followUrl(const KURL&)) );
+ connect( m_fileView, SIGNAL(urlEntered(const KURL&)), this, SIGNAL(urlEntered(const KURL&)) );
+
+ connect( k3bappcore->appDeviceManager(), SIGNAL(mountFinished(const QString&)),
+ this, SLOT(slotMountFinished(const QString&)) );
+ connect( k3bappcore->appDeviceManager(), SIGNAL(unmountFinished(bool)),
+ this, SLOT(slotUnmountFinished(bool)) );
+ connect( k3bappcore->appDeviceManager(), SIGNAL(detectingDiskInfo(K3bDevice::Device*)),
+ this, SLOT(slotDetectingDiskInfo(K3bDevice::Device*)) );
+}
+
+K3bDirView::~K3bDirView()
+{
+ delete d;
+}
+
+
+void K3bDirView::showUrl( const KURL& url )
+{
+ slotDirActivated( url );
+}
+
+
+void K3bDirView::showDevice( K3bDevice::Device* dev )
+{
+ d->contextMediaInfoRequested = true;
+ m_fileTreeView->setSelectedDevice( dev );
+ showMediumInfo( k3bappcore->mediaCache()->medium( dev ) );
+}
+
+
+void K3bDirView::slotDetectingDiskInfo( K3bDevice::Device* dev )
+{
+ d->contextMediaInfoRequested = false;
+ m_fileTreeView->setSelectedDevice( dev );
+ showMediumInfo( k3bappcore->mediaCache()->medium( dev ) );
+}
+
+
+void K3bDirView::showMediumInfo( const K3bMedium& medium )
+{
+ if( !d->contextMediaInfoRequested ||
+ medium.diskInfo().diskState() == K3bDevice::STATE_EMPTY ||
+ medium.diskInfo().diskState() == K3bDevice::STATE_NO_MEDIA ) {
+
+ // show cd info
+ m_viewStack->raiseWidget( m_infoView );
+ m_infoView->reload( medium );
+ return;
+ }
+
+#ifdef HAVE_LIBDVDREAD
+ else if( medium.content() & K3bMedium::CONTENT_VIDEO_DVD ) {
+ KMessageBox::ButtonCode r = KMessageBox::Yes;
+ if( KMessageBox::shouldBeShownYesNo( "videodvdripping", r ) ) {
+ r = (KMessageBox::ButtonCode)
+ KMessageBox::questionYesNoCancel( this,
+ i18n("<p>You have selected the K3b Video DVD ripping tool."
+ "<p>It is intended to <em>rip single titles</em> from a video DVD "
+ "into a compressed format such as XviD. Menu structures are completely ignored."
+ "<p>If you intend to copy the plain Video DVD vob files from the DVD "
+ "(including decryption) for further processing with another application, "
+ "please use the following link to access the Video DVD file structure: "
+ "<a href=\"videodvd:/\">videodvd:/</a>"
+ "<p>If you intend to make a copy of the entire Video DVD including all menus "
+ "and extras it is recommended to use the K3b DVD Copy tool."),
+ i18n("Video DVD ripping"),
+ i18n("Continue"),
+ i18n("Open DVD Copy Dialog"),
+ "videodvdripping",
+ KMessageBox::AllowLink );
+ }
+ else { // if we do not show the dialog we always continue with the ripping. Everything else would be confusing
+ r = KMessageBox::Yes;
+ }
+
+ if( r == KMessageBox::Cancel ) {
+ // m_viewStack->raiseWidget( m_fileView );
+ }
+ else if( r == KMessageBox::No ) {
+ m_viewStack->raiseWidget( m_fileView );
+ static_cast<K3bMainWindow*>( kapp->mainWidget() )->slotDvdCopy();
+ }
+ else {
+ m_movieView->reload( medium );
+ m_viewStack->raiseWidget( m_movieView );
+ }
+
+ return;
+ }
+#endif
+
+ else if( medium.content() & K3bMedium::CONTENT_DATA ) {
+ bool mount = true;
+ if( medium.content() & K3bMedium::CONTENT_VIDEO_CD ) {
+ if( !k3bcore ->externalBinManager() ->foundBin( "vcdxrip" ) ) {
+ KMessageBox::sorry( this,
+ i18n("K3b uses vcdxrip from the vcdimager package to rip Video CDs. "
+ "Please make sure it is installed.") );
+ }
+ else {
+ if( KMessageBox::questionYesNo( this,
+ i18n("Found %1. Do you want K3b to mount the data part "
+ "or show all the tracks?").arg( i18n("Video CD") ),
+ i18n("Video CD"),
+ i18n("Mount CD"),
+ i18n("Show Video Tracks") ) == KMessageBox::No ) {
+ mount = false;
+ m_viewStack->raiseWidget( m_videoView );
+ m_videoView->reload( medium );
+ }
+ }
+ }
+ else if( medium.content() & K3bMedium::CONTENT_AUDIO ) {
+ if( KMessageBox::questionYesNo( this,
+ i18n("Found %1. Do you want K3b to mount the data part "
+ "or show all the tracks?").arg( i18n("Audio CD") ),
+ i18n("Audio CD"),
+ i18n("Mount CD"),
+ i18n("Show Audio Tracks") ) == KMessageBox::No ) {
+ mount = false;
+ m_viewStack->raiseWidget( m_cdView );
+ m_cdView->reload( medium );
+ }
+ }
+
+ if( mount )
+ k3bappcore->appDeviceManager()->mountDisk( medium.device() );
+ }
+
+ else if( medium.content() & K3bMedium::CONTENT_AUDIO ) {
+ m_viewStack->raiseWidget( m_cdView );
+ m_cdView->reload( medium );
+ }
+
+ else {
+ // show cd info
+ m_viewStack->raiseWidget( m_infoView );
+ m_infoView->reload( medium );
+ }
+
+ d->contextMediaInfoRequested = false;
+}
+
+
+void K3bDirView::slotMountFinished( const QString& mp )
+{
+ if( !mp.isEmpty() ) {
+ slotDirActivated( mp );
+ m_fileView->reload(); // HACK to get the contents shown... FIXME
+ }
+ else {
+ m_viewStack->raiseWidget( m_fileView );
+ K3bPassivePopup::showPopup( i18n("<p>K3b was unable to mount medium <b>%1</b> in device <em>%2 - %3</em>")
+ .arg( k3bappcore->mediaCache()->medium( k3bappcore->appDeviceManager()->currentDevice() ).shortString() )
+ .arg( k3bappcore->appDeviceManager()->currentDevice()->vendor() )
+ .arg( k3bappcore->appDeviceManager()->currentDevice()->description() ),
+ i18n("Mount Failed"),
+ K3bPassivePopup::Warning );
+ }
+}
+
+
+void K3bDirView::slotUnmountFinished( bool success )
+{
+ if( success ) {
+ // TODO: check if the fileview is still displaying a folder from the medium
+ }
+ else {
+ K3bPassivePopup::showPopup( i18n("<p>K3b was unable to unmount medium <b>%1</b> in device <em>%2 - %3</em>")
+ .arg( k3bappcore->mediaCache()->medium( k3bappcore->appDeviceManager()->currentDevice() ).shortString() )
+ .arg( k3bappcore->appDeviceManager()->currentDevice()->vendor() )
+ .arg( k3bappcore->appDeviceManager()->currentDevice()->description() ),
+ i18n("Unmount Failed"),
+ K3bPassivePopup::Warning );
+ }
+}
+
+
+void K3bDirView::slotFileTreeContextMenu( K3bDevice::Device* /*dev*/, const QPoint& p )
+{
+ KAction* a = k3bappcore->appDeviceManager()->actionCollection()->action( "device_popup" );
+ if( KActionMenu* m = dynamic_cast<KActionMenu*>(a) )
+ m->popup( p );
+}
+
+
+void K3bDirView::slotDirActivated( const QString& url )
+{
+// m_urlCombo->insertItem( url, 0 );
+ slotDirActivated( KURL::fromPathOrURL(url) );
+}
+
+
+void K3bDirView::slotDirActivated( const KURL& url )
+{
+ m_fileView->setUrl(url, true);
+// m_urlCombo->setEditText( url.path() );
+
+ m_viewStack->raiseWidget( m_fileView );
+}
+
+
+void K3bDirView::home()
+{
+ slotDirActivated( QDir::homeDirPath() );
+}
+
+
+void K3bDirView::saveConfig( KConfig* c )
+{
+ m_fileView->saveConfig(c);
+}
+
+
+void K3bDirView::readConfig( KConfig* c )
+{
+ m_fileView->readConfig(c);
+}
+
+#include "k3bdirview.moc"
diff --git a/src/k3bdirview.h b/src/k3bdirview.h
new file mode 100644
index 0000000..7d4cdf0
--- /dev/null
+++ b/src/k3bdirview.h
@@ -0,0 +1,100 @@
+/*
+ *
+ * $Id: k3bdirview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDIRVIEW_H
+#define K3BDIRVIEW_H
+
+#include <qvbox.h>
+
+#include <k3bmedium.h>
+
+class QSplitter;
+class KURL;
+class K3bAudioCdView;
+class K3bVideoCdView;
+class K3bFileView;
+class K3bVideoDVDRippingView;
+class KComboBox;
+class K3bFileTreeView;
+class QWidgetStack;
+class K3bDiskInfoView;
+class QScrollView;
+class QLabel;
+class KConfig;
+class K3bDeviceBranch;
+
+namespace K3bDevice {
+ class Device;
+ class DiskInfo;
+}
+
+namespace KIO {
+ class Job;
+}
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bDirView : public QVBox
+{
+ Q_OBJECT
+
+ public:
+ K3bDirView(K3bFileTreeView* tree, QWidget *parent=0, const char *name=0);
+ ~K3bDirView();
+
+ public slots:
+ void saveConfig( KConfig* c );
+ void readConfig( KConfig* c );
+ void showUrl( const KURL& );
+ void showDevice( K3bDevice::Device* );
+
+ protected slots:
+ void slotDirActivated( const KURL& );
+ void slotDirActivated( const QString& );
+ void slotMountFinished( const QString& );
+ void slotUnmountFinished( bool );
+ void showMediumInfo( const K3bMedium& );
+ void slotDetectingDiskInfo( K3bDevice::Device* dev );
+ void home();
+ void slotFileTreeContextMenu( K3bDevice::Device* dev, const QPoint& p );
+
+ signals:
+ void urlEntered( const KURL& );
+ void deviceSelected( K3bDevice::Device* );
+
+ private:
+ QWidgetStack* m_viewStack;
+ QScrollView* m_scroll;
+
+ K3bAudioCdView* m_cdView;
+ K3bVideoCdView* m_videoView;
+ K3bVideoDVDRippingView* m_movieView;
+ K3bFileView* m_fileView;
+ K3bDiskInfoView* m_infoView;
+
+ KComboBox* m_urlCombo;
+ QSplitter* m_mainSplitter;
+ K3bFileTreeView* m_fileTreeView;
+
+ bool m_bViewDiskInfo;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3bdiskinfoview.cpp b/src/k3bdiskinfoview.cpp
new file mode 100644
index 0000000..4a1208f
--- /dev/null
+++ b/src/k3bdiskinfoview.cpp
@@ -0,0 +1,500 @@
+/*
+ *
+ * $Id: k3bdiskinfoview.cpp 643214 2007-03-16 15:25:24Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+
+#include "k3bdiskinfoview.h"
+
+#include <k3bdiskinfo.h>
+#include <k3bcdtext.h>
+#include <k3bdeviceglobals.h>
+#include <k3bglobals.h>
+#include <k3bstdguiitems.h>
+#include <k3blistview.h>
+#include <k3biso9660.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qfont.h>
+#include <qcolor.h>
+#include <qheader.h>
+#include <qstring.h>
+#include <qpainter.h>
+#include <qpalette.h>
+#include <qpixmap.h>
+#include <qregion.h>
+#include <qframe.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kio/global.h>
+
+
+// FIXME: use K3bListViewItem instead
+class K3bDiskInfoView::HeaderViewItem : public KListViewItem
+{
+public:
+ HeaderViewItem( QListView* parent )
+ : KListViewItem( parent ) {}
+ HeaderViewItem( QListViewItem* parent )
+ : KListViewItem( parent ) {}
+ HeaderViewItem( QListView* parent, QListViewItem* after )
+ : KListViewItem( parent, after ) {}
+ HeaderViewItem( QListViewItem* parent, QListViewItem* after )
+ : KListViewItem( parent, after ) {}
+ HeaderViewItem( QListView* parent, const QString& t1 )
+ : KListViewItem( parent, t1 ) {}
+ HeaderViewItem( QListViewItem* parent, const QString& t1 )
+ : KListViewItem( parent, t1 ) {}
+ HeaderViewItem( QListView* parent, QListViewItem* after, const QString& t1 )
+ : KListViewItem( parent, after, t1 ) {}
+ HeaderViewItem( QListViewItem* parent, QListViewItem* after, const QString& t1 )
+ : KListViewItem( parent, after, t1 ) {}
+
+ void paintCell( QPainter* p, const QColorGroup & cg, int column, int width, int align )
+ {
+ QFont f ( p->font() );
+ f.setBold( true );
+ p->setFont( f );
+ KListViewItem::paintCell( p, cg, column, width, align );
+ }
+};
+
+
+class K3bDiskInfoView::TwoColumnViewItem : public KListViewItem
+{
+public:
+ TwoColumnViewItem( QListView* parent )
+ : KListViewItem( parent ) {}
+ TwoColumnViewItem( QListViewItem* parent )
+ : KListViewItem( parent ) {}
+ TwoColumnViewItem( QListView* parent, QListViewItem* after )
+ : KListViewItem( parent, after ) {}
+ TwoColumnViewItem( QListViewItem* parent, QListViewItem* after )
+ : KListViewItem( parent, after ) {}
+ TwoColumnViewItem( QListView* parent, const QString& t1 )
+ : KListViewItem( parent, t1 ) {}
+ TwoColumnViewItem( QListViewItem* parent, const QString& t1 )
+ : KListViewItem( parent, t1 ) {}
+ TwoColumnViewItem( QListView* parent, QListViewItem* after, const QString& t1 )
+ : KListViewItem( parent, after, t1 ) {}
+ TwoColumnViewItem( QListViewItem* parent, QListViewItem* after, const QString& t1 )
+ : KListViewItem( parent, after, t1 ) {}
+
+ void paintCell( QPainter* p, const QColorGroup & cg, int column, int width, int align )
+ {
+
+ if( column == 1 ) {
+ int newWidth = width;
+
+ int i = 2;
+ for( ; i < listView()->columns(); ++i ) {
+ newWidth += listView()->columnWidth( i );
+ }
+
+ // TODO: find a way to get the TRUE new width after resizing
+
+ // QRect r = p->clipRegion().boundingRect();
+ // r.setWidth( newWidth );
+ // p->setClipRect( r );
+ p->setClipping( false );
+
+ KListViewItem::paintCell( p, cg, column, newWidth, align );
+ } else if( column == 0 )
+ KListViewItem::paintCell( p, cg, column, width, align );
+ }
+};
+
+
+
+K3bDiskInfoView::K3bDiskInfoView( QWidget* parent, const char* name )
+ : K3bMediaContentsView( true,
+ K3bMedium::CONTENT_ALL,
+ K3bDevice::MEDIA_ALL|K3bDevice::MEDIA_UNKNOWN,
+ K3bDevice::STATE_EMPTY|K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_COMPLETE|K3bDevice::STATE_UNKNOWN,
+ parent, name )
+{
+ m_infoView = new KListView( this );
+ setMainWidget( m_infoView );
+
+ m_infoView->setSorting( -1 );
+ m_infoView->setAllColumnsShowFocus( true );
+ m_infoView->setSelectionMode( QListView::NoSelection );
+ m_infoView->setResizeMode( KListView::AllColumns );
+ m_infoView->setAlternateBackground( QColor() );
+
+ m_infoView->addColumn( "1" );
+ m_infoView->addColumn( "2" );
+ m_infoView->addColumn( "3" );
+ m_infoView->addColumn( "4" );
+#ifdef K3B_DEBUG
+ m_infoView->addColumn( "index0" );
+#endif
+
+ m_infoView->header()->hide();
+
+ // do not automatically reload the disk info
+ // setAutoReload( false );
+}
+
+
+K3bDiskInfoView::~K3bDiskInfoView()
+{}
+
+
+void K3bDiskInfoView::reloadMedium()
+{
+ m_infoView->clear();
+
+ setTitle( medium().shortString( true ) );
+
+ if( medium().diskInfo().diskState() == K3bDevice::STATE_NO_MEDIA ) {
+ (void)new QListViewItem( m_infoView, i18n("No medium present") );
+ setRightPixmap( K3bTheme::MEDIA_NONE );
+ }
+ else {
+ if( medium().diskInfo().empty() ) {
+ setRightPixmap( K3bTheme::MEDIA_EMPTY );
+ }
+ else {
+ switch( medium().toc().contentType() ) {
+ case K3bDevice::AUDIO:
+ setRightPixmap( K3bTheme::MEDIA_AUDIO );
+ break;
+ case K3bDevice::DATA: {
+ if( medium().content() & K3bMedium::CONTENT_VIDEO_DVD ) {
+ setRightPixmap( K3bTheme::MEDIA_VIDEO );
+ }
+ else {
+ setRightPixmap( K3bTheme::MEDIA_DATA );
+ }
+ break;
+ }
+ case K3bDevice::MIXED:
+ setRightPixmap( K3bTheme::MEDIA_MIXED );
+ break;
+ default:
+ setTitle( i18n("Unknown Disk Type") );
+ setRightPixmap( K3bTheme::MEDIA_NONE );
+ }
+ }
+
+ createMediaInfoItems( medium() );
+
+
+ // iso9660 info
+ // /////////////////////////////////////////////////////////////////////////////////////
+ if( medium().content() & K3bMedium::CONTENT_DATA ) {
+ (void)new KListViewItem( m_infoView, m_infoView->lastChild() ); // empty spacer item
+ createIso9660InfoItems( medium().iso9660Descriptor() );
+ }
+
+ // tracks
+ // /////////////////////////////////////////////////////////////////////////////////////
+ if( !medium().toc().isEmpty() ) {
+
+ if( m_infoView->childCount() )
+ (void)new KListViewItem( m_infoView, m_infoView->lastChild() ); // empty spacer item
+
+ KListViewItem* trackHeaderItem = new HeaderViewItem( m_infoView, m_infoView->lastChild(), i18n("Tracks") );
+
+ // create header item
+ KListViewItem* item = new KListViewItem( trackHeaderItem,
+ i18n("Type"),
+ i18n("Attributes"),
+ i18n("First-Last Sector"),
+ i18n("Length") );
+
+#ifdef K3B_DEBUG
+ item->setText( 4, "Index0" );
+#endif
+
+ int lastSession = 0;
+
+ // if we have multiple sessions we create a header item for every session
+ KListViewItem* trackItem = 0;
+ if( medium().diskInfo().numSessions() > 1 && medium().toc()[0].session() > 0 ) {
+ trackItem = new HeaderViewItem( trackHeaderItem, item, i18n("Session %1").arg(1) );
+ lastSession = 1;
+ }
+ else
+ trackItem = trackHeaderItem;
+
+ // create items for the tracks
+ K3bDevice::Toc::const_iterator it;
+ int index = 1;
+ for( it = medium().toc().begin(); it != medium().toc().end(); ++it ) {
+ const K3bTrack& track = *it;
+
+ if( medium().diskInfo().numSessions() > 1 && track.session() != lastSession ) {
+ lastSession = track.session();
+ trackItem->setOpen(true);
+ trackItem = new HeaderViewItem( trackHeaderItem,
+ m_infoView->lastItem()->parent(),
+ i18n("Session %1").arg(lastSession) );
+ }
+
+ item = new KListViewItem( trackItem, item );
+ QString text;
+ if( track.type() == K3bTrack::AUDIO ) {
+ item->setPixmap( 0, SmallIcon( "sound" ) );
+ text = i18n("Audio");
+ } else {
+ item->setPixmap( 0, SmallIcon( "tar" ) );
+ if( track.mode() == K3bTrack::MODE1 )
+ text = i18n("Data/Mode1");
+ else if( track.mode() == K3bTrack::MODE2 )
+ text = i18n("Data/Mode2");
+ else if( track.mode() == K3bTrack::XA_FORM1 )
+ text = i18n("Data/Mode2 XA Form1");
+ else if( track.mode() == K3bTrack::XA_FORM2 )
+ text = i18n("Data/Mode2 XA Form2");
+ else
+ text = i18n("Data");
+ }
+ item->setText( 0, i18n("%1 (%2)").arg( QString::number(index).rightJustify( 2, ' ' )).arg(text) );
+ item->setText( 1, QString( "%1/%2" )
+ .arg( track.copyPermitted() ? i18n("copy") : i18n("no copy") )
+ .arg( track.type() == K3bTrack::AUDIO
+ ? ( track.preEmphasis() ? i18n("preemp") : i18n("no preemp") )
+ : ( track.recordedIncremental() ? i18n("incremental") : i18n("uninterrupted") ) ) );
+ item->setText( 2,
+ QString("%1 - %2")
+ .arg(track.firstSector().lba())
+ .arg(track.lastSector().lba()) );
+ item->setText( 3, QString::number( track.length().lba() ) + " (" + track.length().toString() + ")" );
+
+#ifdef K3B_DEBUG
+ if( track.type() == K3bTrack::AUDIO )
+ item->setText( 4, QString( "%1 (%2)" ).arg(track.index0().toString()).arg(track.index0().lba()) );
+#endif
+ ++index;
+ }
+
+ trackItem->setOpen(true);
+ trackHeaderItem->setOpen( true );
+ }
+
+
+ // CD-TEXT
+ // /////////////////////////////////////////////////////////////////////////////////////
+ if( !medium().cdText().isEmpty() ) {
+ medium().cdText().debug();
+ if( m_infoView->childCount() )
+ (void)new KListViewItem( m_infoView, m_infoView->lastChild() ); // empty spacer item
+
+ KListViewItem* cdTextHeaderItem = new HeaderViewItem( m_infoView,
+ m_infoView->lastChild(),
+ i18n("CD-TEXT (excerpt)") );
+
+ // create header item
+ KListViewItem* item = new KListViewItem( cdTextHeaderItem,
+ i18n("Performer"),
+ i18n("Title"),
+ i18n("Songwriter"),
+ i18n("Composer") );
+ item = new KListViewItem( cdTextHeaderItem, item );
+ item->setText( 0, i18n("CD:") + " " +
+ medium().cdText().performer() );
+ item->setText( 1, medium().cdText().title() );
+ item->setText( 2, medium().cdText().songwriter() );
+ item->setText( 3, medium().cdText().composer() );
+
+ int index = 1;
+ for( unsigned int i = 0; i < medium().cdText().count(); ++i ) {
+ item = new KListViewItem( cdTextHeaderItem, item );
+ item->setText( 0, QString::number(index).rightJustify( 2, ' ' ) + " " +
+ medium().cdText().at(i).performer() );
+ item->setText( 1, medium().cdText().at(i).title() );
+ item->setText( 2, medium().cdText().at(i).songwriter() );
+ item->setText( 3, medium().cdText().at(i).composer() );
+ ++index;
+ }
+
+ cdTextHeaderItem->setOpen( true );
+ }
+ }
+}
+
+
+void K3bDiskInfoView::createMediaInfoItems( const K3bMedium& medium )
+{
+ const K3bDevice::DiskInfo& info = medium.diskInfo();
+
+ KListViewItem* atipItem = new HeaderViewItem( m_infoView, m_infoView->lastItem(), i18n("Medium") );
+ QString typeStr;
+ if( info.mediaType() != K3bDevice::MEDIA_UNKNOWN )
+ typeStr = K3bDevice::mediaTypeString( info.mediaType() );
+ else
+ typeStr = i18n("Unknown (probably CD-ROM)");
+
+ KListViewItem* atipChild = new KListViewItem( atipItem, i18n("Type:"), typeStr );
+
+ if( info.isDvdMedia() )
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Media ID:"),
+ !info.mediaId().isEmpty() ? QString::fromLatin1( info.mediaId() ) : i18n("unknown") );
+
+
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Capacity:"),
+ i18n("%1 min").arg(info.capacity().toString()),
+ KIO::convertSize(info.capacity().mode1Bytes()) );
+
+ if( !info.empty() )
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Used Capacity:"),
+ i18n("%1 min").arg(info.size().toString()),
+ KIO::convertSize(info.size().mode1Bytes()) );
+
+ if( info.appendable() )
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Remaining:"),
+ i18n("%1 min").arg( info.remainingSize().toString() ),
+ KIO::convertSize(info.remainingSize().mode1Bytes()) );
+
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Rewritable:"),
+ info.rewritable() ? i18n("yes") : i18n("no") );
+
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Appendable:"),
+ info.appendable() ? i18n("yes") : i18n("no") );
+
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Empty:"),
+ info.empty() ? i18n("yes") : i18n("no") );
+
+ if( info.isDvdMedia() )
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Layers:"),
+ QString::number( info.numLayers() ) );
+
+ if( info.mediaType() == K3bDevice::MEDIA_DVD_PLUS_RW ) {
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Background Format:") );
+ switch( info.bgFormatState() ) {
+ case K3bDevice::BG_FORMAT_NONE:
+ atipChild->setText( 1, i18n("not formatted") );
+ break;
+ case K3bDevice::BG_FORMAT_INCOMPLETE:
+ atipChild->setText( 1, i18n("incomplete") );
+ break;
+ case K3bDevice::BG_FORMAT_IN_PROGRESS:
+ atipChild->setText( 1, i18n("in progress") );
+ break;
+ case K3bDevice::BG_FORMAT_COMPLETE:
+ atipChild->setText( 1, i18n("complete") );
+ break;
+ }
+ }
+
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Sessions:"),
+ QString::number( info.numSessions() ) );
+
+ if( info.mediaType() & K3bDevice::MEDIA_WRITABLE ) {
+ atipChild = new KListViewItem( atipItem, atipChild,
+ i18n("Supported writing speeds:") );
+ QString s;
+ if( medium.writingSpeeds().isEmpty() )
+ s = "-";
+ else
+ for( QValueList<int>::const_iterator it = medium.writingSpeeds().begin();
+ it != medium.writingSpeeds().end(); ++it ) {
+ if( !s.isEmpty() ) {
+ s.append( "\n" );
+ atipChild->setMultiLinesEnabled( true );
+ }
+
+ if( info.isDvdMedia() )
+ s.append( QString().sprintf( "%.1fx (%d KB/s)", (double)*it / 1385.0, *it ) );
+ else
+ s.append( QString( "%1x (%2 KB/s)" ).arg( *it/175 ).arg( *it ) );
+ }
+
+ atipChild->setText( 1, s );
+ }
+
+ atipItem->setOpen( true );
+}
+
+
+void K3bDiskInfoView::createIso9660InfoItems( const K3bIso9660SimplePrimaryDescriptor& iso )
+{
+ KListViewItem* iso9660Item = new HeaderViewItem( m_infoView, m_infoView->lastChild(),
+ i18n("ISO9660 Filesystem Info") );
+ KListViewItem* iso9660Child = 0;
+
+ iso9660Child = new KListViewItem( iso9660Item, iso9660Child,
+ i18n("System Id:"),
+ iso.systemId.isEmpty()
+ ? QString("-")
+ : iso.systemId );
+ iso9660Child = new KListViewItem( iso9660Item, iso9660Child,
+ i18n("Volume Id:"),
+ iso.volumeId.isEmpty()
+ ? QString("-")
+ : iso.volumeId );
+ iso9660Child = new KListViewItem( iso9660Item, iso9660Child,
+ i18n("Volume Set Id:"),
+ iso.volumeSetId.isEmpty()
+ ? QString("-")
+ : iso.volumeSetId );
+ iso9660Child = new KListViewItem( iso9660Item, iso9660Child,
+ i18n("Publisher Id:"),
+ iso.publisherId.isEmpty()
+ ? QString("-")
+ : iso.publisherId );
+ iso9660Child = new KListViewItem( iso9660Item, iso9660Child,
+ i18n("Preparer Id:"),
+ iso.preparerId.isEmpty()
+ ? QString("-")
+ : iso.preparerId );
+ iso9660Child = new KListViewItem( iso9660Item, iso9660Child,
+ i18n("Application Id:"),
+ iso.applicationId.isEmpty()
+ ? QString("-")
+ : iso.applicationId );
+// iso9660Child = new KListViewItem( iso9660Item, iso9660Child,
+// i18n("Volume Size:"),
+// QString( "%1 (%2*%3)" )
+// .arg(iso.logicalBlockSize
+// *iso.volumeSpaceSize)
+// .arg(iso.logicalBlockSize)
+// .arg(iso.volumeSpaceSize),
+// KIO::convertSize(iso.logicalBlockSize
+// *iso.volumeSpaceSize) );
+
+ iso9660Item->setOpen( true );
+}
+
+
+void K3bDiskInfoView::enableInteraction( bool enable )
+{
+ QListViewItemIterator it( m_infoView );
+ while( it.current() ) {
+ it.current()->setEnabled( enable );
+ ++it;
+ }
+}
+
+#include "k3bdiskinfoview.moc"
+
diff --git a/src/k3bdiskinfoview.h b/src/k3bdiskinfoview.h
new file mode 100644
index 0000000..7c817a7
--- /dev/null
+++ b/src/k3bdiskinfoview.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * $Id: k3bdiskinfoview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef K3BDISKINFOVIEW_H
+#define K3BDISKINFOVIEW_H
+
+#include "k3bmediacontentsview.h"
+#include "k3bmedium.h"
+
+class QLabel;
+class KListView;
+class K3bIso9660;
+
+namespace K3bDevice {
+ class DiskInfoDetector;
+ class DiskInfo;
+}
+
+class K3bDiskInfoView : public K3bMediaContentsView
+{
+ Q_OBJECT
+
+ public:
+ K3bDiskInfoView( QWidget* parent = 0, const char* name = 0 );
+ ~K3bDiskInfoView();
+
+ void enableInteraction( bool enable );
+
+ private:
+ void reloadMedium();
+
+ void createMediaInfoItems( const K3bMedium& );
+ void createIso9660InfoItems( const K3bIso9660SimplePrimaryDescriptor& );
+
+ KListView* m_infoView;
+
+ class HeaderViewItem;
+ class TwoColumnViewItem;
+};
+
+
+#endif
diff --git a/src/k3bemptydiscwaiter.cpp b/src/k3bemptydiscwaiter.cpp
new file mode 100644
index 0000000..7e11198
--- /dev/null
+++ b/src/k3bemptydiscwaiter.cpp
@@ -0,0 +1,761 @@
+/*
+ *
+ * $Id: k3bemptydiscwaiter.cpp 642801 2007-03-15 12:39:04Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bemptydiscwaiter.h"
+#include "k3bmediacache.h"
+#include "k3bapplication.h"
+#include <k3bdevice.h>
+#include <k3bdeviceglobals.h>
+#include <k3bdevicehandler.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+#include <k3biso9660.h>
+#include "k3bblankingjob.h"
+#include <k3bbusywidget.h>
+#include <k3bprogressdialog.h>
+#include <k3bdvdformattingjob.h>
+
+#include <qtimer.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qpushbutton.h>
+#include <qapplication.h>
+#include <qeventloop.h>
+#include <qfont.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kactivelabel.h>
+#include <knotifyclient.h>
+
+
+class K3bEmptyDiscWaiter::Private
+{
+public:
+ Private()
+ : erasingInfoDialog(0) {
+ dialogVisible = false;
+ inLoop = false;
+ mediumChanged = 0;
+ blockMediaChange = false;
+ }
+
+ K3bDevice::Device* device;
+
+ int wantedMediaType;
+ int wantedMediaState;
+
+ QString wantedMediaTypeString;
+
+ int result;
+ int dialogVisible;
+ bool inLoop;
+
+ bool blockMediaChange;
+ int mediumChanged;
+
+ bool forced;
+ bool canceled;
+
+ bool waitingDone;
+
+ QLabel* labelRequest;
+ QLabel* labelFoundMedia;
+ QLabel* pixLabel;
+
+ K3bProgressDialog* erasingInfoDialog;
+};
+
+
+
+K3bEmptyDiscWaiter::K3bEmptyDiscWaiter( K3bDevice::Device* device, QWidget* parent, const char* name )
+ : KDialogBase( KDialogBase::Plain, i18n("Waiting for Disk"),
+ KDialogBase::Cancel|KDialogBase::User1|KDialogBase::User2|KDialogBase::User3,
+ KDialogBase::User3, parent, name, true, true, i18n("Force"), i18n("Eject"), i18n("Load") )
+{
+ d = new Private();
+ d->device = device;
+
+ // setup the gui
+ // -----------------------------
+ d->labelRequest = new QLabel( plainPage() );
+ d->labelRequest->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
+ d->labelFoundMedia = new QLabel( plainPage() );
+ d->pixLabel = new QLabel( plainPage() );
+ d->pixLabel->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
+
+ QFont f( d->labelFoundMedia->font() );
+ f.setBold(true);
+ d->labelFoundMedia->setFont( f );
+
+ QGridLayout* grid = new QGridLayout( plainPage() );
+ grid->setMargin( marginHint() );
+ grid->setSpacing( spacingHint() );
+
+ grid->addMultiCellWidget( d->pixLabel, 0, 2, 0, 0 );
+ grid->addColSpacing( 1, 20 );
+ grid->addWidget( new QLabel( i18n("Found media:"), plainPage() ), 0, 2 );
+ grid->addWidget( d->labelFoundMedia, 0, 3 );
+ grid->addMultiCellWidget( d->labelRequest, 1, 1, 2, 3 );
+ grid->setRowStretch( 2, 1 );
+ grid->setColStretch( 3, 1 );
+ // -----------------------------
+
+ connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3bDevice::Device*)),
+ this, SLOT(slotMediumChanged(K3bDevice::Device*)) );
+
+ QToolTip::add( actionButton(KDialogBase::User1),
+ i18n("Force K3b to continue if it seems not to detect your empty CD/DVD.") );
+}
+
+
+K3bEmptyDiscWaiter::~K3bEmptyDiscWaiter()
+{
+ delete d;
+}
+
+
+int K3bEmptyDiscWaiter::waitForDisc( int mediaState, int mediaType, const QString& message )
+{
+ if ( d->inLoop ) {
+ kdError() << "(K3bEmptyDiscWaiter) Recursive call detected." << endl;
+ return -1;
+ }
+
+ d->wantedMediaState = mediaState;
+ d->wantedMediaType = mediaType;
+ d->dialogVisible = false;
+ d->forced = false;
+ d->canceled = false;
+ d->waitingDone = false;
+ d->blockMediaChange = false;
+ d->mediumChanged = 0;
+
+ //
+ // We do not cover every case here but just the ones that really make sense
+ //
+ if( (d->wantedMediaType & K3bDevice::MEDIA_WRITABLE_DVD) &&
+ (d->wantedMediaType & K3bDevice::MEDIA_WRITABLE_CD) )
+ d->wantedMediaTypeString = i18n("CD-R(W) or DVD%1R(W)").arg("");
+ else if( d->wantedMediaType & K3bDevice::MEDIA_WRITABLE_DVD_SL )
+ d->wantedMediaTypeString = i18n("DVD%1R(W)").arg("");
+ else if( d->wantedMediaType & K3bDevice::MEDIA_WRITABLE_DVD_DL )
+ d->wantedMediaTypeString = i18n("Double Layer DVD%1R").arg("");
+ else
+ d->wantedMediaTypeString = i18n("CD-R(W)");
+
+ if( message.isEmpty() ) {
+ if( (d->wantedMediaState & K3bDevice::STATE_COMPLETE) && (d->wantedMediaState & K3bDevice::STATE_INCOMPLETE) )
+ d->labelRequest->setText( i18n("Please insert a complete or appendable %4 medium "
+ "into drive<p><b>%1 %2 (%3)</b>.")
+ .arg(d->device->vendor())
+ .arg(d->device->description())
+ .arg(d->device->devicename())
+ .arg( d->wantedMediaTypeString ) );
+ else if( d->wantedMediaState & K3bDevice::STATE_COMPLETE )
+ d->labelRequest->setText( i18n("Please insert a complete %4 medium "
+ "into drive<p><b>%1 %2 (%3)</b>.")
+ .arg(d->device->vendor())
+ .arg(d->device->description())
+ .arg(d->device->devicename())
+ .arg( d->wantedMediaTypeString ) );
+ else if( (d->wantedMediaState & K3bDevice::STATE_INCOMPLETE) && (d->wantedMediaState & K3bDevice::STATE_EMPTY) )
+ d->labelRequest->setText( i18n("Please insert an empty or appendable %4 medium "
+ "into drive<p><b>%1 %2 (%3)</b>.")
+ .arg(d->device->vendor())
+ .arg(d->device->description())
+ .arg(d->device->devicename())
+ .arg( d->wantedMediaTypeString ) );
+ else if( d->wantedMediaState & K3bDevice::STATE_INCOMPLETE )
+ d->labelRequest->setText( i18n("Please insert an appendable %4 medium "
+ "into drive<p><b>%1 %2 (%3)</b>.")
+ .arg(d->device->vendor())
+ .arg(d->device->description())
+ .arg(d->device->devicename())
+ .arg( d->wantedMediaTypeString ) );
+ else if( d->wantedMediaState & K3bDevice::STATE_EMPTY )
+ d->labelRequest->setText( i18n("Please insert an empty %4 medium "
+ "into drive<p><b>%1 %2 (%3)</b>.")
+ .arg(d->device->vendor())
+ .arg(d->device->description())
+ .arg(d->device->devicename())
+ .arg( d->wantedMediaTypeString ) );
+ else // fallback case (this should not happen in K3b)
+ d->labelRequest->setText( i18n("Please insert a suitable medium "
+ "into drive<p><b>%1 %2 (%3)</b>.")
+ .arg(d->device->vendor())
+ .arg(d->device->description())
+ .arg(d->device->devicename()) );
+
+ }
+ else
+ d->labelRequest->setText( message );
+
+ if( d->wantedMediaType & K3bDevice::MEDIA_WRITABLE_DVD )
+ d->pixLabel->setPixmap( KGlobal::instance()->iconLoader()->loadIcon( "dvd_unmount",
+ KIcon::NoGroup, KIcon::SizeMedium ) );
+ else
+ d->pixLabel->setPixmap( KGlobal::instance()->iconLoader()->loadIcon( "cdwriter_unmount",
+ KIcon::NoGroup, KIcon::SizeMedium ) );
+
+ adjustSize();
+
+ slotMediumChanged( d->device );
+
+ //
+ // in case we already found a medium and thus the dialog is not shown entering
+ // the loop only causes problems (since there is no dialog yet the user could
+ // not have forced or canceled yet
+ //
+ if( !d->waitingDone ) {
+ d->inLoop = true;
+ QApplication::eventLoop()->enterLoop();
+ }
+
+ return d->result;
+}
+
+
+int K3bEmptyDiscWaiter::exec()
+{
+ return waitForDisc();
+}
+
+
+void K3bEmptyDiscWaiter::slotMediumChanged( K3bDevice::Device* dev )
+{
+ kdDebug() << "(K3bEmptyDiscWaiter) slotMediumChanged() " << endl;
+ if( d->forced || d->canceled || d->device != dev )
+ return;
+
+ //
+ // This slot may open dialogs which enter a new event loop and that
+ // may result in another call to this slot if a medium changes while
+ // a dialog is open
+ //
+ if( d->blockMediaChange ) {
+ d->mediumChanged++;
+ return;
+ }
+
+ d->blockMediaChange = true;
+
+ KConfig* c = k3bcore->config();
+ bool formatWithoutAsking = KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "auto rewritable erasing", false );
+
+ K3bMedium medium = k3bappcore->mediaCache()->medium( dev );
+
+ d->labelFoundMedia->setText( medium.shortString( false ) );
+
+ if( medium.diskInfo().diskState() == K3bDevice::STATE_NO_MEDIA ) {
+ continueWaiting();
+ d->blockMediaChange = false;
+ return;
+ }
+
+// QString mediaState;
+// if( medium.diskInfo().diskState() == K3bDevice::STATE_COMPLETE )
+// mediaState = i18n("complete");
+// else if( medium.diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE )
+// mediaState = i18n("appendable");
+// else if( medium.diskInfo().diskState() == K3bDevice::STATE_EMPTY )
+// mediaState = i18n("empty");
+
+// if( !mediaState.isEmpty() )
+// mediaState = " (" + mediaState +")";
+
+
+ // /////////////////////////////////////////////////////////////
+ //
+ // DVD+RW handling
+ //
+ // /////////////////////////////////////////////////////////////
+
+ // DVD+RW: if empty we need to preformat. Although growisofs does it before writing doing it here
+ // allows better control and a progress bar. If it's not empty we should check if there is
+ // already a filesystem on the media.
+ if( (d->wantedMediaType & K3bDevice::MEDIA_DVD_PLUS_RW) &&
+ (medium.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_PLUS_RW) ) {
+
+ kdDebug() << "(K3bEmptyDiscWaiter) ------ found DVD+RW as wanted." << endl;
+
+ if( medium.diskInfo().diskState() == K3bDevice::STATE_EMPTY ) {
+ if( d->wantedMediaState & K3bDevice::STATE_EMPTY ) {
+ // special case for the formatting job which wants to preformat on it's own!
+ if( d->wantedMediaState & K3bDevice::STATE_COMPLETE &&
+ d->wantedMediaState & K3bDevice::STATE_EMPTY ) {
+ kdDebug() << "(K3bEmptyDiscWaiter) special case: DVD+RW for the formatting job." << endl;
+ finishWaiting( K3bDevice::MEDIA_DVD_PLUS_RW );
+ }
+ else {
+ // empty - preformat without asking
+ prepareErasingDialog();
+
+ K3bDvdFormattingJob job( this );
+ job.setDevice( d->device );
+ job.setQuickFormat( true );
+ job.setForce( false );
+ job.setForceNoEject( true );
+
+ d->erasingInfoDialog->setText( i18n("Preformatting DVD+RW") );
+ connect( &job, SIGNAL(finished(bool)), this, SLOT(slotErasingFinished(bool)) );
+ connect( &job, SIGNAL(percent(int)), d->erasingInfoDialog, SLOT(setProgress(int)) );
+ connect( d->erasingInfoDialog, SIGNAL(cancelClicked()), &job, SLOT(cancel()) );
+ job.start( medium.diskInfo() );
+ d->erasingInfoDialog->exec( true );
+ }
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) starting devicehandler: empty DVD+RW where a non-empty was requested." << endl;
+ continueWaiting();
+ }
+ }
+ else {
+ //
+ // We have a DVD+RW medium which is already preformatted
+ //
+ if( d->wantedMediaState == K3bDevice::STATE_EMPTY ) {
+ // check if the media contains a filesystem
+ K3bIso9660 isoF( d->device );
+ bool hasIso = isoF.open();
+
+ if( formatWithoutAsking ||
+ !hasIso ||
+ KMessageBox::warningContinueCancel( parentWidgetToUse(),
+ i18n("Found %1 media in %2 - %3. "
+ "Should it be overwritten?")
+ .arg("DVD+RW")
+ .arg(d->device->vendor())
+ .arg(d->device->description()),
+ i18n("Found %1").arg("DVD+RW"),i18n("Overwrite") ) == KMessageBox::Continue ) {
+ finishWaiting( K3bDevice::MEDIA_DVD_PLUS_RW );
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) starting devicehandler: no DVD+RW overwrite" << endl;
+ K3b::unmount( d->device );
+ K3bDevice::eject( d->device );
+ continueWaiting();
+ }
+ }
+
+ //
+ // We want a DVD+RW not nessessarily empty. No problem, just use this one. Becasue incomplete and complete
+ // are handled the same everywhere (isofs is grown).
+ //
+ else {
+ finishWaiting( K3bDevice::MEDIA_DVD_PLUS_RW );
+ }
+ }
+ } // --- DVD+RW --------
+
+
+ // /////////////////////////////////////////////////////////////
+ //
+ // DVD-RW handling
+ //
+ // /////////////////////////////////////////////////////////////
+
+ //
+ // DVD-RW in sequential mode can be empty. DVD-RW in restricted overwrite mode is always complete.
+ //
+ else if( (d->wantedMediaType & (K3bDevice::MEDIA_DVD_RW|
+ K3bDevice::MEDIA_DVD_RW_SEQ|
+ K3bDevice::MEDIA_DVD_RW_OVWR) ) &&
+ (medium.diskInfo().mediaType() & (K3bDevice::MEDIA_DVD_RW|
+ K3bDevice::MEDIA_DVD_RW_SEQ|
+ K3bDevice::MEDIA_DVD_RW_OVWR) ) ) {
+
+ kdDebug() << "(K3bEmptyDiscWaiter) ------ found DVD-R(W) as wanted." << endl;
+
+ // we format in the following cases:
+ // seq. incr. and not empty and empty requested
+ // seq. incr. and restr. overwri. reqested
+ // restr. ovw. and seq. incr. requested
+
+ // we have exactly what was requested
+ if( (d->wantedMediaType & medium.diskInfo().mediaType()) &&
+ (d->wantedMediaState & medium.diskInfo().diskState()) ) {
+ finishWaiting( medium.diskInfo().mediaType() );
+ }
+
+ // DVD-RW in restr. overwrite may just be overwritten
+ else if( (medium.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_RW_OVWR) &&
+ (d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_OVWR) ) {
+ if( d->wantedMediaState == K3bDevice::STATE_EMPTY ) {
+
+ kdDebug() << "(K3bEmptyDiscWaiter) ------ DVD-RW restricted overwrite." << endl;
+
+ // check if the media contains a filesystem
+ K3bIso9660 isoF( d->device );
+ bool hasIso = isoF.open();
+
+ if( formatWithoutAsking ||
+ !hasIso ||
+ KMessageBox::warningContinueCancel( parentWidgetToUse(),
+ i18n("Found %1 media in %2 - %3. "
+ "Should it be overwritten?")
+ .arg(K3bDevice::mediaTypeString(medium.diskInfo().mediaType()))
+ .arg(d->device->vendor())
+ .arg(d->device->description()),
+ i18n("Found %1").arg("DVD-RW"),i18n("Overwrite") ) == KMessageBox::Continue ) {
+ finishWaiting( K3bDevice::MEDIA_DVD_RW_OVWR );
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) starting devicehandler: no DVD-RW overwrite." << endl;
+ K3b::unmount( d->device );
+ K3bDevice::eject( d->device );
+ continueWaiting();
+ }
+ }
+
+ else if( !(d->wantedMediaState & K3bDevice::STATE_EMPTY ) ) {
+ // check if the media contains a filesystem
+ K3bIso9660 isoF( d->device );
+ bool hasIso = isoF.open();
+
+ if( hasIso ) {
+ finishWaiting( K3bDevice::MEDIA_DVD_RW_OVWR );
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) starting devicehandler: empty DVD-RW where a non-empty was requested." << endl;
+ continueWaiting();
+ }
+ }
+
+ //
+ // We want a DVD-RW overwrite not nessessarily empty. No problem, just use this one. Becasue incomplete and complete
+ // are handled the same everywhere (isofs is grown).
+ //
+ else {
+ finishWaiting( K3bDevice::MEDIA_DVD_RW_OVWR );
+ }
+ }
+
+ // formatting
+ else if( ( (d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_OVWR) &&
+ (medium.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_RW_SEQ) &&
+ !(d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_SEQ) ) ||
+
+ ( (d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_SEQ) &&
+ (medium.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_RW_OVWR) &&
+ !(d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_OVWR) ) ||
+
+ ( (d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_SEQ) &&
+ (medium.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_RW_SEQ) &&
+ (d->wantedMediaState & K3bDevice::STATE_EMPTY) &&
+ (medium.diskInfo().diskState() != K3bDevice::STATE_EMPTY) ) ) {
+
+ kdDebug() << "(K3bEmptyDiscWaiter) ------ DVD-RW needs to be formated." << endl;
+
+ if( formatWithoutAsking ||
+ KMessageBox::warningContinueCancel( parentWidgetToUse(),
+ i18n("Found %1 media in %2 - %3. "
+ "Should it be formatted?")
+ .arg( K3bDevice::mediaTypeString(medium.diskInfo().mediaType()) )
+ .arg(d->device->vendor())
+ .arg(d->device->description()),
+ i18n("Found %1").arg("DVD-RW"), i18n("Format") ) == KMessageBox::Continue ) {
+
+ kdDebug() << "(K3bEmptyDiscWaiter) ------ formatting DVD-RW." << endl;
+
+ prepareErasingDialog();
+
+ K3bDvdFormattingJob job( this );
+ job.setDevice( d->device );
+ // we prefere the current mode of the media if no special mode has been requested
+ job.setMode( ( (d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_SEQ) &&
+ (d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_OVWR) )
+ ? ( medium.diskInfo().mediaType() == K3bDevice::MEDIA_DVD_RW_OVWR
+ ? K3b::WRITING_MODE_RES_OVWR
+ : K3b::WRITING_MODE_INCR_SEQ )
+ : ( (d->wantedMediaType & K3bDevice::MEDIA_DVD_RW_SEQ)
+ ? K3b::WRITING_MODE_INCR_SEQ
+ : K3b::WRITING_MODE_RES_OVWR ) );
+ job.setQuickFormat( true );
+ job.setForce( false );
+ job.setForceNoEject(true);
+
+ d->erasingInfoDialog->setText( i18n("Formatting DVD-RW") );
+ connect( &job, SIGNAL(finished(bool)), this, SLOT(slotErasingFinished(bool)) );
+ connect( &job, SIGNAL(percent(int)), d->erasingInfoDialog, SLOT(setProgress(int)) );
+ connect( d->erasingInfoDialog, SIGNAL(cancelClicked()), &job, SLOT(cancel()) );
+ job.start( medium.diskInfo() );
+ d->erasingInfoDialog->exec( true );
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) starting devicehandler: no DVD-RW formatting." << endl;
+ K3b::unmount( d->device );
+ K3bDevice::eject( d->device );
+ continueWaiting();
+ }
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) ------ nothing useful found." << endl;
+ continueWaiting();
+ }
+ } // --- DVD-RW ------
+
+
+ // /////////////////////////////////////////////////////////////
+ //
+ // CD handling (and DVD-R and DVD+R)
+ //
+ // /////////////////////////////////////////////////////////////
+
+ // we have exactly what was requested
+ else if( (d->wantedMediaType & medium.diskInfo().mediaType()) &&
+ (d->wantedMediaState & medium.diskInfo().diskState()) )
+ finishWaiting( medium.diskInfo().mediaType() );
+
+ else if( (medium.diskInfo().mediaType() != K3bDevice::MEDIA_UNKNOWN) &&
+ (d->wantedMediaType & medium.diskInfo().mediaType()) &&
+ (d->wantedMediaState & medium.diskInfo().diskState()) )
+ finishWaiting( medium.diskInfo().mediaType() );
+
+ // this is for CD drives that are not able to determine the state of a disk
+ else if( medium.diskInfo().diskState() == K3bDevice::STATE_UNKNOWN &&
+ medium.diskInfo().mediaType() == K3bDevice::MEDIA_CD_ROM &&
+ d->wantedMediaType & K3bDevice::MEDIA_CD_ROM )
+ finishWaiting( medium.diskInfo().mediaType() );
+
+ // format CD-RW
+ else if( (d->wantedMediaType & medium.diskInfo().mediaType()) &&
+ (d->wantedMediaState & K3bDevice::STATE_EMPTY) &&
+ medium.diskInfo().rewritable() ) {
+
+ if( formatWithoutAsking ||
+ KMessageBox::questionYesNo( parentWidgetToUse(),
+ i18n("Found rewritable media in %1 - %2. "
+ "Should it be erased?").arg(d->device->vendor()).arg(d->device->description()),
+ i18n("Found Rewritable Disk"),
+ KGuiItem(i18n("&Erase"), "cdrwblank"),
+ KGuiItem(i18n("E&ject")) ) == KMessageBox::Yes ) {
+
+
+ prepareErasingDialog();
+
+ // start a k3bblankingjob
+ d->erasingInfoDialog->setText( i18n("Erasing CD-RW") );
+
+ // the user may be using cdrdao for erasing as cdrecord does not work
+ int erasingApp = K3b::DEFAULT;
+ if( KConfigGroup( c, "General Options" ).readBoolEntry( "Manual writing app selection", false ) ) {
+ erasingApp = K3b::writingAppFromString( KConfigGroup( c, "CDRW Erasing" ).readEntry( "writing_app" ) );
+ }
+
+ K3bBlankingJob job( this );
+ job.setDevice( d->device );
+ job.setMode( K3bBlankingJob::Fast );
+ job.setForce(true);
+ job.setForceNoEject(true);
+ job.setSpeed( 0 ); // Auto
+ job.setWritingApp( erasingApp );
+ connect( &job, SIGNAL(finished(bool)), this, SLOT(slotErasingFinished(bool)) );
+ connect( d->erasingInfoDialog, SIGNAL(cancelClicked()), &job, SLOT(cancel()) );
+ job.start();
+ d->erasingInfoDialog->exec( false );
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) starting devicehandler: no CD-RW overwrite." << endl;
+ K3b::unmount( d->device );
+ K3bDevice::eject( d->device );
+ continueWaiting();
+ }
+ }
+ else {
+ kdDebug() << "(K3bEmptyDiscWaiter) ------ nothing useful found." << endl;
+ continueWaiting();
+ }
+
+ // handle queued medium changes
+ d->blockMediaChange = false;
+ if( d->mediumChanged > 0 ) {
+ d->mediumChanged--;
+ slotMediumChanged( dev );
+ }
+}
+
+
+void K3bEmptyDiscWaiter::showDialog()
+{
+ // we need to show the dialog if not done already
+ if( !d->dialogVisible ) {
+
+ KNotifyClient::event( 0, "WaitingForMedium", i18n("Waiting for Medium") );
+
+ d->dialogVisible = true;
+ clearWFlags( WDestructiveClose );
+ setWFlags( WShowModal );
+ setResult( 0 );
+ show();
+ }
+}
+
+
+void K3bEmptyDiscWaiter::continueWaiting()
+{
+ showDialog();
+}
+
+
+void K3bEmptyDiscWaiter::slotCancel()
+{
+ kdDebug() << "(K3bEmptyDiscWaiter) slotCancel() " << endl;
+ d->canceled = true;
+ finishWaiting( CANCELED );
+}
+
+
+void K3bEmptyDiscWaiter::slotUser1()
+{
+ d->forced = true;
+ finishWaiting( DISK_READY );
+}
+
+
+void K3bEmptyDiscWaiter::slotUser2()
+{
+ K3b::unmount( d->device );
+ K3bDevice::eject( d->device );
+}
+
+
+void K3bEmptyDiscWaiter::slotUser3()
+{
+ K3bDevice::load( d->device );
+}
+
+
+void K3bEmptyDiscWaiter::finishWaiting( int code )
+{
+ kdDebug() << "(K3bEmptyDiscWaiter) finishWaiting() " << endl;
+
+ d->waitingDone = true;
+ d->result = code;
+
+ if( d->dialogVisible )
+ hide();
+
+ if( d->inLoop ) {
+ d->inLoop = false;
+ kdDebug() << "(K3bEmptyDiscWaiter) exitLoop " << endl;
+ QApplication::eventLoop()->exitLoop();
+ }
+}
+
+
+void K3bEmptyDiscWaiter::slotErasingFinished( bool success )
+{
+ if( success ) {
+ connect( K3bDevice::reload( d->device ),
+ SIGNAL(finished(K3bDevice::DeviceHandler*)),
+ this,
+ SLOT(slotReloadingAfterErasingFinished(K3bDevice::DeviceHandler*)) );
+ }
+ else {
+ K3bDevice::eject( d->device );
+ KMessageBox::error( d->erasingInfoDialog, i18n("Erasing failed.") );
+ d->erasingInfoDialog->hide(); // close the dialog thus ending it's event loop -> back to slotMediumChanged
+ }
+}
+
+
+void K3bEmptyDiscWaiter::slotReloadingAfterErasingFinished( K3bDevice::DeviceHandler* )
+{
+ // close the dialog thus ending it's event loop -> back to slotMediumChanged
+ d->erasingInfoDialog->hide();
+}
+
+
+int K3bEmptyDiscWaiter::wait( K3bDevice::Device* device, bool appendable, int mediaType, QWidget* parent )
+{
+ K3bEmptyDiscWaiter d( device, parent ? parent : qApp->activeWindow() );
+ int mediaState = K3bDevice::STATE_EMPTY;
+ if( appendable ) mediaState |= K3bDevice::STATE_INCOMPLETE;
+ return d.waitForDisc( mediaState, mediaType );
+}
+
+
+int K3bEmptyDiscWaiter::wait( K3bDevice::Device* device,
+ int mediaState,
+ int mediaType,
+ const QString& message,
+ QWidget* parent )
+{
+ K3bEmptyDiscWaiter d( device, parent ? parent : qApp->activeWindow() );
+ return d.waitForDisc( mediaState, mediaType, message );
+}
+
+
+void K3bEmptyDiscWaiter::prepareErasingDialog()
+{
+ // we hide the emptydiskwaiter so the info dialog needs to have the same parent
+ if( !d->erasingInfoDialog )
+ d->erasingInfoDialog = new K3bProgressDialog( QString::null, parentWidget() );
+
+ //
+ // hide the dialog
+ //
+ if( d->dialogVisible ) {
+ hide();
+ d->dialogVisible = false;
+ }
+}
+
+
+QWidget* K3bEmptyDiscWaiter::parentWidgetToUse()
+{
+ // we might also show dialogs if the discwaiter widget is not visible yet
+ if( d->dialogVisible )
+ return this;
+ else
+ return parentWidget();
+}
+
+
+int K3bEmptyDiscWaiter::waitForMedia( K3bDevice::Device* device,
+ int mediaState,
+ int mediaType,
+ const QString& message )
+{
+ // this is only needed for the formatting
+ return wait( device, mediaState, mediaType, message, d->erasingInfoDialog );
+}
+
+
+bool K3bEmptyDiscWaiter::questionYesNo( const QString& text,
+ const QString& caption,
+ const QString& yesText,
+ const QString& noText )
+{
+ return ( KMessageBox::questionYesNo( parentWidgetToUse(),
+ text,
+ caption,
+ yesText.isEmpty() ? KStdGuiItem::yes() : KGuiItem(yesText),
+ noText.isEmpty() ? KStdGuiItem::no() : KGuiItem(noText) ) == KMessageBox::Yes );
+}
+
+
+void K3bEmptyDiscWaiter::blockingInformation( const QString& text,
+ const QString& caption )
+{
+ KMessageBox::information( this, text, caption );
+}
+
+#include "k3bemptydiscwaiter.moc"
diff --git a/src/k3bemptydiscwaiter.h b/src/k3bemptydiscwaiter.h
new file mode 100644
index 0000000..ce3bced
--- /dev/null
+++ b/src/k3bemptydiscwaiter.h
@@ -0,0 +1,139 @@
+/*
+ *
+ * $Id: k3bemptydiscwaiter.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BEMPTYDISCWAITER_H
+#define K3BEMPTYDISCWAITER_H
+
+#include <kdialogbase.h>
+#include <k3bjobhandler.h>
+
+#include <k3bdiskinfo.h>
+
+namespace K3bDevice {
+ class Device;
+ class DeviceHandler;
+}
+
+
+/**
+ * Tests for an empty cd in a given device.
+ *
+ * Use the static wait methods.
+ *
+ * @author Sebastian Trueg
+ */
+class K3bEmptyDiscWaiter : public KDialogBase, public K3bJobHandler
+{
+ Q_OBJECT
+
+ public:
+ ~K3bEmptyDiscWaiter();
+
+ /**
+ * This should be replaced by the mediaType that was found or -1 for forced.
+ * MEDIA_NONE if canceled.
+ */
+ enum returnValue { DISK_READY = 0,
+ CANCELED = -1 };
+
+ /**
+ * the same as waitForEmptyDisc( false );
+ */
+ int exec();
+
+ /**
+ * @reimplemented from K3bJobHandler
+ * \internal do not use!
+ */
+ int waitForMedia( K3bDevice::Device*,
+ int mediaState = K3bDevice::STATE_EMPTY,
+ int mediaType = K3bDevice::MEDIA_WRITABLE_CD,
+ const QString& message = QString::null );
+
+ /**
+ * @reimplemented from K3bJobHandler
+ */
+ bool questionYesNo( const QString& text,
+ const QString& caption = QString::null,
+ const QString& yesText = QString::null,
+ const QString& noText = QString::null );
+
+ /**
+ * reimplemented from K3bJobHandler
+ */
+ void blockingInformation( const QString& text,
+ const QString& caption = QString::null );
+
+ /**
+ * This only openes a dialog if the first check failed.
+ */
+ static int wait( K3bDevice::Device* device,
+ bool appendable = false,
+ int mediaType = K3bDevice::MEDIA_WRITABLE_CD,
+ QWidget* parent = 0 );
+
+ /**
+ * Starts the emptydiskwaiter.
+ *
+ * \param mediaState a bitwise combination of the K3bDevice::State enum
+ * \param mediaType a bitwise combination of the K3bDevice::MediaType enum
+ * \return the found MediaType on success, 0 if forced and -1 if canceled
+ */
+ static int wait( K3bDevice::Device*,
+ int mediaState,
+ int mediaType = K3bDevice::MEDIA_WRITABLE_CD,
+ const QString& message = QString::null,
+ QWidget* parent = 0 );
+
+ protected slots:
+ void slotCancel();
+ void slotUser1();
+ void slotUser2();
+ void slotUser3();
+ void slotMediumChanged( K3bDevice::Device* );
+ void showDialog();
+ void continueWaiting();
+ void slotErasingFinished( bool );
+ void slotReloadingAfterErasingFinished( K3bDevice::DeviceHandler* );
+
+ protected:
+ /**
+ * Use the static wait methods.
+ */
+ explicit K3bEmptyDiscWaiter( K3bDevice::Device* device, QWidget* parent = 0, const char* name = 0 );
+
+ int waitForDisc( int mediaState = K3bDevice::STATE_EMPTY,
+ int mediaType = K3bDevice::MEDIA_WRITABLE_CD,
+ const QString& message = QString::null );
+
+
+ /**
+ * Nobody closes this dialog but itself!
+ */
+ void closeEvent( QCloseEvent* ) {}
+
+ private:
+ void finishWaiting( int );
+ void prepareErasingDialog();
+
+ QWidget* parentWidgetToUse();
+
+ class Private;
+ Private* d;
+};
+
+
+#endif
diff --git a/src/k3bfiletreecombobox.cpp b/src/k3bfiletreecombobox.cpp
new file mode 100644
index 0000000..ce9b6b7
--- /dev/null
+++ b/src/k3bfiletreecombobox.cpp
@@ -0,0 +1,393 @@
+/*
+ *
+ * $Id: k3bfiletreecombobox.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bfiletreecombobox.h"
+#include "k3bfiletreeview.h"
+
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+
+#include <qrect.h>
+#include <qapplication.h>
+#include <qstyle.h>
+#include <qlistbox.h>
+#include <qheader.h>
+#include <qevent.h>
+#include <qpainter.h>
+#include <qpalette.h>
+#include <qdrawutil.h>
+#include <qdir.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kurlcompletion.h>
+#include <kuser.h>
+
+
+class K3bFileTreeComboBox::Private
+{
+public:
+ Private() {
+ poppedUp = false;
+ ignoreNextMouseClick = false;
+ }
+ bool poppedUp;
+ bool ignoreNextMouseClick; // used when the view was hidden with the arrow button
+
+ KURLCompletion* urlCompletion;
+};
+
+
+K3bFileTreeComboBox::K3bFileTreeComboBox( QWidget* parent, const char* name )
+ : KComboBox( true, parent, name )
+{
+ d = new Private;
+
+ d->urlCompletion = new KURLCompletion();
+ setCompletionObject( d->urlCompletion );
+
+ m_fileTreeView = new K3bFileTreeView( this );
+ m_fileTreeView->hide();
+ m_fileTreeView->reparent( this, WType_Popup, QPoint(0,0), false );
+ m_fileTreeView->header()->hide();
+ m_fileTreeView->installEventFilter(this);
+
+ m_fileTreeView->addDefaultBranches();
+ m_fileTreeView->addCdDeviceBranches( k3bcore->deviceManager() );
+
+ // HACK! Why the hell is QComboBox that closed???
+ listBox()->insertItem( "HACK" );
+
+ connect( m_fileTreeView, SIGNAL(deviceExecuted(K3bDevice::Device*)),
+ this, SLOT(slotDeviceExecuted(K3bDevice::Device*)) );
+ connect( m_fileTreeView, SIGNAL(urlExecuted(const KURL&)),
+ this, SLOT(slotUrlExecuted(const KURL&)) );
+
+ connect( lineEdit(), SIGNAL(returnPressed()),
+ this, SLOT(slotGoUrl()) );
+
+ // TODO: subclass KURLCompletition to support the dev:/ stuff and block any non-local urls
+}
+
+
+K3bFileTreeComboBox::~K3bFileTreeComboBox()
+{
+ delete d->urlCompletion;
+ delete d;
+}
+
+
+void K3bFileTreeComboBox::slotDeviceExecuted( K3bDevice::Device* dev )
+{
+ setDevice( dev );
+ popdown();
+ emit deviceExecuted( dev );
+}
+
+
+void K3bFileTreeComboBox::slotUrlExecuted( const KURL& url )
+{
+ setUrl( url );
+ emit urlExecuted( url );
+}
+
+
+void K3bFileTreeComboBox::setUrl( const KURL& url )
+{
+ setEditText( SmallIcon("folder"), K3b::convertToLocalUrl(url).path() );
+ popdown();
+}
+
+
+void K3bFileTreeComboBox::setDevice( K3bDevice::Device* dev )
+{
+ setEditText( SmallIcon("cdrom_unmount"), dev->vendor() + " " + dev->description() + " (" + dev->blockDeviceName() + ")" );
+}
+
+
+void K3bFileTreeComboBox::setEditText( const QPixmap& pix, const QString& t )
+{
+ // QComboBox::changeItem() doesn't honor the pixmap when
+ // using an editable combobox, so we just remove and insert
+
+ setUpdatesEnabled( false );
+ lineEdit()->setUpdatesEnabled( false );
+
+ removeItem(0);
+ insertItem( pix, t, 0 );
+ lineEdit()->setText( t );
+
+ setUpdatesEnabled( true );
+ lineEdit()->setUpdatesEnabled( true );
+ update();
+}
+
+
+void K3bFileTreeComboBox::setCurrentItem( int )
+{
+ // the current item is always 0 due to the ugly but quite smart HACK ;)
+}
+
+
+void K3bFileTreeComboBox::setCurrentText( const QString& )
+{
+}
+
+
+void K3bFileTreeComboBox::popup()
+{
+ // code mainly from qcombobox.cpp
+
+ m_fileTreeView->triggerUpdate();
+ int w = QMAX( m_fileTreeView->sizeHint().width(), width() );
+ int h = m_fileTreeView->sizeHint().height();
+ QRect screen = QApplication::desktop()->availableGeometry( this );
+ int sx = screen.x(); // screen pos
+ int sy = screen.y();
+ int sw = screen.width(); // screen width
+ int sh = screen.height(); // screen height
+ QPoint pos = mapToGlobal( QPoint(0,height()) );
+ // ## Similar code is in QPopupMenu
+ int x = pos.x();
+ int y = pos.y();
+
+ // the complete widget must be visible
+ if ( x + w > sx + sw )
+ x = sx+sw - w;
+ if ( x < sx )
+ x = sx;
+ if (y + h > sy+sh && y - h - height() >= 0 )
+ y = y - h - height();
+
+ QRect rect =
+ style().querySubControlMetrics( QStyle::CC_ComboBox, this,
+ QStyle::SC_ComboBoxListBoxPopup,
+ QStyleOption( x, y, w, h ) );
+ // work around older styles that don't implement the combobox
+ // listbox popup subcontrol
+ if ( rect.isNull() )
+ rect.setRect( x, y, w, h );
+
+ m_fileTreeView->setGeometry( rect );
+ m_fileTreeView->raise();
+
+ // TODO: somehow set the current item
+
+ m_fileTreeView->show();
+ d->poppedUp = true;
+ d->ignoreNextMouseClick = false;
+}
+
+
+void K3bFileTreeComboBox::popdown()
+{
+ m_fileTreeView->hide();
+ d->poppedUp = false;
+ repaint(); // repaint the arrow
+}
+
+
+void K3bFileTreeComboBox::slotGoUrl()
+{
+ QString p = currentText();
+
+ // check for a media url or a device string
+ if( K3bDevice::Device* dev = K3b::urlToDevice( p ) ) {
+ emit deviceExecuted( dev );
+ return;
+ }
+
+ // check for our own internal format
+ else if( p.contains("/dev/") ) {
+ int pos1 = p.findRev('(');
+ int pos2 = p.findRev(')');
+ QString devStr = p.mid( pos1+1, pos2-pos1-1 );
+ if( K3bDevice::Device* dev = k3bcore->deviceManager()->findDevice( devStr ) ) {
+ emit deviceExecuted( dev );
+ return;
+ }
+ }
+
+ // no device -> select url
+
+ //
+ // Properly replace home dirs.
+ // a single ~ will be replaced with the current user's home dir
+ // while for example "~ftp" will be replaced by the home dir of user
+ // ftp
+ //
+ // TODO: move this to k3bglobals
+
+ // to expand another user's home dir we need a tilde followed by a user name
+ static QRegExp someUsersHomeDir( "\\~([^/]+)" );
+ int pos = 0;
+ while( ( pos = someUsersHomeDir.search( p, pos ) ) != -1 ) {
+ KUser user( someUsersHomeDir.cap(1) );
+ if( user.isValid() )
+ p.replace( pos, someUsersHomeDir.cap(1).length() + 1, user.homeDir() );
+ else
+ ++pos; // skip this ~
+ }
+
+ // now replace the unmatched tildes with our home dir
+ p.replace( "~", K3b::prepareDir( QDir::homeDirPath() ) );
+
+
+ lineEdit()->setText( p );
+ KURL url;
+ url.setPath( p );
+ emit urlExecuted( url );
+}
+
+
+bool K3bFileTreeComboBox::eventFilter( QObject* o, QEvent* e )
+{
+ if( dynamic_cast<K3bFileTreeView*>(o) == m_fileTreeView ) {
+ if( e->type() == QEvent::DragLeave ) {
+ // the user dragged a dir from the filetree
+ // now
+ popdown();
+ return true;
+ }
+ else if( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *k = (QKeyEvent *)e;
+ if( k->key() == Qt::Key_Escape ) {
+ popdown();
+ return true;
+ }
+ }
+ else if( e->type() == QEvent::MouseButtonPress ) {
+ QMouseEvent* me = (QMouseEvent*)e;
+ if ( !m_fileTreeView->rect().contains( me->pos() ) ) {
+ QRect arrowRect = style().querySubControlMetrics( QStyle::CC_ComboBox, this,
+ QStyle::SC_ComboBoxArrow);
+ arrowRect = QStyle::visualRect(arrowRect, this);
+
+ // Correction for motif style, where arrow is smaller
+ // and thus has a rect that doesn't fit the button.
+ arrowRect.setHeight( QMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) );
+
+ if ( arrowRect.contains( mapFromGlobal(me->globalPos()) ) ) {
+ d->ignoreNextMouseClick = true; // in the case we hit the arrow button
+ }
+ popdown();
+ }
+ return false; // we need this in the listview
+ }
+
+ return false;
+ }
+ else
+ return KComboBox::eventFilter(o, e);
+}
+
+
+void K3bFileTreeComboBox::mousePressEvent( QMouseEvent* e )
+{
+ // mainly from qcombobox.cpp
+
+ if ( e->button() != LeftButton )
+ return;
+ if ( d->ignoreNextMouseClick ) {
+ d->ignoreNextMouseClick = FALSE;
+ return;
+ }
+
+ QRect arrowRect = style().querySubControlMetrics( QStyle::CC_ComboBox, this,
+ QStyle::SC_ComboBoxArrow);
+ arrowRect = QStyle::visualRect(arrowRect, this);
+
+ // Correction for motif style, where arrow is smaller
+ // and thus has a rect that doesn't fit the button.
+ arrowRect.setHeight( QMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) );
+
+ if ( arrowRect.contains( e->pos() ) ) {
+ popup();
+ repaint( FALSE );
+ }
+}
+
+
+void K3bFileTreeComboBox::keyPressEvent( QKeyEvent* e )
+{
+ if( e->key() == Qt::Key_Escape ) {
+ popdown();
+ }
+ KComboBox::keyPressEvent(e);
+}
+
+
+void K3bFileTreeComboBox::paintEvent( QPaintEvent* )
+{
+ // a lot of code from qcombobox.cpp
+
+ // we only need this since there is no way to change the status of the arrow-button
+
+ QPainter p( this );
+ const QColorGroup & g = colorGroup();
+ p.setPen(g.text());
+
+ QStyle::SFlags flags = QStyle::Style_Default;
+ if (isEnabled())
+ flags |= QStyle::Style_Enabled;
+ if (hasFocus())
+ flags |= QStyle::Style_HasFocus;
+
+ if ( width() < 5 || height() < 5 ) {
+ qDrawShadePanel( &p, rect(), g, FALSE, 2,
+ &g.brush( QColorGroup::Button ) );
+ return;
+ }
+
+ // bool reverse = QApplication::reverseLayout();
+
+ style().drawComplexControl( QStyle::CC_ComboBox, &p, this, rect(), g,
+ flags, QStyle::SC_All,
+ (d->poppedUp ?
+ QStyle::SC_ComboBoxArrow :
+ QStyle::SC_None ));
+
+ QRect re = style().querySubControlMetrics( QStyle::CC_ComboBox, this,
+ QStyle::SC_ComboBoxEditField );
+ re = QStyle::visualRect(re, this);
+ p.setClipRect( re );
+
+// QListBoxItem * item = listBox()->item( 0 );
+// if ( item ) {
+// // we calculate the QListBoxTexts height (ignoring strut)
+// int itemh = d->listBox()->fontMetrics().lineSpacing() + 2;
+// p.translate( re.x(), re.y() + (re.height() - itemh)/2 );
+// item->paint( &p );
+// }
+// } else if ( d->listBox() && d->listBox()->item( 0 ) ) {
+ p.setClipping( FALSE );
+ QListBoxItem * item = listBox()->item( 0 );
+ const QPixmap *pix = item->pixmap();
+ if ( pix ) {
+ p.fillRect( re.x(), re.y(), pix->width() + 4, re.height(),
+ colorGroup().brush( QColorGroup::Base ) );
+ p.drawPixmap( re.x() + 2, re.y() +
+ ( re.height() - pix->height() ) / 2, *pix );
+ }
+// }
+ p.setClipping( FALSE );
+}
+
+
+#include "k3bfiletreecombobox.moc"
+
diff --git a/src/k3bfiletreecombobox.h b/src/k3bfiletreecombobox.h
new file mode 100644
index 0000000..50bc683
--- /dev/null
+++ b/src/k3bfiletreecombobox.h
@@ -0,0 +1,72 @@
+/*
+ *
+ * $Id: k3bfiletreecombobox.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_FILETREE_COMBOBOX_H_
+#define _K3B_FILETREE_COMBOBOX_H_
+
+#include <kcombobox.h>
+
+class K3bFileTreeView;
+class QEvent;
+class QKeyEvent;
+class QMouseEvent;
+class QPaintEvent;
+
+namespace K3bDevice {
+ class Device;
+}
+
+class K3bFileTreeComboBox : public KComboBox
+{
+ Q_OBJECT
+
+ public:
+ K3bFileTreeComboBox( QWidget* parent = 0, const char* name = 0 );
+ ~K3bFileTreeComboBox();
+
+ void popup();
+ void popdown();
+
+ void setCurrentItem( int );
+ void setCurrentText( const QString& );
+
+ public slots:
+ void setDevice( K3bDevice::Device* );
+ void setUrl( const KURL& url );
+ void slotGoUrl();
+
+ signals:
+ void urlExecuted( const KURL& url );
+ void deviceExecuted( K3bDevice::Device* dev );
+
+ private slots:
+ void slotDeviceExecuted( K3bDevice::Device* );
+ void slotUrlExecuted( const KURL& url );
+
+ protected:
+ bool eventFilter( QObject*, QEvent* );
+ void keyPressEvent( QKeyEvent* );
+ void mousePressEvent( QMouseEvent* );
+ void paintEvent( QPaintEvent* );
+
+ private:
+ void setEditText( const QPixmap& pix, const QString& t );
+
+ class Private;
+ Private* d;
+ K3bFileTreeView* m_fileTreeView;
+};
+
+#endif
diff --git a/src/k3bfiletreeview.cpp b/src/k3bfiletreeview.cpp
new file mode 100644
index 0000000..36c86c3
--- /dev/null
+++ b/src/k3bfiletreeview.cpp
@@ -0,0 +1,728 @@
+/*
+ *
+ * $Id: k3bfiletreeview.cpp 657858 2007-04-25 08:25:11Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bfiletreeview.h"
+#include "k3bappdevicemanager.h"
+#include "k3bapplication.h"
+#include "k3bmediacache.h"
+#include "k3btooltip.h"
+#include "k3bthememanager.h"
+
+#include <k3bdevice.h>
+#include <k3bdiskinfo.h>
+#include <k3bglobals.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kstandarddirs.h>
+#include <kaction.h>
+#include <kio/global.h>
+#include <kfileitem.h>
+#include <kapplication.h>
+#include <kglobalsettings.h>
+
+#include <qdir.h>
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qcursor.h>
+#include <qnamespace.h>
+#include <qmap.h>
+#include <qptrdict.h>
+#include <qpainter.h>
+#include <qfont.h>
+#include <qstyle.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+
+K3bDeviceBranch::K3bDeviceBranch( KFileTreeView* view, K3bDevice::Device* dev, KFileTreeViewItem* item )
+ : KFileTreeBranch( view,
+ KURL( "media:/" + dev->blockDeviceName() ),
+ QString("%1 - %2").arg(dev->vendor()).arg(dev->description()),
+ ( dev->burner()
+ ? SmallIcon("cdwriter_unmount")
+ : SmallIcon("cdrom_unmount") ),
+ false,
+ item == 0
+ ? new K3bDeviceBranchViewItem( view, dev, this )
+ : item ),
+ m_device( dev ),
+ m_showBlockDeviceName( false )
+{
+ setAutoUpdate(true);
+ root()->setExpandable(false);
+ updateLabel();
+
+ connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3bDevice::Device*)),
+ this, SLOT(slotMediumChanged(K3bDevice::Device*)) );
+}
+
+
+bool K3bDeviceBranch::populate( const KURL& url, KFileTreeViewItem *currItem )
+{
+ // FIXME: we somehow need to "unpopulate" once the medium is unmounted
+
+ // make sure we do not try to populate in case we are not mounted
+ if( K3b::isMounted( m_device ) ) {
+ bool b = KFileTreeBranch::populate( url, currItem );
+ populateFinished( currItem );
+ return b;
+ }
+ else
+ populateFinished( currItem );
+
+ return true;
+}
+
+
+void K3bDeviceBranch::setCurrent( bool c )
+{
+ static_cast<K3bDeviceBranchViewItem*>( root() )->setCurrent( c );
+}
+
+
+void K3bDeviceBranch::updateLabel()
+{
+ if( m_showBlockDeviceName )
+ setName( QString("%1 %2 (%3)")
+ .arg(m_device->vendor())
+ .arg(m_device->description())
+ .arg(m_device->blockDeviceName()) );
+ else
+ setName( QString("%1 %2")
+ .arg(m_device->vendor())
+ .arg(m_device->description()) );
+
+ if( k3bappcore->mediaCache() ) {
+ root()->setMultiLinesEnabled( true );
+ root()->setText( 0, name() + "\n" + k3bappcore->mediaCache()->mediumString( m_device ) );
+ static_cast<K3bFileTreeView*>( root()->listView() )->updateMinimumWidth();
+ }
+ else {
+ root()->setMultiLinesEnabled( false );
+ root()->setText( 0, name() );
+ }
+}
+
+
+void K3bDeviceBranch::slotMediumChanged( K3bDevice::Device* dev )
+{
+ if( dev == m_device )
+ updateLabel();
+}
+
+
+void K3bDeviceBranch::showBlockDeviceName( bool b )
+{
+ m_showBlockDeviceName = b;
+ updateLabel();
+}
+
+
+K3bFileTreeBranch::K3bFileTreeBranch( KFileTreeView* view,
+ const KURL& url,
+ const QString& name,
+ const QPixmap& pix,
+ bool showHidden,
+ KFileTreeViewItem* item )
+ : KFileTreeBranch( view, url, name, pix, showHidden,
+ item == 0
+ ? new K3bFileTreeViewItem( view,
+ new KFileItem( url, "inode/directory",
+ S_IFDIR ),
+ this )
+ : item )
+{
+}
+
+
+
+K3bDeviceBranchViewItem::K3bDeviceBranchViewItem( KFileTreeViewItem* parent,
+ K3bDevice::Device* dev,
+ K3bDeviceBranch* branch )
+ : KFileTreeViewItem( parent,
+ new KFileItem( KURL( "media:/" + dev->blockDeviceName() ),
+ "inode/directory",
+ S_IFDIR ),
+ branch ),
+ m_bCurrent( false ),
+ m_device( dev )
+{
+}
+
+
+K3bDeviceBranchViewItem::K3bDeviceBranchViewItem( KFileTreeView* parent,
+ K3bDevice::Device* dev,
+ K3bDeviceBranch* branch )
+ : KFileTreeViewItem( parent,
+ new KFileItem( KURL( "media:/" + dev->blockDeviceName() ),
+ "inode/directory",
+ S_IFDIR ),
+ branch ),
+ m_bCurrent( false ),
+ m_device( dev )
+{
+}
+
+
+void K3bDeviceBranchViewItem::setCurrent( bool c )
+{
+ m_bCurrent = c;
+ repaint();
+}
+
+
+void K3bDeviceBranchViewItem::paintCell( QPainter* p, const QColorGroup& cg, int /* col */, int width, int align )
+{
+ p->save();
+
+ int xpos = 1;
+ int ypos = 1;
+ QFontMetrics fm( p->fontMetrics() );
+
+ if( isSelected() ) {
+ p->fillRect( 0, 0, width, height(),
+ cg.brush( QColorGroup::Highlight ) );
+ p->setPen( cg.highlightedText() );
+ }
+ else {
+ p->fillRect( 0, 0, width, height(), cg.base() );
+ p->setPen( cg.text() );
+ }
+
+ if( pixmap(0) ) {
+ p->drawPixmap( xpos, ypos, *pixmap(0) );
+ xpos += pixmap(0)->width() + 5;
+ }
+
+ if( m_bCurrent ) {
+ QFont f( listView()->font() );
+ f.setBold( true );
+ p->setFont( f );
+ }
+
+ ypos += fm.ascent();
+ QString line1 = text(0).left( text(0).find('\n') );
+ p->drawText( xpos, ypos, line1 );
+
+ QFont f( listView()->font() );
+ f.setItalic( true );
+ f.setBold( false );
+ f.setPointSize( f.pointSize() - 2 );
+ p->setFont( f );
+
+ ypos += p->fontMetrics().height() + 1;
+ QString line2 = text(0).mid( text(0).find('\n')+1 );
+ p->drawText( xpos - p->fontMetrics().leftBearing( line2[0] ), ypos, line2 );
+
+
+ // from QListViewItem
+ if( isOpen() && childCount() ) {
+ int textheight = fm.size( align, text(0) ).height() + 2 * listView()->itemMargin();
+ textheight = QMAX( textheight, QApplication::globalStrut().height() );
+ if ( textheight % 2 > 0 )
+ textheight++;
+ if ( textheight < height() ) {
+ int w = listView()->treeStepSize() / 2;
+ listView()->style().drawComplexControl( QStyle::CC_ListView, p, listView(),
+ QRect( 0, textheight, w + 1, height() - textheight + 1 ), cg,
+ QStyle::Style_Enabled,
+ QStyle::SC_ListViewExpand,
+ (uint)QStyle::SC_All, QStyleOption( this ) );
+ }
+ }
+
+ p->restore();
+}
+
+
+int K3bDeviceBranchViewItem::widthHint() const
+{
+ QFont f( listView()->font() );
+ if ( m_bCurrent ) {
+ f.setBold( true );
+ }
+ int w = QFontMetrics(f).width( text(0).left( text(0).find('\n') ) );
+
+ f.setItalic( true );
+ f.setBold( false );
+ f.setPointSize( f.pointSize() - 2 );
+ w = QMAX( w, QFontMetrics(f).width( text(0).mid( text(0).find('\n')+1 ) ) );
+
+ w++; // see paintCell
+
+ if( pixmap(0) )
+ w += pixmap(0)->width() + 5;
+
+ return w;
+}
+
+
+QString K3bDeviceBranchViewItem::key( int column, bool ascending ) const
+{
+ return "0" + KFileTreeViewItem::key( column, ascending );
+}
+
+
+
+K3bFileTreeViewItem::K3bFileTreeViewItem( KFileTreeViewItem* parent, KFileItem* item, KFileTreeBranch* branch )
+ : KFileTreeViewItem( parent, item, branch )
+{
+}
+
+
+K3bFileTreeViewItem::K3bFileTreeViewItem( KFileTreeView* parent, KFileItem* item, KFileTreeBranch* branch )
+ : KFileTreeViewItem( parent, item, branch )
+{
+}
+
+
+QString K3bFileTreeViewItem::key( int column, bool ascending ) const
+{
+ return "1" + KFileTreeViewItem::key( column, ascending );
+}
+
+
+class K3bDeviceTreeToolTip : public K3bToolTip
+{
+public:
+ K3bDeviceTreeToolTip( QWidget* parent, K3bFileTreeView* lv );
+
+ void maybeTip( const QPoint &pos );
+
+private:
+ K3bFileTreeView* m_view;
+};
+
+
+K3bDeviceTreeToolTip::K3bDeviceTreeToolTip( QWidget* parent, K3bFileTreeView* lv )
+ : K3bToolTip( parent ),
+ m_view( lv )
+{
+ setTipTimeout( 500 );
+}
+
+
+void K3bDeviceTreeToolTip::maybeTip( const QPoint& pos )
+{
+ if( !parentWidget() || !m_view )
+ return;
+
+ K3bDeviceBranchViewItem* item = dynamic_cast<K3bDeviceBranchViewItem*>( m_view->itemAt( pos ) );
+ if( !item )
+ return;
+
+ K3bDevice::Device* dev = static_cast<K3bDeviceBranch*>( item->branch() )->device();
+
+ QFrame* tooltip = new QFrame( parentWidget() );
+ tooltip->setFrameStyle( QFrame::Panel | QFrame::Raised );
+ tooltip->setFrameShape( QFrame::StyledPanel );
+ QGridLayout* lay = new QGridLayout( tooltip, 2, 2, tooltip->frameWidth()*2 /*margin*/, 6 /*spacing*/ );
+
+ QString text = k3bappcore->mediaCache()->medium( dev ).longString();
+ int detailsStart = text.find( "<p>", 3 );
+ QString details = text.mid( detailsStart );
+ text.truncate( detailsStart );
+
+ QLabel* label = new QLabel( text, tooltip );
+ label->setMargin( 9 );
+ lay->addMultiCellWidget( label, 0, 0, 0, 1 );
+ label = new QLabel( details, tooltip );
+ label->setMargin( 9 );
+ label->setAlignment( Qt::Vertical );
+ lay->addMultiCellWidget( label, 1, 2, 0, 0 );
+ label = new QLabel( tooltip );
+ lay->addWidget( label, 2, 1 );
+ lay->setColStretch( 0, 1 );
+
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ tooltip->setPaletteBackgroundColor( theme->backgroundColor() );
+ tooltip->setPaletteForegroundColor( theme->foregroundColor() );
+ K3bTheme::PixmapType pm;
+ int c = k3bappcore->mediaCache()->medium( dev ).content();
+ if( c & (K3bMedium::CONTENT_VIDEO_CD|K3bMedium::CONTENT_VIDEO_DVD) )
+ pm = K3bTheme::MEDIA_VIDEO;
+ else if( c & K3bMedium::CONTENT_AUDIO &&
+ c & K3bMedium::CONTENT_DATA )
+ pm = K3bTheme::MEDIA_MIXED;
+ else if( c & K3bMedium::CONTENT_AUDIO )
+ pm = K3bTheme::MEDIA_AUDIO;
+ else if( c & K3bMedium::CONTENT_DATA )
+ pm = K3bTheme::MEDIA_DATA;
+ else {
+ K3bDevice::DiskInfo di = k3bappcore->mediaCache()->diskInfo( dev );
+ if( di.diskState() == K3bDevice::STATE_EMPTY )
+ pm = K3bTheme::MEDIA_EMPTY;
+ else
+ pm = K3bTheme::MEDIA_NONE;
+ }
+ label->setPixmap( theme->pixmap( pm ) );
+ }
+
+ // the tooltip will take care of deleting the widget
+ tip( m_view->itemRect( item ), tooltip );
+}
+
+
+
+class K3bFileTreeView::Private
+{
+public:
+ Private()
+ : deviceManager(0),
+ currentDeviceBranch(0) {
+ }
+
+ QPtrDict<K3bDeviceBranch> deviceBranchDict;
+ QMap<KFileTreeBranch*, K3bDevice::Device*> branchDeviceMap;
+
+ K3bDevice::DeviceManager* deviceManager;
+ K3bDeviceBranch* currentDeviceBranch;
+
+ K3bDeviceTreeToolTip* toolTip;
+};
+
+K3bFileTreeView::K3bFileTreeView( QWidget *parent, const char *name )
+ : KFileTreeView( parent, name )
+{
+ d = new Private();
+
+ d->toolTip = new K3bDeviceTreeToolTip( viewport(), this );
+
+ addColumn( i18n("Directories") );
+ setDragEnabled( true );
+ setAlternateBackground( QColor() );
+ setFullWidth(true);
+ // setRootIsDecorated(true);
+ setSorting(0);
+
+ m_dirOnlyMode = true;
+ m_menuEnabled = false;
+
+ connect( this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotItemExecuted(QListViewItem*)) );
+ connect( this, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(slotItemExecuted(QListViewItem*)) );
+ connect( this, SIGNAL(contextMenu(KListView*, QListViewItem* , const QPoint& )),
+ this, SLOT(slotContextMenu(KListView*, QListViewItem* , const QPoint& )) );
+
+ // we always simulate the single click
+ slotSettingsChangedK3b(KApplication::SETTINGS_MOUSE);
+ if( kapp )
+ connect( kapp, SIGNAL(settingsChanged(int)), SLOT(slotSettingsChangedK3b(int)) );
+
+ initActions();
+}
+
+
+K3bFileTreeView::~K3bFileTreeView()
+{
+ delete d;
+}
+
+
+void K3bFileTreeView::clear()
+{
+ KFileTreeView::clear();
+ if( d->deviceManager )
+ d->deviceManager->disconnect( this );
+ d->deviceManager = 0;
+}
+
+
+void K3bFileTreeView::initActions()
+{
+// m_actionCollection = new KActionCollection( this );
+
+// m_devicePopupMenu = new KActionMenu( m_actionCollection, "device_popup_menu" );
+// m_urlPopupMenu = new KActionMenu( m_actionCollection, "url_popup_menu" );
+
+// KAction* actionDiskInfo = new KAction( i18n("&Disk Info"), "info", 0, this, SLOT(slotShowDiskInfo()),
+// m_actionCollection, "disk_info");
+// KAction* actionUnmount = new KAction( i18n("&Unmount"), "cdrom_unmount", 0, this, SLOT(slotUnmountDisk()),
+// m_actionCollection, "disk_unmount");
+// KAction* actionEject = new KAction( i18n("&Eject"), "", 0, this, SLOT(slotEjectDisk()),
+// m_actionCollection, "disk_eject");
+
+// m_devicePopupMenu->insert( actionDiskInfo );
+// m_devicePopupMenu->insert( new KActionSeparator( this ) );
+// m_devicePopupMenu->insert( actionUnmount );
+// m_devicePopupMenu->insert( actionEject );
+
+}
+
+
+void K3bFileTreeView::addDefaultBranches()
+{
+ KURL home = KURL::fromPathOrURL( QDir::homeDirPath() );
+ KURL root = KURL( "file:/" );
+
+ KFileTreeBranch* treeBranch = addBranch( new K3bFileTreeBranch( this, root, i18n("Root"), SmallIcon("folder_red") ) );
+ treeBranch = addBranch( new K3bFileTreeBranch( this, home, i18n("Home"), SmallIcon("folder_home") ) );
+ treeBranch->setOpen( true );
+}
+
+
+void K3bFileTreeView::addCdDeviceBranches( K3bDevice::DeviceManager* dm )
+{
+ kdDebug() << "(K3bFileTreeView::addCdDeviceBranches)" << endl;
+
+ // remove all previous added device branches
+ for( QMap<KFileTreeBranch*, K3bDevice::Device*>::Iterator it = d->branchDeviceMap.begin();
+ it != d->branchDeviceMap.end(); ++it ) {
+ removeBranch( it.key() );
+ }
+
+ // clear the maps
+ d->branchDeviceMap.clear();
+ d->deviceBranchDict.clear();
+
+ for( QPtrListIterator<K3bDevice::Device> it( dm->allDevices() ); *it; ++it )
+ addDeviceBranch( *it );
+
+ if( dm != d->deviceManager ) {
+ if( d->deviceManager )
+ d->deviceManager->disconnect( this );
+ d->deviceManager = dm;
+
+ // make sure we get changes to the config
+ connect( dm, SIGNAL(changed(K3bDevice::DeviceManager*)),
+ this, SLOT(addCdDeviceBranches(K3bDevice::DeviceManager*)) );
+
+ if( K3bAppDeviceManager* appDevM = dynamic_cast<K3bAppDeviceManager*>( dm ) )
+ connect( appDevM, SIGNAL(currentDeviceChanged(K3bDevice::Device*)),
+ this, SLOT(setCurrentDevice(K3bDevice::Device*)) );
+ }
+
+ K3bDevice::Device* currentDevice = k3bappcore->appDeviceManager()->currentDevice();
+ if ( !currentDevice && !k3bappcore->appDeviceManager()->allDevices().isEmpty() ) {
+ k3bappcore->appDeviceManager()->setCurrentDevice( k3bappcore->appDeviceManager()->allDevices().getFirst() );
+ }
+
+ d->currentDeviceBranch = d->deviceBranchDict[currentDevice];
+ if( d->currentDeviceBranch ) {
+ d->currentDeviceBranch->setCurrent( true );
+ }
+
+ kdDebug() << "(K3bFileTreeView::addCdDeviceBranches) done" << endl;
+}
+
+
+void K3bFileTreeView::addDeviceBranch( K3bDevice::Device* dev )
+{
+ K3bDeviceBranch* newBranch = new K3bDeviceBranch( this, dev );
+ addBranch( newBranch );
+
+ // search for an equal device
+ int equalCnt = 0;
+ K3bDeviceBranch* equalBranch = 0;
+ for( QMap<KFileTreeBranch*, K3bDevice::Device*>::Iterator it = d->branchDeviceMap.begin();
+ it != d->branchDeviceMap.end(); ++it ) {
+ K3bDevice::Device* itDev = it.data();
+ K3bDeviceBranch* itBranch = (K3bDeviceBranch*)it.key();
+ if( itDev->vendor() == dev->vendor() &&
+ itDev->description() == dev->description() ) {
+ ++equalCnt;
+ equalBranch = itBranch;
+ }
+ }
+
+ // if there is at least one equal device add the block device name
+ // if there is more than one equal device they have been updated after
+ // adding the last one so there is no need to update more than two
+ if( equalCnt > 0 ) {
+ kdDebug() << "(K3bFileTreeView) equal branch" << endl;
+ newBranch->showBlockDeviceName(true);
+ equalBranch->showBlockDeviceName(true);
+ }
+
+ // add to maps
+ d->branchDeviceMap.insert( newBranch, dev );
+ d->deviceBranchDict.insert( (void*)dev, newBranch );
+
+ updateMinimumWidth();
+}
+
+
+KFileTreeBranch* K3bFileTreeView::addBranch( KFileTreeBranch* branch )
+{
+ KFileTreeBranch* newBranch = KFileTreeView::addBranch( branch );
+ newBranch->setChildRecurse( false );
+ setDirOnlyMode( newBranch, m_dirOnlyMode );
+
+ return newBranch;
+}
+
+
+KFileTreeBranch* K3bFileTreeView::addBranch( const KURL& url, const QString& name, const QPixmap& pix, bool showHidden )
+{
+ KFileTreeBranch* newBranch = KFileTreeView::addBranch( url, name, pix, showHidden );
+ newBranch->setChildRecurse( false );
+ setDirOnlyMode( newBranch, m_dirOnlyMode );
+
+ return newBranch;
+}
+
+
+void K3bFileTreeView::slotItemExecuted( QListViewItem* item )
+{
+ KFileTreeViewItem* treeItem = static_cast<KFileTreeViewItem*>(item);
+ if( d->branchDeviceMap.contains( treeItem->branch() ) &&
+ treeItem == treeItem->branch()->root() ) {
+ K3bDevice::Device* dev = d->branchDeviceMap[treeItem->branch()];
+ k3bappcore->appDeviceManager()->setCurrentDevice( dev );
+ emit deviceExecuted( dev );
+ }
+ else
+ emit urlExecuted( treeItem->url() );
+}
+
+
+void K3bFileTreeView::setTreeDirOnlyMode( bool b )
+{
+ m_dirOnlyMode = b;
+}
+
+
+void K3bFileTreeView::followUrl( const KURL& url )
+{
+ // TODO: first try the current branch
+ KFileTreeBranchIterator it( branches() );
+ for( ; *it; ++it ) {
+ if( !d->branchDeviceMap.contains( *it ) )
+ if( KFileTreeViewItem* item = (*it)->findTVIByURL( url ) ) {
+ setCurrentItem( item );
+ setSelected(item, true);
+ ensureItemVisible( item );
+ return;
+ }
+ }
+}
+
+
+void K3bFileTreeView::slotContextMenu( KListView*, QListViewItem* item, const QPoint& p )
+{
+ KFileTreeViewItem* treeItem = dynamic_cast<KFileTreeViewItem*>(item);
+ if( treeItem ) {
+ K3bDevice::Device* device = 0;
+ QMap<KFileTreeBranch*, K3bDevice::Device*>::iterator devIt =
+ d->branchDeviceMap.find( treeItem->branch() );
+ if( devIt != d->branchDeviceMap.end() )
+ device = devIt.data();
+
+ setCurrentItem( treeItem );
+ setSelected( treeItem, true);
+
+ if( device ) {
+ k3bappcore->appDeviceManager()->setCurrentDevice( device );
+ emit contextMenu( device, p );
+ }
+ else
+ emit contextMenu( treeItem->url(), p );
+ }
+ else
+ kdWarning() << "(K3bFileTreeView) found viewItem that is no KFileTreeViewItem!" << endl;
+}
+
+
+K3bDevice::Device* K3bFileTreeView::selectedDevice() const
+{
+ KFileTreeViewItem* treeItem = dynamic_cast<KFileTreeViewItem*>(selectedItem());
+ if( treeItem ) {
+ if( d->branchDeviceMap.contains( treeItem->branch() ) )
+ return d->branchDeviceMap[treeItem->branch()];
+ }
+ return 0;
+}
+
+
+KURL K3bFileTreeView::selectedUrl() const
+{
+ KFileTreeViewItem* treeItem = dynamic_cast<KFileTreeViewItem*>(selectedItem());
+ if( treeItem ) {
+ if( !d->branchDeviceMap.contains( treeItem->branch() ) )
+ return treeItem->url();
+ }
+ return KURL();
+}
+
+
+void K3bFileTreeView::setCurrentDevice( K3bDevice::Device* dev )
+{
+ if( d->currentDeviceBranch )
+ d->currentDeviceBranch->setCurrent( false );
+
+ if( dev ) {
+ if ( ( d->currentDeviceBranch = branch( dev ) ) )
+ d->currentDeviceBranch->setCurrent( true );
+ }
+
+ updateMinimumWidth();
+}
+
+
+void K3bFileTreeView::setSelectedDevice( K3bDevice::Device* dev )
+{
+ setCurrentDevice( dev );
+ K3bDeviceBranch* b = branch( dev );
+ setCurrentItem( b->root() );
+ setSelected( b->root(), true );
+}
+
+
+K3bDeviceBranch* K3bFileTreeView::branch( K3bDevice::Device* dev )
+{
+ return d->deviceBranchDict.find( (void*)dev );
+}
+
+
+void K3bFileTreeView::slotSettingsChangedK3b(int category)
+{
+ // we force single click like konqueror does. This really should be done in KFileTreeView
+
+ if( category == KApplication::SETTINGS_MOUSE ) {
+ disconnect(this, SIGNAL(mouseButtonClicked(int, QListViewItem*, const QPoint &, int)),
+ this, SLOT(slotMouseButtonClickedK3b(int, QListViewItem*, const QPoint &, int)));
+
+ if( !KGlobalSettings::singleClick() )
+ connect(this, SIGNAL(mouseButtonClicked(int, QListViewItem*, const QPoint &, int)),
+ this, SLOT(slotMouseButtonClickedK3b(int, QListViewItem*, const QPoint &, int)));
+ }
+}
+
+
+void K3bFileTreeView::slotMouseButtonClickedK3b( int btn, QListViewItem *item, const QPoint &pos, int c )
+{
+ if( (btn == LeftButton) && item )
+ emitExecute(item, pos, c);
+}
+
+
+void K3bFileTreeView::updateMinimumWidth()
+{
+ //
+ // only handle the device branches, we don't care about the folders.
+ //
+ int w = 0;
+ for( QMap<KFileTreeBranch*, K3bDevice::Device*>::Iterator it = d->branchDeviceMap.begin();
+ it != d->branchDeviceMap.end(); ++it ) {
+ w = QMAX( w, static_cast<K3bDeviceBranchViewItem*>( it.key()->root() )->widthHint() );
+ }
+
+ // width of the items + scrollbar width + the frame + a little eyecandy spacing
+ setMinimumWidth( w + verticalScrollBar()->sizeHint().width() + 2*frameWidth() + 2 );
+}
+
+#include "k3bfiletreeview.moc"
diff --git a/src/k3bfiletreeview.h b/src/k3bfiletreeview.h
new file mode 100644
index 0000000..31a25c4
--- /dev/null
+++ b/src/k3bfiletreeview.h
@@ -0,0 +1,199 @@
+/*
+ *
+ * $Id: k3bfiletreeview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BFILETREEVIEW_H
+#define K3BFILETREEVIEW_H
+
+
+#include <kfiletreeview.h>
+
+class KFileTreeBranch;
+class KActionCollection;
+class KActionMenu;
+class QPoint;
+class QDropEvent;
+class QDragEnterEvent;
+
+namespace K3bDevice {
+ class Device;
+ class DeviceManager;
+}
+
+namespace KIO {
+ class Job;
+}
+
+
+class K3bDeviceBranch : public KFileTreeBranch
+{
+ Q_OBJECT
+
+ public:
+ K3bDeviceBranch( KFileTreeView*, K3bDevice::Device* dev, KFileTreeViewItem* item = 0 );
+
+ K3bDevice::Device* device() const { return m_device; }
+
+ /**
+ * Adds or removes the blockdevicename from the branch name
+ */
+ void showBlockDeviceName( bool b );
+
+ public slots:
+ void setCurrent( bool );
+
+ bool populate( const KURL& url, KFileTreeViewItem *currItem );
+
+ private slots:
+ void slotMediumChanged( K3bDevice::Device* );
+
+ private:
+ void updateLabel();
+
+ K3bDevice::Device* m_device;
+ bool m_showBlockDeviceName;
+};
+
+
+class K3bFileTreeBranch : public KFileTreeBranch
+{
+ public:
+ K3bFileTreeBranch( KFileTreeView*,
+ const KURL& url,
+ const QString& name,
+ const QPixmap& pix,
+ bool showHidden = false,
+ KFileTreeViewItem* item = 0 );
+};
+
+
+class K3bDeviceBranchViewItem : public KFileTreeViewItem
+{
+ public:
+ K3bDeviceBranchViewItem( KFileTreeViewItem*, K3bDevice::Device*, K3bDeviceBranch* );
+ K3bDeviceBranchViewItem( KFileTreeView*, K3bDevice::Device*, K3bDeviceBranch* );
+
+ QString key( int column, bool ascending ) const;
+
+ void setCurrent( bool );
+
+ void paintCell( QPainter* p, const QColorGroup& cg, int col, int width, int align );
+
+ int widthHint() const;
+
+ private:
+ bool m_bCurrent;
+
+ K3bDevice::Device* m_device;
+};
+
+
+class K3bFileTreeViewItem : public KFileTreeViewItem
+{
+ public:
+ K3bFileTreeViewItem( KFileTreeViewItem*, KFileItem*, KFileTreeBranch* );
+ K3bFileTreeViewItem( KFileTreeView *, KFileItem*, KFileTreeBranch* );
+
+ QString key( int column, bool ascending ) const;
+};
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bFileTreeView : public KFileTreeView
+{
+ Q_OBJECT
+
+ public:
+ K3bFileTreeView( QWidget *parent = 0, const char *name = 0 );
+ ~K3bFileTreeView();
+
+
+ virtual KFileTreeBranch* addBranch( KFileTreeBranch* );
+ virtual KFileTreeBranch* addBranch( const KURL& url, const QString& name, const QPixmap& , bool showHidden = false );
+
+ K3bDeviceBranch* branch( K3bDevice::Device* dev );
+
+ /**
+ * returns 0 if no device is selected
+ */
+ K3bDevice::Device* selectedDevice() const;
+
+ /**
+ * returnes an empty url if no url is selected
+ */
+ KURL selectedUrl() const;
+
+ public slots:
+ /**
+ * adds home and root dir branch
+ */
+ void addDefaultBranches();
+ void addCdDeviceBranches( K3bDevice::DeviceManager* );
+ void addDeviceBranch( K3bDevice::Device* dev );
+
+ /**
+ * Make dev the current device. This does not mean that the device entry
+ * will be highlighted but marked otherwise since this means that it is the
+ * current device in the application and not the treeview.
+ */
+ void setCurrentDevice( K3bDevice::Device* dev );
+
+ /**
+ * his will highlight the device and also make it the current device.
+ */
+ void setSelectedDevice( K3bDevice::Device* dev );
+
+ void followUrl( const KURL& url );
+ void setTreeDirOnlyMode( bool b );
+ void enablePopupMenu( bool b ) { m_menuEnabled = b; }
+
+ /**
+ * @reimplemented
+ */
+ virtual void clear();
+
+ void updateMinimumWidth();
+
+ signals:
+ void urlExecuted( const KURL& url );
+ void deviceExecuted( K3bDevice::Device* dev );
+
+ /** only gets emitted if the menu is disabled */
+ void contextMenu( K3bDevice::Device*, const QPoint& );
+ /** only gets emitted if the menu is disabled */
+ void contextMenu( const KURL& url, const QPoint& );
+
+ private slots:
+ void slotItemExecuted( QListViewItem* item );
+ void slotContextMenu( KListView*, QListViewItem*, const QPoint& );
+ void slotSettingsChangedK3b(int category);
+ void slotMouseButtonClickedK3b( int btn, QListViewItem *item, const QPoint &pos, int c );
+
+ private:
+ void initActions();
+
+ class Private;
+ Private* d;
+
+ bool m_dirOnlyMode;
+ KActionCollection* m_actionCollection;
+ KActionMenu* m_devicePopupMenu;
+ KActionMenu* m_urlPopupMenu;
+ bool m_menuEnabled;
+};
+
+#endif
diff --git a/src/k3bfileview.cpp b/src/k3bfileview.cpp
new file mode 100644
index 0000000..04ce435
--- /dev/null
+++ b/src/k3bfileview.cpp
@@ -0,0 +1,183 @@
+/*
+ *
+ * $Id: k3bfileview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bfileview.h"
+#include "k3b.h"
+#include "k3bdiroperator.h"
+#include "k3btoolbox.h"
+#include "k3bapplication.h"
+
+#include <qwidget.h>
+#include <qdragobject.h>
+#include <qlayout.h>
+#include <qdir.h>
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+
+#include <kfiledetailview.h>
+#include <klistview.h>
+#include <kaction.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+#include <kurl.h>
+#include <kurldrag.h>
+#include <kfilefiltercombo.h>
+#include <klocale.h>
+#include <kfileitem.h>
+#include <kmessagebox.h>
+#include <kdirlister.h>
+#include <kprogress.h>
+
+
+K3bFileView::K3bFileView(QWidget *parent, const char *name )
+ : K3bContentsView( false, parent, name)
+{
+ setupGUI();
+}
+
+
+K3bFileView::~K3bFileView()
+{
+}
+
+
+KActionCollection* K3bFileView::actionCollection() const
+{
+ return m_dirOp->actionCollection();
+}
+
+
+void K3bFileView::setupGUI()
+{
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ // layout->setAutoAdd( true );
+
+ m_dirOp = new K3bDirOperator( KURL::fromPathOrURL(QDir::home().absPath()), this );
+ m_toolBox = new K3bToolBox( this );
+
+ layout->addWidget( m_toolBox );
+ layout->addWidget( m_dirOp );
+ layout->setStretchFactor( m_dirOp, 1 );
+
+ // setup actions
+ KAction* actionHome = m_dirOp->actionCollection()->action("home");
+ KAction* actionBack = m_dirOp->actionCollection()->action("back");
+ KAction* actionUp = m_dirOp->actionCollection()->action("up");
+ KAction* actionReload = m_dirOp->actionCollection()->action("reload");
+
+ m_toolBox->addButton( actionUp );
+ m_toolBox->addButton( actionBack );
+ m_toolBox->addButton( actionHome );
+ m_toolBox->addButton( actionReload );
+ m_toolBox->addSpacing();
+ m_toolBox->addButton( m_dirOp->actionCollection()->action("short view") );
+ m_toolBox->addButton( m_dirOp->actionCollection()->action("detailed view") );
+ m_toolBox->addSpacing();
+ m_toolBox->addButton( m_dirOp->bookmarkMenu() );
+ m_toolBox->addSpacing();
+
+ // create filter selection combobox
+ m_toolBox->addSpacing();
+ m_toolBox->addLabel( i18n("Filter:") );
+ m_toolBox->addSpacing();
+ m_filterWidget = new KFileFilterCombo( m_toolBox, "filterwidget" );
+ m_toolBox->addWidget( m_filterWidget );
+ m_toolBox->addStretch();
+ m_toolBox->addWidget( m_dirOp->progressBar() );
+
+ m_filterWidget->setEditable( true );
+ QString filter = i18n("*|All Files");
+ filter += "\n" + i18n("audio/x-mp3 audio/x-wav application/x-ogg |Sound Files");
+ filter += "\n" + i18n("audio/x-wav |Wave Sound Files");
+ filter += "\n" + i18n("audio/x-mp3 |MP3 Sound Files");
+ filter += "\n" + i18n("application/x-ogg |Ogg Vorbis Sound Files");
+ filter += "\n" + i18n("video/mpeg |MPEG Video Files");
+ m_filterWidget->setFilter(filter);
+
+ connect( m_filterWidget, SIGNAL(filterChanged()), SLOT(slotFilterChanged()) );
+
+ connect( m_dirOp, SIGNAL(fileHighlighted(const KFileItem*)), this, SLOT(slotFileHighlighted(const KFileItem*)) );
+ connect( m_dirOp, SIGNAL(urlEntered(const KURL&)), this, SIGNAL(urlEntered(const KURL&)) );
+ connect( m_dirOp, SIGNAL(fileSelected(const KFileItem*)), m_dirOp, SLOT(slotAddFilesToProject()) );
+
+ slotFileHighlighted(0);
+}
+
+void K3bFileView::setDir( const QString& dir )
+{
+ KURL url;
+ url.setPath(dir);
+ setUrl( url );
+}
+
+
+void K3bFileView::setUrl(const KURL& url, bool forward)
+{
+ m_dirOp->setURL( url, forward );
+}
+
+KURL K3bFileView::url()
+{
+ return m_dirOp->url();
+}
+
+void K3bFileView::setAutoUpdate( bool b )
+{
+ m_dirOp->dirLister()->setAutoUpdate( b );
+}
+
+void K3bFileView::slotFileHighlighted( const KFileItem* )
+{
+}
+
+
+void K3bFileView::slotFilterChanged()
+{
+ QString filter = m_filterWidget->currentFilter();
+ m_dirOp->clearFilter();
+
+ if( filter.find( '/' ) > -1 ) {
+ QStringList types = QStringList::split( " ", filter );
+ types.prepend( "inode/directory" );
+ m_dirOp->setMimeFilter( types );
+ }
+ else
+ m_dirOp->setNameFilter( filter );
+
+ m_dirOp->rereadDir();
+ // emit filterChanged( filter );
+}
+
+
+void K3bFileView::reload()
+{
+ m_dirOp->actionCollection()->action("reload")->activate();
+}
+
+
+void K3bFileView::saveConfig( KConfig* c )
+{
+ m_dirOp->writeConfig( c, "file view" );
+}
+
+
+void K3bFileView::readConfig( KConfig* c )
+{
+ m_dirOp->readConfig( c, "file view" );
+}
+
+#include "k3bfileview.moc"
diff --git a/src/k3bfileview.h b/src/k3bfileview.h
new file mode 100644
index 0000000..f89d3b8
--- /dev/null
+++ b/src/k3bfileview.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * $Id: k3bfileview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BFILEVIEW_H
+#define K3BFILEVIEW_H
+
+
+#include "k3bcontentsview.h"
+
+
+class K3bDirOperator;
+class QDragObject;
+class KURL;
+class KFileFilterCombo;
+class KFileItem;
+class KActionCollection;
+class KConfig;
+class K3bToolBox;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bFileView : public K3bContentsView
+{
+ Q_OBJECT
+
+ public:
+ K3bFileView(QWidget *parent=0, const char *name=0);
+ ~K3bFileView();
+
+ void setUrl( const KURL &url, bool forward = true );
+ KURL url();
+
+ KActionCollection* actionCollection() const;
+
+ void reload();
+
+ signals:
+ void urlEntered( const KURL& url );
+
+ public slots:
+ void setDir( const QString& );
+ void saveConfig( KConfig* c );
+ void readConfig( KConfig* c );
+ void setAutoUpdate( bool );
+
+ private:
+ K3bToolBox* m_toolBox;
+ K3bDirOperator* m_dirOp;
+ KFileFilterCombo* m_filterWidget;
+
+ void setupGUI();
+
+ private slots:
+ void slotFilterChanged();
+ void slotFileHighlighted( const KFileItem* item );
+};
+
+
+#endif
diff --git a/src/k3bfirstrun.cpp b/src/k3bfirstrun.cpp
new file mode 100644
index 0000000..23a285a
--- /dev/null
+++ b/src/k3bfirstrun.cpp
@@ -0,0 +1,84 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bfirstrun.h"
+#include "k3b.h"
+#include "k3bservicemenuinstaller.h"
+#include <k3bcore.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kconfig.h>
+
+#include <qlayout.h>
+#include <qlabel.h>
+
+
+void K3bFirstRun::run( QWidget* parent )
+{
+ if( !k3bcore->config()->readBoolEntry( "First run", true ) )
+ return;
+
+ k3bcore->config()->writeEntry( "First run", false );
+
+ // for now the first run dialog only asks for
+ // the konqui integration. So in case it is
+ // already installed there is no need to show the
+ // dialog.
+ K3bServiceInstaller si;
+ if( si.allInstalled() )
+ return;
+
+ K3bFirstRun dlg( parent );
+ if( dlg.exec() == QDialog::Accepted )
+ si.install( parent );
+}
+
+
+K3bFirstRun::K3bFirstRun( QWidget* parent )
+ : KDialogBase( Plain,
+ i18n("First Run"),
+ Ok|Cancel,
+ Ok,
+ parent,
+ 0,
+ true,
+ true )
+{
+ setButtonOK( i18n("Enable Konqueror integration") );
+ setButtonCancel( i18n("No Konqueror integration") );
+
+ QFrame* plain = plainPage();
+ QLabel* label = new QLabel( i18n("<p>K3b can integrate itself into Konqueror. This integration "
+ "allows to start K3b from the context menu in the file manager."
+ "<p><em>The Konqueror integration can always be disabled and "
+ "enabled again from the K3b settings.</em>"), plain );
+ QLabel* pixLabel = new QLabel( plain );
+ pixLabel->setPixmap( DesktopIcon( "konqueror" ) );
+
+ QHBoxLayout* lay = new QHBoxLayout( plain );
+ lay->setMargin( 0 );
+ lay->setSpacing( spacingHint() );
+ lay->addWidget( pixLabel );
+ lay->addWidget( label );
+ lay->setStretchFactor( label, 1 );
+}
+
+
+K3bFirstRun::~K3bFirstRun()
+{
+}
+
+#include "k3bfirstrun.moc"
diff --git a/src/k3bfirstrun.h b/src/k3bfirstrun.h
new file mode 100644
index 0000000..d59c931
--- /dev/null
+++ b/src/k3bfirstrun.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_FIRST_RUN_H_
+#define _K3B_FIRST_RUN_H_
+
+#include <kdialogbase.h>
+
+
+class K3bFirstRun : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ static void run( QWidget* parent = 0 );
+
+ private:
+ K3bFirstRun( QWidget* parent );
+ ~K3bFirstRun();
+};
+
+#endif
diff --git a/src/k3bflatbutton.cpp b/src/k3bflatbutton.cpp
new file mode 100644
index 0000000..808de32
--- /dev/null
+++ b/src/k3bflatbutton.cpp
@@ -0,0 +1,203 @@
+/*
+ *
+ * $Id: k3bflatbutton.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bflatbutton.h"
+#include "k3bthememanager.h"
+#include "k3bapplication.h"
+
+#include <kaction.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qfontmetrics.h>
+#include <qpixmap.h>
+
+
+K3bFlatButton::K3bFlatButton( QWidget *parent, const char *name )
+ : QFrame( parent, name/*, WNoAutoErase*/ ),
+ m_pressed(false)
+{
+ init();
+}
+
+
+K3bFlatButton::K3bFlatButton( const QString& text, QWidget *parent, const char *name )
+ : QFrame( parent, name/*, WNoAutoErase*/ ),
+ m_pressed(false)
+{
+ init();
+ setText( text );
+}
+
+
+K3bFlatButton::K3bFlatButton( KAction* a, QWidget *parent, const char *name )
+ : QFrame( parent, name/*, WNoAutoErase*/ ),
+ m_pressed(false)
+{
+ init();
+
+ setText( a->text() );
+ QToolTip::add( this, a->toolTip() );
+ setPixmap( KGlobal::iconLoader()->loadIcon( a->icon(), KIcon::NoGroup, 32 ) );
+ connect( this, SIGNAL(clicked()), a, SLOT(activate()) );
+}
+
+
+K3bFlatButton::~K3bFlatButton() {}
+
+
+void K3bFlatButton::init()
+{
+ setHover(false);
+ setMargin(5);
+ setFrameStyle( QFrame::Box|QFrame::Plain );
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()), this, SLOT(slotThemeChanged()) );
+ connect( kapp, SIGNAL(appearanceChanged()), this, SLOT(slotThemeChanged()) );
+ slotThemeChanged();
+}
+
+
+void K3bFlatButton::setText( const QString& s )
+{
+ m_text = s;
+ m_text.remove( '&' );
+
+ update();
+}
+
+
+void K3bFlatButton::setPixmap( const QPixmap& p )
+{
+ m_pixmap = p;
+ update();
+}
+
+
+void K3bFlatButton::enterEvent( QEvent* )
+{
+ setHover(true);
+}
+
+
+void K3bFlatButton::leaveEvent( QEvent* )
+{
+ setHover(false);
+}
+
+
+void K3bFlatButton::mousePressEvent( QMouseEvent* e )
+{
+ if( e->button() == QMouseEvent::LeftButton ) {
+ emit pressed();
+ m_pressed = true;
+ }
+ else
+ e->ignore();
+}
+
+
+void K3bFlatButton::mouseReleaseEvent( QMouseEvent* e )
+{
+ if( e->button() == QMouseEvent::LeftButton ) {
+ if( m_pressed )
+ emit clicked();
+ m_pressed = false;
+ }
+ else
+ e->ignore();
+}
+
+
+void K3bFlatButton::setHover( bool b )
+{
+ if( b ) {
+ setPaletteBackgroundColor( m_foreColor );
+ setPaletteForegroundColor( m_backColor );
+ } else {
+ setPaletteBackgroundColor( m_backColor );
+ setPaletteForegroundColor( m_foreColor );
+ }
+
+ m_hover = b;
+
+ update();
+}
+
+
+QSize K3bFlatButton::sizeHint() const
+{
+ // height: pixmap + 5 spacing + font height + frame width
+ // width: max( pixmap, text) + frame width
+ return QSize( QMAX( m_pixmap.width(), fontMetrics().width( m_text ) ) + frameWidth()*2,
+ m_pixmap.height() + fontMetrics().height() + 5 + frameWidth()*2 );
+}
+
+
+void K3bFlatButton::drawContents( QPainter* p )
+{
+ QRect rect = contentsRect();
+
+// if( m_hover )
+// p->fillRect( rect, m_foreColor );
+// else if( parentWidget() ) {
+// QRect r( mapToParent( QPoint(lineWidth(), lineWidth()) ),
+// mapToParent( QPoint(width()-2*lineWidth(), height()-2*lineWidth() )) );
+
+// parentWidget()->repaint( r );
+// }
+
+ p->save();
+
+ QRect textRect = fontMetrics().boundingRect( m_text );
+ int textX = QMAX( 0, ( rect.width() - textRect.width() ) / 2 );
+ int textY = textRect.height();
+
+ if( !m_pixmap.isNull() ) {
+ p->translate( rect.left(), rect.top() );
+ textX = QMAX( textX, (m_pixmap.width() - textRect.width()) / 2 );
+ textY += 5 + m_pixmap.height();
+
+ int pixX = QMAX( QMAX( 0, (textRect.width() - m_pixmap.width()) / 2 ),
+ ( rect.width() - m_pixmap.width() ) / 2 );
+ p->drawPixmap( pixX, 0, m_pixmap );
+ p->drawText( textX, textY, m_text );
+ }
+ else
+ p->drawText( rect, Qt::AlignCenter, m_text );
+
+ p->restore();
+}
+
+
+void K3bFlatButton::setColors( const QColor& fore, const QColor& back )
+{
+ m_foreColor = fore;
+ m_backColor = back;
+
+ setHover( m_hover );
+}
+
+
+void K3bFlatButton::slotThemeChanged()
+{
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ setColors( theme->foregroundColor(), theme->backgroundColor() );
+ }
+}
+
+#include "k3bflatbutton.moc"
diff --git a/src/k3bflatbutton.h b/src/k3bflatbutton.h
new file mode 100644
index 0000000..a3dc97e
--- /dev/null
+++ b/src/k3bflatbutton.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * $Id: k3bflatbutton.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef FLATBUTTON_H
+#define FLATBUTTON_H
+
+#include <qframe.h>
+#include <qcolor.h>
+#include <qpixmap.h>
+
+class QEvent;
+class QMouseEvent;
+class QPainter;
+class KAction;
+
+
+/**
+@author Sebastian Trueg
+*/
+class K3bFlatButton : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ K3bFlatButton( QWidget *parent = 0, const char *name = 0 );
+ K3bFlatButton( const QString& text, QWidget *parent = 0, const char *name = 0 );
+ K3bFlatButton( KAction*, QWidget *parent = 0, const char *name = 0 );
+
+ ~K3bFlatButton();
+
+ QSize sizeHint() const;
+
+ public slots:
+ void setColors( const QColor& fore, const QColor& back );
+ void setText( const QString& );
+ void setPixmap( const QPixmap& );
+
+ signals:
+ void pressed();
+ void clicked();
+
+ private slots:
+ void slotThemeChanged();
+
+ private:
+ void init();
+
+ void mousePressEvent(QMouseEvent* e);
+ void mouseReleaseEvent(QMouseEvent* e);
+ void enterEvent( QEvent* );
+ void leaveEvent( QEvent* );
+ void drawContents( QPainter* );
+
+ void setHover( bool );
+
+ bool m_pressed;
+ QColor m_backColor;
+ QColor m_foreColor;
+ QString m_text;
+ QPixmap m_pixmap;
+
+ bool m_hover;
+};
+
+#endif
diff --git a/src/k3binteractiondialog.cpp b/src/k3binteractiondialog.cpp
new file mode 100644
index 0000000..4784c7f
--- /dev/null
+++ b/src/k3binteractiondialog.cpp
@@ -0,0 +1,662 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3binteractiondialog.h"
+#include "k3btitlelabel.h"
+#include "kcutlabel.h"
+#include "k3bstdguiitems.h"
+#include "k3bpushbutton.h"
+#include "k3bthemedheader.h"
+#include "k3bthememanager.h"
+#include <k3bapplication.h>
+#include <k3btoolbutton.h>
+#include <k3bmultichoicedialog.h>
+
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qstring.h>
+#include <qpoint.h>
+#include <qfont.h>
+#include <qpopupmenu.h>
+#include <qeventloop.h>
+#include <qapplication.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <kstdguiitem.h>
+#include <kpushbutton.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kglobalsettings.h>
+#include <kdeversion.h>
+
+
+K3bInteractionDialog::K3bInteractionDialog( QWidget* parent,
+ const char* name,
+ const QString& title,
+ const QString& subTitle,
+ int buttonMask,
+ int defaultButton,
+ const QString& configGroup,
+ bool modal,
+ WFlags fl )
+ : KDialog( parent, name, modal, fl ),
+ m_mainWidget(0),
+ m_defaultButton(defaultButton),
+ m_configGroup(configGroup),
+ m_exitLoopOnHide(true),
+ m_inLoop(false),
+ m_inToggleMode(false),
+ m_delayedInit(false)
+{
+ installEventFilter( this );
+
+ mainGrid = new QGridLayout( this );
+ mainGrid->setSpacing( spacingHint() );
+ mainGrid->setMargin( marginHint() );
+
+ // header
+ // ---------------------------------------------------------------------------------------------------
+ m_dialogHeader = new K3bThemedHeader( this );
+ mainGrid->addMultiCellWidget( m_dialogHeader, 0, 0, 0, 2 );
+
+
+ // settings buttons
+ // ---------------------------------------------------------------------------------------------------
+ if( !m_configGroup.isEmpty() ) {
+ QHBoxLayout* layout2 = new QHBoxLayout( 0, 0, spacingHint(), "layout2");
+ m_buttonLoadSettings = new K3bToolButton( /*i18n("User Defaults"), */this );
+ ((K3bToolButton*)m_buttonLoadSettings)->setIconSet( SmallIconSet( "revert" ) );
+ QPopupMenu* userDefaultsPopup = new QPopupMenu( m_buttonLoadSettings );
+ userDefaultsPopup->insertItem( i18n("Load default settings"), this, SLOT(slotLoadK3bDefaults()) );
+ userDefaultsPopup->insertItem( i18n("Load saved settings"), this, SLOT(slotLoadUserDefaults()) );
+ userDefaultsPopup->insertItem( i18n("Load last used settings"), this, SLOT(slotLoadLastSettings()) );
+ ((QToolButton*)m_buttonLoadSettings)->setPopup( userDefaultsPopup );
+ ((K3bToolButton*)m_buttonLoadSettings)->setInstantMenu( true );
+ layout2->addWidget( m_buttonLoadSettings );
+
+ m_buttonSaveSettings = new QToolButton( /*i18n("Save User Defaults"), */this, "m_buttonSaveSettings" );
+ ((QToolButton*)m_buttonSaveSettings)->setIconSet( SmallIconSet( "filesave" ) );
+ layout2->addWidget( m_buttonSaveSettings );
+
+ mainGrid->addLayout( layout2, 2, 0 );
+ }
+
+ QSpacerItem* spacer = new QSpacerItem( 10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ mainGrid->addItem( spacer, 2, 1 );
+
+
+ // action buttons
+ // ---------------------------------------------------------------------------------------------------
+ QHBoxLayout* layout5 = new QHBoxLayout( 0, 0, spacingHint(), "layout5");
+
+ if( buttonMask & START_BUTTON ) {
+ KGuiItem startItem = KStdGuiItem::ok();
+ m_buttonStart = new KPushButton( startItem, this, "m_buttonStart" );
+ // refine the button text
+ setButtonText( START_BUTTON,
+ i18n("Start"),
+ i18n("Start the task") );
+ QFont fnt( m_buttonStart->font() );
+ fnt.setBold(true);
+ m_buttonStart->setFont( fnt );
+ }
+ else
+ m_buttonStart = 0;
+
+ if( buttonMask & SAVE_BUTTON ) {
+ m_buttonSave = new KPushButton( KStdGuiItem::save(), this, "m_buttonSave" );
+ }
+ else
+ m_buttonSave = 0;
+
+ if( buttonMask & CANCEL_BUTTON ) {
+ m_buttonCancel = new KPushButton( KConfigGroup( k3bcore->config(), "General Options" )
+ .readBoolEntry( "keep action dialogs open", false )
+ ? KStdGuiItem::close()
+ : KStdGuiItem::cancel(),
+ this,
+ "m_buttonCancel" );
+ }
+ else
+ m_buttonCancel = 0;
+
+ // we only handle some of the possible settings since
+ // our buttons are always to the right of the dialog
+ int btl = 0;
+#if KDE_IS_VERSION(3,3,0)
+ btl = KGlobalSettings::buttonLayout();
+#endif
+ switch( btl ) {
+ case 0: // KDE default
+ default:
+ if ( m_buttonStart )
+ layout5->addWidget( m_buttonStart );
+ if ( m_buttonSave )
+ layout5->addWidget( m_buttonSave );
+ if ( m_buttonCancel )
+ layout5->addWidget( m_buttonCancel );
+ break;
+
+ case 1: // something different
+ if ( m_buttonCancel )
+ layout5->addWidget( m_buttonCancel );
+ if ( m_buttonSave )
+ layout5->addWidget( m_buttonSave );
+ if ( m_buttonStart )
+ layout5->addWidget( m_buttonStart );
+ break;
+
+ case 2: // GTK-Style
+ if ( m_buttonSave )
+ layout5->addWidget( m_buttonSave );
+ if ( m_buttonCancel )
+ layout5->addWidget( m_buttonCancel );
+ if ( m_buttonStart )
+ layout5->addWidget( m_buttonStart );
+ break;
+ }
+
+ mainGrid->addLayout( layout5, 2, 2 );
+
+ mainGrid->setRowStretch( 1, 1 );
+
+ setTitle( title, subTitle );
+
+ initConnections();
+ initToolTipsAndWhatsThis();
+
+ setDefaultButton( START_BUTTON );
+}
+
+K3bInteractionDialog::~K3bInteractionDialog()
+{
+}
+
+
+void K3bInteractionDialog::show()
+{
+ KDialog::show();
+ if( KPushButton* b = getButton( m_defaultButton ) )
+ b->setFocus();
+}
+
+
+QSize K3bInteractionDialog::sizeHint() const
+{
+ QSize s = KDialog::sizeHint();
+ // I want the dialogs to look good.
+ // That means their height should never outgrow their width
+ if( s.height() > s.width() )
+ s.setWidth( s.height() );
+
+ return s;
+}
+
+
+void K3bInteractionDialog::initConnections()
+{
+ if( m_buttonStart ) {
+ connect( m_buttonStart, SIGNAL(clicked()),
+ this, SLOT(slotStartClickedInternal()) );
+ }
+ if( m_buttonSave ) {
+// connect( m_buttonSave, SIGNAL(clicked()),
+// this, SLOT(slotSaveLastSettings()) );
+ connect( m_buttonSave, SIGNAL(clicked()),
+ this, SLOT(slotSaveClicked()) );
+ }
+ if( m_buttonCancel )
+ connect( m_buttonCancel, SIGNAL(clicked()),
+ this, SLOT(slotCancelClicked()) );
+
+ if( !m_configGroup.isEmpty() ) {
+ connect( m_buttonSaveSettings, SIGNAL(clicked()),
+ this, SLOT(slotSaveUserDefaults()) );
+ }
+}
+
+
+void K3bInteractionDialog::initToolTipsAndWhatsThis()
+{
+ if( !m_configGroup.isEmpty() ) {
+ // ToolTips
+ // -------------------------------------------------------------------------
+ QToolTip::add( m_buttonLoadSettings, i18n("Load default or saved settings") );
+ QToolTip::add( m_buttonSaveSettings, i18n("Save current settings to reuse them later") );
+
+ // What's This info
+ // -------------------------------------------------------------------------
+ QWhatsThis::add( m_buttonLoadSettings, i18n("<p>Load a set of settings either from the default K3b settings, "
+ "settings saved before, or the last used ones.") );
+ QWhatsThis::add( m_buttonSaveSettings, i18n("<p>Saves the current settings of the action dialog."
+ "<p>These settings can be loaded with the <em>Load saved settings</em> "
+ "button."
+ "<p><b>The K3b defaults are not overwritten by this.</b>") );
+ }
+}
+
+
+void K3bInteractionDialog::setTitle( const QString& title, const QString& subTitle )
+{
+ m_dialogHeader->setTitle( title, subTitle );
+
+ setCaption( title );
+}
+
+
+void K3bInteractionDialog::setMainWidget( QWidget* w )
+{
+ w->reparent( this, QPoint(0,0) );
+ mainGrid->addMultiCellWidget( w, 1, 1, 0, 2 );
+ m_mainWidget = w;
+}
+
+QWidget* K3bInteractionDialog::mainWidget()
+{
+ if( !m_mainWidget ) {
+ setMainWidget( new QWidget( this ) );
+ }
+ return m_mainWidget;
+}
+
+void K3bInteractionDialog::slotLoadK3bDefaults()
+{
+ loadK3bDefaults();
+}
+
+void K3bInteractionDialog::slotLoadUserDefaults()
+{
+ KConfigGroup c( k3bcore->config(), m_configGroup );
+ loadUserDefaults( &c );
+}
+
+void K3bInteractionDialog::slotSaveUserDefaults()
+{
+ KConfigGroup c( k3bcore->config(), m_configGroup );
+ saveUserDefaults( &c );
+}
+
+
+void K3bInteractionDialog::slotLoadLastSettings()
+{
+ KConfigGroup c( k3bcore->config(), "last used " + m_configGroup );
+ loadUserDefaults( &c );
+}
+
+
+void K3bInteractionDialog::saveLastSettings()
+{
+ KConfigGroup c( k3bcore->config(), "last used " + m_configGroup );
+ saveUserDefaults( &c );
+}
+
+
+void K3bInteractionDialog::slotStartClickedInternal()
+{
+ saveLastSettings();
+
+ KConfigGroup c( k3bcore->config(), "General Options" );
+ if( !c.readNumEntry( "action dialog startup settings", 0 ) ) {
+ // first time saving last used settings
+ switch( K3bMultiChoiceDialog::choose( i18n("Action Dialog Settings"),
+ i18n("<p>K3b handles three sets of settings in action dialogs: "
+ "the defaults, the saved settings, and the last used settings. "
+ "Please choose which of these sets should be loaded if an action "
+ "dialog is opened again."
+ "<p><em>Be aware that this choice can always be changed from the K3b "
+ "configuration dialog.</em>"),
+ QMessageBox::Question,
+ this,
+ 0,
+ 3,
+ i18n("Default Settings"),
+ i18n("Saved Settings"),
+ i18n("Last Used Settings") ) ) {
+ case 1:
+ c.writeEntry( "action dialog startup settings", LOAD_K3B_DEFAULTS );
+ break;
+ case 2:
+ c.writeEntry( "action dialog startup settings", LOAD_SAVED_SETTINGS );
+ break;
+ case 3:
+ c.writeEntry( "action dialog startup settings", LOAD_LAST_SETTINGS );
+ break;
+ }
+ }
+
+ slotStartClicked();
+}
+
+
+void K3bInteractionDialog::slotStartClicked()
+{
+ emit started();
+}
+
+void K3bInteractionDialog::slotCancelClicked()
+{
+ emit canceled();
+ close( false );
+}
+
+void K3bInteractionDialog::slotSaveClicked()
+{
+ emit saved();
+}
+
+
+void K3bInteractionDialog::setDefaultButton( int button )
+{
+ m_defaultButton = button;
+
+ // reset all other default buttons
+ if( KPushButton* b = getButton( START_BUTTON ) )
+ b->setDefault( true );
+ if( KPushButton* b = getButton( SAVE_BUTTON ) )
+ b->setDefault( true );
+ if( KPushButton* b = getButton( CANCEL_BUTTON ) )
+ b->setDefault( true );
+
+ // set the selected default
+ if( KPushButton* b = getButton( button ) )
+ b->setDefault( true );
+}
+
+
+bool K3bInteractionDialog::eventFilter( QObject* o, QEvent* ev )
+{
+ if( dynamic_cast<K3bInteractionDialog*>(o) == this &&
+ ev->type() == QEvent::KeyPress ) {
+
+ QKeyEvent* kev = dynamic_cast<QKeyEvent*>(ev);
+
+ switch ( kev->key() ) {
+ case Key_Enter:
+ case Key_Return:
+ // if the process finished this closes the dialog
+ if( m_defaultButton == START_BUTTON ) {
+ if( m_buttonStart->isEnabled() )
+ slotStartClickedInternal();
+ }
+ else if( m_defaultButton == CANCEL_BUTTON ) {
+ if( m_buttonCancel->isEnabled() )
+ slotCancelClicked();
+ }
+ else if( m_defaultButton == SAVE_BUTTON ) {
+ if( m_buttonSave->isEnabled() )
+ slotSaveClicked();
+ }
+ return true;
+
+ case Key_Escape:
+ // simulate button clicks
+ if( m_buttonCancel ) {
+ if( m_buttonCancel->isEnabled() )
+ slotCancelClicked();
+ }
+ return true;
+ }
+ }
+
+ return KDialog::eventFilter( o, ev );
+}
+
+
+KPushButton* K3bInteractionDialog::getButton( int button )
+{
+ switch( button ) {
+ case START_BUTTON:
+ return m_buttonStart;
+ case SAVE_BUTTON:
+ return m_buttonSave;
+ case CANCEL_BUTTON:
+ return m_buttonCancel;
+ default:
+ return 0;
+ }
+}
+
+
+void K3bInteractionDialog::setButtonGui( int button,
+ const KGuiItem& item )
+{
+ if( KPushButton* b = getButton( button ) )
+ b->setGuiItem( item );
+}
+
+
+void K3bInteractionDialog::setButtonText( int button,
+ const QString& text,
+ const QString& tooltip,
+ const QString& whatsthis )
+{
+ if( KPushButton* b = getButton( button ) ) {
+ b->setText( text );
+ QToolTip::remove( b );
+ QWhatsThis::remove( b );
+ QToolTip::add( b, tooltip );
+ QWhatsThis::add( b, whatsthis );
+ }
+}
+
+
+void K3bInteractionDialog::setButtonEnabled( int button, bool enabled )
+{
+ if( KPushButton* b = getButton( button ) ) {
+ b->setEnabled( enabled );
+ // make sure the correct button is selected as default again
+ setDefaultButton( m_defaultButton );
+ }
+}
+
+
+void K3bInteractionDialog::setButtonShown( int button, bool shown )
+{
+ if( KPushButton* b = getButton( button ) ) {
+ b->setShown( shown );
+ // make sure the correct button is selected as default again
+ setDefaultButton( m_defaultButton );
+ }
+}
+
+
+void K3bInteractionDialog::setStartButtonText( const QString& text,
+ const QString& tooltip,
+ const QString& whatsthis )
+{
+ if( m_buttonStart ) {
+ m_buttonStart->setText( text );
+ QToolTip::remove( m_buttonStart );
+ QWhatsThis::remove( m_buttonStart );
+ QToolTip::add( m_buttonStart, tooltip );
+ QWhatsThis::add( m_buttonStart, whatsthis );
+ }
+}
+
+
+void K3bInteractionDialog::setCancelButtonText( const QString& text,
+ const QString& tooltip,
+ const QString& whatsthis )
+{
+ if( m_buttonCancel ) {
+ m_buttonCancel->setText( text );
+ QToolTip::remove( m_buttonCancel );
+ QWhatsThis::remove( m_buttonCancel );
+ QToolTip::add( m_buttonCancel, tooltip );
+ QWhatsThis::add( m_buttonCancel, whatsthis );
+ }
+}
+
+
+void K3bInteractionDialog::setSaveButtonText( const QString& text,
+ const QString& tooltip,
+ const QString& whatsthis )
+{
+ if( m_buttonSave ) {
+ m_buttonSave->setText( text );
+ QToolTip::remove( m_buttonSave );
+ QWhatsThis::remove( m_buttonSave );
+ QToolTip::add( m_buttonSave, tooltip );
+ QWhatsThis::add( m_buttonSave, whatsthis );
+ }
+}
+
+
+void K3bInteractionDialog::saveUserDefaults( KConfigBase* )
+{
+}
+
+
+void K3bInteractionDialog::loadUserDefaults( KConfigBase* )
+{
+}
+
+
+void K3bInteractionDialog::loadK3bDefaults()
+{
+}
+
+
+void K3bInteractionDialog::loadStartupSettings()
+{
+ KConfigGroup c( k3bcore->config(), "General Options" );
+
+ // earlier K3b versions loaded the saved settings
+ // so that is what we do as a default
+ int i = c.readNumEntry( "action dialog startup settings", LOAD_SAVED_SETTINGS );
+ switch( i ) {
+ case LOAD_K3B_DEFAULTS:
+ slotLoadK3bDefaults();
+ break;
+ case LOAD_SAVED_SETTINGS:
+ slotLoadUserDefaults();
+ break;
+ case LOAD_LAST_SETTINGS:
+ slotLoadLastSettings();
+ break;
+ }
+}
+
+
+int K3bInteractionDialog::exec()
+{
+ return exec( true );
+}
+
+
+int K3bInteractionDialog::exec( bool returnOnHide )
+{
+ m_exitLoopOnHide = returnOnHide;
+
+ // the following code is mainly taken from QDialog::exec
+
+ if( m_inLoop ) {
+ kdError() << "(K3bInteractionDialog::exec) Recursive call detected." << endl;
+ return -1;
+ }
+
+ bool destructiveClose = testWFlags( WDestructiveClose );
+ clearWFlags( WDestructiveClose );
+
+ bool wasShowModal = testWFlags( WShowModal );
+ setWFlags( WShowModal );
+ setResult( 0 );
+
+ loadStartupSettings();
+ show();
+ if( m_delayedInit )
+ QTimer::singleShot( 0, this, SLOT(slotDelayedInit()) );
+ else
+ init();
+
+ m_inLoop = true;
+ QApplication::eventLoop()->enterLoop();
+
+ if( !wasShowModal )
+ clearWFlags( WShowModal );
+
+ int res = result();
+
+ if( destructiveClose )
+ delete this;
+
+ return res;
+}
+
+
+void K3bInteractionDialog::hide()
+{
+ if( isHidden() )
+ return;
+
+ KDialog::hide();
+
+ if( m_inLoop && m_exitLoopOnHide ) {
+ m_inLoop = false;
+ QApplication::eventLoop()->exitLoop();
+ }
+}
+
+
+bool K3bInteractionDialog::close( bool alsoDelete )
+{
+ if( m_inLoop && !m_exitLoopOnHide ) {
+ m_inLoop = false;
+ QApplication::eventLoop()->exitLoop();
+ }
+
+ return KDialog::close( alsoDelete );
+}
+
+
+void K3bInteractionDialog::done( int r )
+{
+ if( m_inLoop && !m_exitLoopOnHide ) {
+ m_inLoop = false;
+ QApplication::eventLoop()->exitLoop();
+ }
+
+ return KDialog::done( r );
+}
+
+
+void K3bInteractionDialog::slotToggleAll()
+{
+ if( !m_inToggleMode ) {
+ m_inToggleMode = true;
+ toggleAll();
+ m_inToggleMode = false;
+ }
+}
+
+
+void K3bInteractionDialog::toggleAll()
+{
+}
+
+
+void K3bInteractionDialog::slotDelayedInit()
+{
+ init();
+}
+
+#include "k3binteractiondialog.moc"
diff --git a/src/k3binteractiondialog.h b/src/k3binteractiondialog.h
new file mode 100644
index 0000000..2bdb426
--- /dev/null
+++ b/src/k3binteractiondialog.h
@@ -0,0 +1,279 @@
+/*
+ *
+ * $Id: k3binteractiondialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_INTERACTION_DIALOG_H_
+#define _K3B_INTERACTION_DIALOG_H_
+
+#include <kdialog.h>
+
+
+class QGridLayout;
+class QLabel;
+class KPushButton;
+class QButton;
+class K3bThemedHeader;
+class KConfigBase;
+class KGuiItem;
+
+
+/**
+ * This is the base dialog for all the dialogs in K3b that start
+ * some job. Use setMainWidget to set the contents or let mainWidget()
+ * create an empty plain page.
+ * The default implementations of the slots just emit the
+ * corresponding signals.
+ */
+class K3bInteractionDialog : public KDialog
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * The constructor.
+ * loadUserDefaults will be called automatically when the dialog is showing.
+ *
+ * @param title the text to be displayed in the K3b header (not the widget frame)
+ * @param subTitle additional text that will be displayed after the title in smaller size
+ * @param buttonMask combination of Buttons
+ * @param defaultButton may also be null to deactivate the feature
+ * @param configgroup The config group used for the loadUserDefaults and saveUserDefaults methods
+ */
+ K3bInteractionDialog( QWidget* parent = 0,
+ const char* name = 0,
+ const QString& title = QString::null,
+ const QString& subTitle = QString::null,
+ int buttonMask = START_BUTTON|CANCEL_BUTTON,
+ int defaultButton = START_BUTTON,
+ const QString& configgroup = QString::null,
+ bool modal = true,
+ WFlags fl = 0 );
+ virtual ~K3bInteractionDialog();
+
+ void setMainWidget( QWidget* w );
+ void setTitle( const QString& title, const QString& subTitle = QString::null );
+ void setDefaultButton( int b );
+
+ /**
+ * Reimplemented for internal reasons. The API does not change.
+ */
+ int exec();
+
+ /**
+ * @param returnOnHide if false the dialog can be hidden and shown without being closed.
+ * one needs to call close() to actually close the dialog.
+ */
+ int exec( bool returnOnHide );
+
+ /**
+ * reimplemented to allow initialization after the dialog has been opened.
+ */
+ void show();
+
+ /**
+ * Reimplemented for internal reasons. The API does not change.
+ */
+ void hide();
+
+ /**
+ * Reimplemented for internal reasons. The API does not change.
+ */
+ bool close( bool alsoDelete );
+
+ inline bool close() { return close( false ); }
+
+ /**
+ * If no mainWidget has been set a plain page will be created.
+ */
+ QWidget* mainWidget();
+
+ enum Buttons {
+ START_BUTTON = 1,
+ SAVE_BUTTON = 2,
+ CANCEL_BUTTON = 4
+ };
+
+ QSize sizeHint() const;
+
+ const QString& configGroup() const { return m_configGroup; }
+
+ /**
+ * K3b's dialogs use this method to determine if it is safe to hide when starting
+ * some action. Take for example the copy dialog which starts a copy job with a progress
+ * dialog. Both the job and the progress dialog are deleted by the copy dialog after the
+ * progress dialog has been closed. If the copy dialog would hide itself before starting
+ * the job and exitLoopOnHide() would return true the hiding would result in the exec call
+ * of the copy dialog to return. And what would that mean for the code after the hide()
+ * statement (deleting of the job and so on).
+ *
+ * \return true in case this dialog will not exit it's private event loop
+ * in case it is hidden.
+ *
+ * \see exec(bool)
+ */
+ bool exitLoopOnHide() const { return m_exitLoopOnHide; }
+
+ enum StartUpSettings {
+ LOAD_K3B_DEFAULTS = 1,
+ LOAD_SAVED_SETTINGS = 2,
+ LOAD_LAST_SETTINGS = 3
+ };
+
+ signals:
+ void started();
+ void canceled();
+ void saved();
+
+ public slots:
+ /**
+ * \deprecated use setButtonText
+ */
+ void setStartButtonText( const QString& text,
+ const QString& tooltip = QString::null,
+ const QString& whatsthis = QString::null );
+ /**
+ * \deprecated use setButtonText
+ */
+ void setCancelButtonText( const QString& text,
+ const QString& tooltip = QString::null,
+ const QString& whatsthis = QString::null );
+ /**
+ * \deprecated use setButtonText
+ */
+ void setSaveButtonText( const QString& text,
+ const QString& tooltip = QString::null,
+ const QString& whatsthis = QString::null );
+
+ void setButtonGui( int button,
+ const KGuiItem& );
+
+ void setButtonText( int button,
+ const QString& text,
+ const QString& tooltip = QString::null,
+ const QString& whatsthis = QString::null );
+
+ void setButtonEnabled( int button, bool enabled );
+ void setButtonShown( int button, bool enabled );
+
+ /**
+ * If set true the init() method will be called via a QTimer to ensure event
+ * handling be done before (default: false).
+ */
+ void setDelayedInitialization( bool b ) { m_delayedInit = b; }
+
+ protected slots:
+ // FIXME: replace these with protected methods which are called from private slots.
+ virtual void slotStartClicked();
+
+ /**
+ * The default implementation emits the canceled() signal
+ * and calls close()
+ */
+ virtual void slotCancelClicked();
+ virtual void slotSaveClicked();
+
+ /**
+ * This slot will call the toggleAll() method protecting from infinite loops
+ * caused by one element influencing another element which in turn influences
+ * the first.
+ *
+ * Connect this slot to GUI elements (like Checkboxes) that change
+ * the state of the whole dialog.
+ */
+ void slotToggleAll();
+
+ protected:
+ /**
+ * Reimplement this method in case you are using slotToggleAll()
+ */
+ virtual void toggleAll();
+
+ /**
+ * Reimplement this to support the save/load user default buttons.
+ * @p config is already set to the correct group.
+ *
+ * The save/load buttons are only activated if the config group is
+ * set in the constructor.
+ */
+ virtual void saveUserDefaults( KConfigBase* config );
+
+ /**
+ * Reimplement this to support the save/load user default buttons.
+ * @p config is already set to the correct group.
+ *
+ * The save/load buttons are only activated if the config group is
+ * set in the constructor.
+ */
+ virtual void loadUserDefaults( KConfigBase* config );
+
+ /**
+ * Reimplement this to support the "k3b defaults" button.
+ * set all GUI options to reasonable defaults.
+ */
+ virtual void loadK3bDefaults();
+
+ /**
+ * This is called after the dialog has been shown.
+ * Use this for initialization that should happen
+ * when the user already sees the dialog.
+ */
+ virtual void init() {}
+
+ /**
+ * reimplemented from QDialog
+ */
+ virtual bool eventFilter( QObject*, QEvent* );
+
+ protected slots:
+ /**
+ * Reimplemented for internal reasons. The API does not change.
+ */
+ virtual void done( int );
+
+ private slots:
+ void slotLoadK3bDefaults();
+ void slotLoadUserDefaults();
+ void slotSaveUserDefaults();
+ void slotLoadLastSettings();
+ void slotStartClickedInternal();
+ void slotDelayedInit();
+
+ private:
+ void initConnections();
+ void initToolTipsAndWhatsThis();
+ void saveLastSettings();
+ void loadStartupSettings();
+
+ KPushButton* getButton( int );
+
+ K3bThemedHeader* m_dialogHeader;
+ KPushButton* m_buttonStart;
+ KPushButton* m_buttonSave;
+ KPushButton* m_buttonCancel;
+ QWidget* m_mainWidget;
+
+ QButton* m_buttonLoadSettings;
+ QButton* m_buttonSaveSettings;
+
+ QGridLayout* mainGrid;
+ int m_defaultButton;
+ QString m_configGroup;
+
+ bool m_exitLoopOnHide;
+ bool m_inLoop;
+ bool m_inToggleMode;
+ bool m_delayedInit;
+};
+
+#endif
diff --git a/src/k3binterface.cpp b/src/k3binterface.cpp
new file mode 100644
index 0000000..c95e598
--- /dev/null
+++ b/src/k3binterface.cpp
@@ -0,0 +1,192 @@
+/*
+ *
+ * $Id: k3binterface.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3binterface.h"
+#include "k3bprojectinterface.h"
+#include "k3bprojectmanager.h"
+#include "k3bapplication.h"
+#include "k3bdoc.h"
+#include "k3bview.h"
+#include "k3bcore.h"
+#include "k3b.h"
+
+#include <k3bglobals.h>
+
+#include <dcopclient.h>
+#include <qptrlist.h>
+#include <qtimer.h>
+
+
+
+K3bInterface::K3bInterface()
+ : DCOPObject( "K3bInterface" ),
+ m_main( 0 )
+{
+}
+
+DCOPRef K3bInterface::createDataCDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::DATA ) )->objId() );
+}
+
+DCOPRef K3bInterface::createAudioCDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::AUDIO ) )->objId() );
+}
+
+DCOPRef K3bInterface::createMixedCDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::MIXED ) )->objId() );
+}
+
+DCOPRef K3bInterface::createVideoCDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::VCD ) )->objId() );
+}
+
+DCOPRef K3bInterface::createMovixCDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::MOVIX ) )->objId() );
+}
+
+DCOPRef K3bInterface::createDataDVDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::DVD ) )->objId() );
+}
+
+DCOPRef K3bInterface::createVideoDVDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::VIDEODVD ) )->objId() );
+}
+
+DCOPRef K3bInterface::createMovixDVDProject()
+{
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( k3bappcore->projectManager()->createProject( K3bDoc::MOVIX_DVD ) )->objId() );
+}
+
+DCOPRef K3bInterface::currentProject()
+{
+ K3bView* view = m_main->activeView();
+ if( view )
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( view->doc() )->objId() );
+ else
+ return DCOPRef();
+}
+
+DCOPRef K3bInterface::openProject( const KURL& url )
+{
+ K3bDoc* doc = k3bappcore->projectManager()->openProject( url );
+ if( doc )
+ return DCOPRef( kapp->dcopClient()->appId(),
+ k3bappcore->projectManager()->dcopInterface( doc )->objId() );
+ else
+ return DCOPRef();
+}
+
+QValueList<DCOPRef> K3bInterface::projects()
+{
+ QValueList<DCOPRef> lst;
+ const QPtrList<K3bDoc>& docs = k3bappcore->projectManager()->projects();
+ for( QPtrListIterator<K3bDoc> it( docs ); it.current(); ++it )
+ lst.append( DCOPRef( kapp->dcopClient()->appId(), k3bappcore->projectManager()->dcopInterface( it.current() )->objId() ) );
+
+ return lst;
+}
+
+void K3bInterface::addUrls( const KURL::List& urls )
+{
+ m_main->addUrls( urls );
+}
+
+void K3bInterface::addUrl( const KURL& url )
+{
+ KURL::List l;
+ l.append(url);
+ addUrls( l );
+}
+
+
+void K3bInterface::copyCd( const KURL& dev )
+{
+ m_main->cdCopy( K3b::urlToDevice( dev ) );
+}
+
+
+void K3bInterface::copyDvd( const KURL& dev )
+{
+ m_main->dvdCopy( K3b::urlToDevice( dev ) );
+}
+
+
+void K3bInterface::copyCd()
+{
+ // HACK since we want this method to return immediately
+ QTimer::singleShot( 0, m_main, SLOT(slotCdCopy()) );
+}
+
+
+void K3bInterface::copyDvd()
+{
+ // HACK since we want this method to return immediately
+ QTimer::singleShot( 0, m_main, SLOT(slotDvdCopy()) );
+}
+
+
+void K3bInterface::eraseCdrw()
+{
+ // HACK since we want this method to return immediately
+ QTimer::singleShot( 0, m_main, SLOT(slotBlankCdrw()) );
+}
+
+
+void K3bInterface::formatDvd()
+{
+ // HACK since we want this method to return immediately
+ QTimer::singleShot( 0, m_main, SLOT(slotFormatDvd()) );
+}
+
+
+void K3bInterface::burnCdImage( const KURL& url )
+{
+ m_main->slotWriteCdImage( url );
+}
+
+
+void K3bInterface::burnDvdImage( const KURL& url )
+{
+ m_main->slotWriteDvdIsoImage( url );
+}
+
+
+bool K3bInterface::blocked() const
+{
+ return k3bcore->jobsRunning();
+}
+
+
+void K3bInterface::cddaRip( const KURL& dev )
+{
+ m_main->cddaRip( K3b::urlToDevice( dev ) );
+}
diff --git a/src/k3binterface.h b/src/k3binterface.h
new file mode 100644
index 0000000..b54e2ef
--- /dev/null
+++ b/src/k3binterface.h
@@ -0,0 +1,102 @@
+/*
+ *
+ * $Id: k3binterface.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_INTERFACE_H_
+#define _K3B_INTERFACE_H_
+
+#include <dcopobject.h>
+#include <dcopref.h>
+#include <qvaluelist.h>
+
+#include <kurl.h>
+
+class K3bMainWindow;
+namespace K3bDevice {
+ class Device;
+}
+
+
+class K3bInterface : public DCOPObject
+{
+ K_DCOP
+
+ public:
+ K3bInterface();
+
+ void setMainWindow( K3bMainWindow* mw ) { m_main = mw; }
+
+ k_dcop:
+ /**
+ * returns a DCOPRef to a K3bProjectInterface
+ */
+ DCOPRef createDataCDProject();
+ DCOPRef createAudioCDProject();
+ DCOPRef createMixedCDProject();
+ DCOPRef createVideoCDProject();
+ DCOPRef createMovixCDProject();
+ DCOPRef createDataDVDProject();
+ DCOPRef createVideoDVDProject();
+ DCOPRef createMovixDVDProject();
+
+ /**
+ * Returns a reference to the currently active project.
+ * This is useful to do things like:
+ *
+ * <pre>k3b --audiocd</pre>
+ * and then use dcop on the newly created project via:
+ * <pre>dcop $(dcop k3b K3bInterface currentProject) something</pre>
+ */
+ DCOPRef currentProject();
+
+ DCOPRef openProject( const KURL& url );
+
+ QValueList<DCOPRef> projects();
+
+ void copyCd();
+ void copyDvd();
+ void copyCd( const KURL& dev );
+ void copyDvd( const KURL& dev );
+ void eraseCdrw();
+ void formatDvd();
+ void burnCdImage( const KURL& url );
+ void burnDvdImage( const KURL& url );
+
+ /**
+ * Open the audio ripping window for the specified device.
+ */
+ void cddaRip( const KURL& dev );
+
+ /**
+ * Add URLs to the current active project.
+ * If no project is open a new Audio or Data CD
+ * project will be created depending on the type
+ * of the first file.
+ */
+ void addUrls( const KURL::List& urls );
+ void addUrl( const KURL& url );
+
+ /**
+ * @return true if currently some job is running.
+ */
+ bool blocked() const;
+
+ private:
+ K3bMainWindow* m_main;
+
+ K3bDevice::Device* m_lastDevice;
+};
+
+#endif
diff --git a/src/k3bjobinterface.cpp b/src/k3bjobinterface.cpp
new file mode 100644
index 0000000..60e4436
--- /dev/null
+++ b/src/k3bjobinterface.cpp
@@ -0,0 +1,190 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bjobinterface.h"
+
+#include <k3bjob.h>
+
+#include <qcstring.h>
+#include <qdatastream.h>
+
+
+K3bJobInterface::K3bJobInterface( QObject* parent )
+ : QObject( parent ),
+ DCOPObject( "K3bJobInterface" ),
+ m_job( 0 )
+{
+}
+
+
+void K3bJobInterface::setJob( K3bJob* job )
+{
+ if( m_job )
+ m_job->disconnect( this );
+
+ m_job = job;
+ m_lastProgress = m_lastSubProgress = 0;
+
+ if( m_job ) {
+ connect( m_job, SIGNAL(newTask(const QString&)), this, SLOT(slotNewTask(const QString&)) );
+ connect( m_job, SIGNAL(newSubTask(const QString&)), this, SLOT(slotNewSubTask(const QString&)) );
+ connect( m_job, SIGNAL(infoMessage(const QString&, int)), this, SLOT(slotInfoMessage(const QString&, int)) );
+ connect( m_job, SIGNAL(finished(bool)), this, SLOT(slotFinished(bool)) );
+ connect( m_job, SIGNAL(started()), this, SLOT(slotStarted()) );
+ connect( m_job, SIGNAL(canceled()), this, SLOT(slotCanceled()) );
+ connect( m_job, SIGNAL(percent(int)), this, SLOT(slotProgress(int)) );
+ connect( m_job, SIGNAL(subPercent(int)), this, SLOT(slotSubProgress(int)) );
+ connect( m_job, SIGNAL(nextTrack(int, int)), this, SLOT(slotNextTrack(int, int)) );
+
+ if( m_job->inherits( "K3bBurnJob" ) ) {
+ connect( m_job, SIGNAL(bufferStatus(int)), this, SLOT(slotBuffer(int)) );
+ connect( m_job, SIGNAL(deviceBuffer(int)), this, SLOT(slotDeviceBuffer(int)) );
+ }
+
+ connect( m_job, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
+ }
+}
+
+
+bool K3bJobInterface::jobRunning() const
+{
+ return ( m_job && m_job->active() );
+}
+
+
+QString K3bJobInterface::jobDescription() const
+{
+ if( m_job )
+ return m_job->jobDescription();
+ else
+ return QString::null;
+}
+
+
+QString K3bJobInterface::jobDetails() const
+{
+ if( m_job )
+ return m_job->jobDetails();
+ else
+ return QString::null;
+}
+
+
+void K3bJobInterface::slotStarted()
+{
+ m_lastProgress = m_lastSubProgress = 0;
+ emitDCOPSignal( "started()", QByteArray() );
+}
+
+
+void K3bJobInterface::slotCanceled()
+{
+ emitDCOPSignal( "canceled()", QByteArray() );
+}
+
+
+void K3bJobInterface::slotFinished( bool success )
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << success;
+ emitDCOPSignal( "finished(bool)", params );
+}
+
+
+void K3bJobInterface::slotInfoMessage( const QString& message, int type )
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << message << type;
+ emitDCOPSignal( "infoMessage(QString)", params );
+}
+
+
+void K3bJobInterface::slotProgress( int val )
+{
+ if( m_lastProgress != val ) {
+ m_lastProgress = val;
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << val;
+ emitDCOPSignal( "progress(int)", params );
+ }
+}
+
+
+void K3bJobInterface::slotSubProgress( int val )
+{
+ if( m_lastSubProgress != val ) {
+ m_lastSubProgress = val;
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << val;
+ emitDCOPSignal( "subProgress(int)", params );
+ }
+}
+
+
+void K3bJobInterface::slotNewTask( const QString& task )
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << task;
+ emitDCOPSignal( "newTask(QString)", params );
+}
+
+
+void K3bJobInterface::slotNewSubTask( const QString& task )
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << task;
+ emitDCOPSignal( "newSubTask(QString)", params );
+}
+
+
+void K3bJobInterface::slotBuffer( int val )
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << val;
+ emitDCOPSignal( "buffer(int)", params );
+}
+
+
+void K3bJobInterface::slotDeviceBuffer( int val )
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << val;
+ emitDCOPSignal( "deviceBuffer(int)", params );
+}
+
+
+void K3bJobInterface::slotNextTrack( int track, int numTracks )
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << track << numTracks;
+ emitDCOPSignal( "nextTrack(int,int)", params );
+}
+
+
+void K3bJobInterface::slotDestroyed()
+{
+ m_job = 0;
+}
+
+#include "k3bjobinterface.moc"
diff --git a/src/k3bjobinterface.h b/src/k3bjobinterface.h
new file mode 100644
index 0000000..0d27ac2
--- /dev/null
+++ b/src/k3bjobinterface.h
@@ -0,0 +1,82 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_JOB_INTERFACE_H_
+#define _K3B_JOB_INTERFACE_H_
+
+#include <qobject.h>
+#include <dcopobject.h>
+
+class K3bJob;
+
+
+/**
+ * A DCOP interface for K3b's currently running job.
+ *
+ * This may be used for example in a karamba theme with a non-volitile
+ * DCOP connection.
+ */
+class K3bJobInterface : public QObject, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+ public:
+ K3bJobInterface( QObject* parent );
+
+ void setJob( K3bJob* );
+
+ k_dcop:
+ bool jobRunning() const;
+
+ QString jobDescription() const;
+ QString jobDetails() const;
+
+ k_dcop_signals:
+ void started();
+ void canceled();
+ void finished( bool );
+ void infoMessage( const QString&, int );
+ void progress( int );
+ void subProgress( int );
+ void newTask( const QString& );
+ void newSubTask( const QString& );
+ void buffer( int );
+ void deviceBuffer( int );
+ void nextTrack( int track, int numTracks );
+
+ private slots:
+ void slotStarted();
+ void slotCanceled();
+ void slotFinished( bool );
+ void slotInfoMessage( const QString&, int );
+ void slotProgress( int );
+ void slotSubProgress( int );
+ void slotNewTask( const QString& );
+ void slotNewSubTask( const QString& );
+ void slotBuffer( int );
+ void slotDeviceBuffer( int );
+ void slotNextTrack( int track, int numTracks );
+
+ void slotDestroyed();
+
+ private:
+ K3bJob* m_job;
+
+ int m_lastProgress;
+ int m_lastSubProgress;
+};
+
+#endif
diff --git a/src/k3bjobprogressdialog.cpp b/src/k3bjobprogressdialog.cpp
new file mode 100644
index 0000000..351f1d9
--- /dev/null
+++ b/src/k3bjobprogressdialog.cpp
@@ -0,0 +1,696 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bjobprogressdialog.h"
+#include "k3bapplication.h"
+#include "k3bemptydiscwaiter.h"
+#include "k3bjobprogressosd.h"
+#include "k3bdebuggingoutputdialog.h"
+#include "k3bapplication.h"
+#include "k3bjobinterface.h"
+#include "k3bthemedlabel.h"
+#include <k3bjob.h>
+#include <kcutlabel.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bdeviceglobals.h>
+#include <k3bglobals.h>
+#include <k3bstdguiitems.h>
+#include <k3bversion.h>
+#include <k3bthememanager.h>
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qdatetime.h>
+#include <qstring.h>
+#include <qhbox.h>
+#include <qheader.h>
+#include <qscrollbar.h>
+#include <qpoint.h>
+#include <qfontmetrics.h>
+#include <qtimer.h>
+#include <qfont.h>
+#include <qeventloop.h>
+#include <qfile.h>
+#include <qapplication.h>
+
+#include <kprogress.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <knotifyclient.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <kstdguiitem.h>
+#include <kpushbutton.h>
+
+
+
+
+class K3bJobProgressDialog::Private
+{
+public:
+ int lastProgress;
+};
+
+
+
+K3bJobProgressDialog::K3bJobProgressDialog( QWidget* parent,
+ const char* name,
+ bool showSubProgress,
+ bool modal, WFlags fl )
+ : KDialog( parent, name, modal, fl ),
+ in_loop(false),
+ m_osd(0)
+{
+ d = new Private;
+
+ setupGUI();
+ setupConnections();
+
+ if( !showSubProgress ) {
+ m_progressSubPercent->hide();
+ }
+
+ m_job = 0;
+ m_timer = new QTimer( this );
+
+ connect( m_timer, SIGNAL(timeout()), this, SLOT(slotUpdateTime()) );
+}
+
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+K3bJobProgressDialog::~K3bJobProgressDialog()
+{
+ delete d;
+ delete m_osd;
+}
+
+
+void K3bJobProgressDialog::setupGUI()
+{
+ QVBoxLayout* mainLayout = new QVBoxLayout( this, 11, 6, "mainLayout");
+
+
+ // header
+ // ------------------------------------------------------------------------------------------
+ QFrame* headerFrame = new QFrame( this, "headerFrame" );
+ headerFrame->setFrameShape( QFrame::StyledPanel );
+ headerFrame->setFrameShadow( QFrame::Sunken );
+ headerFrame->setLineWidth( 1 );
+ headerFrame->setMargin( 1 );
+ QHBoxLayout* headerLayout = new QHBoxLayout( headerFrame );
+ headerLayout->setMargin( 2 ); // to make sure the frame gets displayed
+ headerLayout->setSpacing( 0 );
+ m_pixLabel = new K3bThemedLabel( headerFrame );
+ headerLayout->addWidget( m_pixLabel );
+
+ QFrame* frame4 = new QFrame( headerFrame, "frame4" );
+ frame4->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 1, 0, frame4->sizePolicy().hasHeightForWidth() ) );
+ frame4->setFrameShape( QFrame::NoFrame );
+ frame4->setFrameShadow( QFrame::Raised );
+ QVBoxLayout* frame4Layout = new QVBoxLayout( frame4, 6, 3, "frame4Layout");
+
+ m_labelJob = new K3bThemedLabel( frame4 );
+ m_labelJob->setMinimumVisibleText( 40 );
+ QFont m_labelJob_font( m_labelJob->font() );
+ m_labelJob_font.setPointSize( m_labelJob_font.pointSize() + 2 );
+ m_labelJob_font.setBold( true );
+ m_labelJob->setFont( m_labelJob_font );
+ m_labelJob->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ frame4Layout->addWidget( m_labelJob );
+
+ m_labelJobDetails = new K3bThemedLabel( frame4 );
+ m_labelJobDetails->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 0, 1, m_labelJobDetails->sizePolicy().hasHeightForWidth() ) );
+ m_labelJobDetails->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ frame4Layout->addWidget( m_labelJobDetails );
+ headerLayout->addWidget( frame4 );
+
+ mainLayout->addWidget( headerFrame );
+ // ------------------------------------------------------------------------------------------
+
+
+ m_viewInfo = new KListView( this, "m_viewInfo" );
+ m_viewInfo->addColumn( "" );
+ m_viewInfo->addColumn( i18n( "Message" ) );
+ m_viewInfo->setFullWidth( true );
+ m_viewInfo->header()->hide();
+ m_viewInfo->setSorting(-1);
+ mainLayout->addWidget( m_viewInfo );
+
+
+ // progress header
+ // ------------------------------------------------------------------------------------------
+ QFrame* progressHeaderFrame = new QFrame( this, "progressHeaderFrame" );
+ progressHeaderFrame->setFrameShape( QFrame::StyledPanel );
+ progressHeaderFrame->setFrameShadow( QFrame::Sunken );
+ progressHeaderFrame->setLineWidth( 1 );
+ progressHeaderFrame->setMargin( 1 );
+
+ QHBoxLayout* progressHeaderLayout = new QHBoxLayout( progressHeaderFrame );
+ progressHeaderLayout->setMargin( 2 );
+ progressHeaderLayout->setSpacing( 0 );
+
+ QFrame* frame5 = new QFrame( progressHeaderFrame, "frame5" );
+ frame5->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 1, 0, frame5->sizePolicy().hasHeightForWidth() ) );
+ frame5->setFrameShape( QFrame::NoFrame );
+ frame5->setFrameShadow( QFrame::Raised );
+ QVBoxLayout* frame5Layout = new QVBoxLayout( frame5, 6, 3, "frame5Layout");
+
+ m_labelTask = new K3bThemedLabel( frame5 );
+ QFont m_labelTask_font( m_labelTask->font() );
+ m_labelTask_font.setPointSize( m_labelTask_font.pointSize() + 2 );
+ m_labelTask_font.setBold( true );
+ m_labelTask->setFont( m_labelTask_font );
+ frame5Layout->addWidget( m_labelTask );
+
+ m_labelElapsedTime = new K3bThemedLabel( frame5 );
+ m_labelElapsedTime->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 0, 1, m_labelElapsedTime->sizePolicy().hasHeightForWidth() ) );
+ frame5Layout->addWidget( m_labelElapsedTime );
+ progressHeaderLayout->addWidget( frame5 );
+
+ progressHeaderLayout->addWidget( new K3bThemedLabel( K3bTheme::PROGRESS_RIGHT, progressHeaderFrame ) );
+ mainLayout->addWidget( progressHeaderFrame );
+ // ------------------------------------------------------------------------------------------
+
+ QHBoxLayout* layout3 = new QHBoxLayout( 0, 0, 6, "layout3");
+
+ m_labelSubTask = new KCutLabel( this, "m_labelSubTask" );
+ layout3->addWidget( m_labelSubTask );
+
+ m_labelSubProcessedSize = new QLabel( this, "m_labelSubProcessedSize" );
+ m_labelSubProcessedSize->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ layout3->addWidget( m_labelSubProcessedSize );
+ mainLayout->addLayout( layout3 );
+
+ m_progressSubPercent = new KProgress( this, "m_progressSubPercent" );
+ mainLayout->addWidget( m_progressSubPercent );
+
+ QHBoxLayout* layout4 = new QHBoxLayout( 0, 0, 6, "layout4");
+
+ QLabel* textLabel5 = new QLabel( i18n("Overall progress:"), this, "textLabel5" );
+ layout4->addWidget( textLabel5 );
+
+ m_labelProcessedSize = new QLabel( this, "m_labelProcessedSize" );
+ m_labelProcessedSize->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ layout4->addWidget( m_labelProcessedSize );
+ mainLayout->addLayout( layout4 );
+
+ m_progressPercent = new KProgress( this, "m_progressPercent" );
+ mainLayout->addWidget( m_progressPercent );
+
+ m_frameExtraInfo = new QFrame( this, "m_frameExtraInfo" );
+ m_frameExtraInfo->setFrameShape( QFrame::NoFrame );
+ m_frameExtraInfo->setFrameShadow( QFrame::Raised );
+ m_frameExtraInfoLayout = new QGridLayout( m_frameExtraInfo );
+ m_frameExtraInfoLayout->setMargin(0);
+ m_frameExtraInfoLayout->setSpacing( spacingHint() );
+ mainLayout->addWidget( m_frameExtraInfo );
+
+ QFrame* line2 = new QFrame( this, "line2" );
+ line2->setFrameShape( QFrame::HLine );
+ line2->setFrameShadow( QFrame::Sunken );
+ mainLayout->addWidget( line2 );
+
+ QHBoxLayout* layout5 = new QHBoxLayout( 0, 0, 6, "layout5");
+ QSpacerItem* spacer = new QSpacerItem( 10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ layout5->addItem( spacer );
+
+ m_buttonCancel = new KPushButton( KStdGuiItem::cancel(), this, "m_buttonCancel" );
+ layout5->addWidget( m_buttonCancel );
+ m_buttonClose = new KPushButton( KStdGuiItem::close(), this );
+ layout5->addWidget( m_buttonClose );
+ m_buttonShowDebug = new QPushButton( i18n("Show Debugging Output"), this );
+ layout5->addWidget( m_buttonShowDebug );
+
+ mainLayout->addLayout( layout5 );
+
+ m_pixLabel->setThemePixmap( K3bTheme::PROGRESS_WORKING );
+
+ slotThemeChanged();
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()),
+ this, SLOT(slotThemeChanged()) );
+ connect( kapp, SIGNAL(appearanceChanged()),
+ this, SLOT(slotThemeChanged()) );
+}
+
+
+void K3bJobProgressDialog::show()
+{
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "hide main window while writing", false ) )
+ if( QWidget* w = kapp->mainWidget() )
+ w->hide();
+
+ if( m_osd ) {
+ m_osd->readSettings( k3bcore->config() );
+ m_osd->show();
+ }
+
+ KDialog::show();
+}
+
+
+void K3bJobProgressDialog::setExtraInfo( QWidget *extra )
+{
+ extra->reparent( m_frameExtraInfo, QPoint(0,0) );
+ m_frameExtraInfoLayout->addWidget( extra, 0, 0 );
+}
+
+
+void K3bJobProgressDialog::closeEvent( QCloseEvent* e )
+{
+ if( m_buttonClose->isVisible() ) {
+ KDialog::closeEvent( e );
+ if( QWidget* w = kapp->mainWidget() )
+ w->show();
+
+ if( !m_plainCaption.isEmpty() )
+ if( KMainWindow* w = dynamic_cast<KMainWindow*>(kapp->mainWidget()) )
+ w->setPlainCaption( m_plainCaption );
+
+ if( m_osd ) {
+ m_osd->hide();
+ m_osd->saveSettings( kapp->config() );
+ }
+ }
+ else
+ e->ignore();
+}
+
+
+void K3bJobProgressDialog::setupConnections()
+{
+ connect( m_buttonCancel, SIGNAL(clicked()), this, SLOT(slotCancelButtonPressed()) );
+ connect( m_buttonClose, SIGNAL(clicked()), this, SLOT(close()) );
+ connect( m_buttonShowDebug, SIGNAL(clicked()), this, SLOT(slotShowDebuggingOutput()) );
+}
+
+
+void K3bJobProgressDialog::slotProcessedSize( int processed, int size )
+{
+ m_labelProcessedSize->setText( i18n("%1 of %2 MB").arg( processed ).arg( size ) );
+}
+
+
+void K3bJobProgressDialog::slotProcessedSubSize( int processedTrackSize, int trackSize )
+{
+ m_labelSubProcessedSize->setText( i18n("%1 of %2 MB").arg(processedTrackSize).arg(trackSize) );
+}
+
+
+void K3bJobProgressDialog::slotInfoMessage( const QString& infoString, int type )
+{
+ QListViewItem* currentInfoItem = new QListViewItem( m_viewInfo, m_viewInfo->lastItem(), QString::null, infoString );
+ currentInfoItem->setSelectable( false );
+
+ // set the icon
+ switch( type ) {
+ case K3bJob::ERROR:
+ currentInfoItem->setPixmap( 0, SmallIcon( "stop" ) );
+ break;
+ case K3bJob::WARNING:
+ currentInfoItem->setPixmap( 0, SmallIcon( "yellowinfo" ) );
+ break;
+ case K3bJob::SUCCESS:
+ currentInfoItem->setPixmap( 0, SmallIcon( "ok" ) );
+ break;
+ case K3bJob::INFO:
+ default:
+ currentInfoItem->setPixmap( 0, SmallIcon( "info" ) );
+ }
+
+ // This should scroll down (hopefully!)
+ m_viewInfo->ensureItemVisible( currentInfoItem );
+}
+
+
+void K3bJobProgressDialog::slotFinished( bool success )
+{
+ kdDebug() << "(K3bJobProgressDialog) received finished signal!" << endl;
+
+ m_logFile.close();
+
+ if( success ) {
+ m_pixLabel->setThemePixmap( K3bTheme::PROGRESS_SUCCESS );
+
+ m_labelTask->setText( i18n("Success.") );
+ m_labelTask->setPaletteForegroundColor( Qt::darkGreen );
+ m_labelSubTask->setText( QString::null );
+
+ m_progressPercent->setValue(100);
+ m_progressSubPercent->setValue(100);
+ slotProgress(100);
+
+ // one last time update to be sure no remaining time is displayed anymore
+ slotUpdateTime();
+
+ if( m_osd )
+ m_osd->setText( i18n("Success.") );
+
+ KNotifyClient::event( 0, "SuccessfullyFinished", i18n("Successfully finished.") );
+ }
+ else {
+ m_pixLabel->setThemePixmap( K3bTheme::PROGRESS_FAIL );
+
+ m_labelTask->setPaletteForegroundColor( Qt::red );
+
+ if( m_bCanceled ) {
+ m_labelTask->setText( i18n("Canceled.") );
+ if( m_osd )
+ m_osd->setText( i18n("Canceled.") );
+ }
+ else {
+ m_labelTask->setText( i18n("Error.") );
+ if( m_osd )
+ m_osd->setText( i18n("Error.") );
+ }
+
+ KNotifyClient::event( 0, "FinishedWithError", i18n("Finished with errors") );
+ }
+
+ m_buttonCancel->hide();
+ m_buttonShowDebug->show();
+ m_buttonClose->show();
+ m_timer->stop();
+}
+
+
+void K3bJobProgressDialog::slotCanceled()
+{
+ m_bCanceled = true;
+}
+
+
+void K3bJobProgressDialog::setJob( K3bJob* job )
+{
+ m_bCanceled = false;
+
+ // clear everything
+ m_buttonClose->hide();
+ m_buttonShowDebug->hide();
+ m_buttonCancel->show();
+ m_buttonCancel->setEnabled(true);
+ m_viewInfo->clear();
+ m_progressPercent->setValue(0);
+ m_progressSubPercent->setValue(0);
+ m_labelTask->setText("");
+ m_labelSubTask->setText("");
+ m_labelProcessedSize->setText("");
+ m_labelSubProcessedSize->setText("");
+ m_labelTask->setPaletteForegroundColor( k3bappcore->themeManager()->currentTheme()->foregroundColor() );
+ m_debugOutputMap.clear();
+
+ // disconnect from the former job
+ if( m_job )
+ disconnect( m_job );
+ m_job = job;
+
+ if( job ) {
+
+ // connect to all the shit
+ connect( job, SIGNAL(infoMessage(const QString&,int)), this, SLOT(slotInfoMessage(const QString&,int)) );
+
+ connect( job, SIGNAL(percent(int)), m_progressPercent, SLOT(setValue(int)) );
+ connect( job, SIGNAL(percent(int)), this, SLOT(slotProgress(int)) );
+ connect( job, SIGNAL(subPercent(int)), m_progressSubPercent, SLOT(setValue(int)) );
+
+ connect( job, SIGNAL(processedSubSize(int, int)), this, SLOT(slotProcessedSubSize(int, int)) );
+ connect( job, SIGNAL(processedSize(int, int)), this, SLOT(slotProcessedSize(int, int)) );
+
+ connect( job, SIGNAL(newTask(const QString&)), this, SLOT(slotNewTask(const QString&)) );
+ connect( job, SIGNAL(newSubTask(const QString&)), this, SLOT(slotNewSubTask(const QString&)) );
+ connect( job, SIGNAL(started()), this, SLOT(slotStarted()) );
+ connect( job, SIGNAL(finished(bool)), this, SLOT(slotFinished(bool)) );
+ connect( job, SIGNAL(canceled()), this, SLOT(slotCanceled()) );
+
+ connect( job, SIGNAL(debuggingOutput(const QString&, const QString&)),
+ this, SLOT(slotDebuggingOutput(const QString&, const QString&)) );
+
+ m_labelJob->setText( m_job->jobDescription() );
+ m_labelJobDetails->setText( m_job->jobDetails() );
+
+ setCaption( m_job->jobDescription() );
+
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "Show progress OSD", true ) ) {
+ if( !m_osd )
+ m_osd = new K3bJobProgressOSD( this, "progressosd" );
+ }
+ else
+ delete m_osd;
+
+ if( m_osd ) {
+ m_osd->setText( job->jobDescription() );
+ // FIXME: use a setJob method and let the osd also change the text color to red/green
+ // connect( job, SIGNAL(newTask(const QString&)), m_osd, SLOT(setText(const QString&)) );
+ connect( job, SIGNAL(percent(int)), m_osd, SLOT(setProgress(int)) );
+ }
+ }
+}
+
+
+void K3bJobProgressDialog::slotCancelButtonPressed()
+{
+ if( m_job )
+ if( KMessageBox::questionYesNo( this, i18n("Do you really want to cancel?"), i18n("Cancel Confirmation") ) == KMessageBox::Yes ) {
+ if( m_job ) {
+ m_job->cancel();
+ m_buttonCancel->setDisabled(true); // do not cancel twice
+ }
+ }
+}
+
+
+void K3bJobProgressDialog::slotNewSubTask(const QString& name)
+{
+ m_labelSubTask->setText(name);
+ m_labelSubProcessedSize->setText("");
+ m_progressSubPercent->setValue(0);
+}
+
+void K3bJobProgressDialog::slotNewTask(const QString& name)
+{
+ m_labelTask->setText( name );
+}
+
+
+void K3bJobProgressDialog::slotStarted()
+{
+ d->lastProgress = 0;
+ m_timer->start( 1000 );
+ m_startTime = QTime::currentTime();
+ if( KMainWindow* w = dynamic_cast<KMainWindow*>(kapp->mainWidget()) )
+ m_plainCaption = w->caption();
+
+ m_logFile.open();
+}
+
+
+void K3bJobProgressDialog::slotUpdateTime()
+{
+ int elapsed = m_startTime.secsTo( QTime::currentTime() );
+
+ QString s = i18n("Elapsed time: %1 h").arg( QTime().addSecs(elapsed).toString() );
+ if( d->lastProgress > 0 && d->lastProgress < 100 ) {
+ int rem = m_startTime.secsTo( m_lastProgressUpdateTime ) * (100-d->lastProgress) / d->lastProgress;
+ s += " / " + i18n("Remaining: %1 h").arg( QTime().addSecs(rem).toString() );
+ }
+
+ m_labelElapsedTime->setText( s );
+}
+
+
+void K3bJobProgressDialog::slotDebuggingOutput( const QString& type, const QString& output )
+{
+ m_debugOutputMap[type].append(output);
+ m_logFile.addOutput( type, output );
+}
+
+
+void K3bJobProgressDialog::slotShowDebuggingOutput()
+{
+ K3bDebuggingOutputDialog debugWidget( this );
+ debugWidget.setOutput( m_debugOutputMap );
+ debugWidget.exec();
+}
+
+
+void K3bJobProgressDialog::slotProgress( int percent )
+{
+ if( percent > d->lastProgress ) {
+ d->lastProgress = percent;
+ m_lastProgressUpdateTime = QTime::currentTime();
+ if( KMainWindow* w = dynamic_cast<KMainWindow*>(kapp->mainWidget()) ) {
+ w->setPlainCaption( QString( "(%1%) %2" ).arg(percent).arg(m_plainCaption) );
+ }
+
+ setCaption( QString( "(%1%) %2" ).arg(percent).arg(m_job->jobDescription()) );
+ }
+}
+
+
+void K3bJobProgressDialog::keyPressEvent( QKeyEvent *e )
+{
+ e->accept();
+
+ switch ( e->key() ) {
+ case Key_Enter:
+ case Key_Return:
+ // if the process finished this closes the dialog
+ if( m_buttonClose->isVisible() )
+ close();
+ break;
+ case Key_Escape:
+ // simulate button clicks
+ if( m_buttonCancel->isVisible() && m_buttonCancel->isEnabled() )
+ slotCancelButtonPressed();
+ else if( !m_buttonCancel->isVisible() )
+ close();
+ break;
+ default:
+ // nothing
+ break;
+ }
+}
+
+
+QSize K3bJobProgressDialog::sizeHint() const
+{
+ QSize s = layout()->totalSizeHint();
+ if( s.width() < s.height() )
+ s.setWidth( s.height() );
+ return s;
+}
+
+
+int K3bJobProgressDialog::startJob( K3bJob* job )
+{
+ if( job ) {
+ setJob( job );
+ k3bappcore->jobInterface()->setJob( job );
+ }
+ else if( !m_job ) {
+ kdError() << "(K3bJobProgressDialog) null job!" << endl;
+ return -1;
+ }
+
+ // the following code is mainly taken from QDialog::exec
+
+ if ( in_loop ) {
+ kdError() << "(K3bJobProgressDialog::startJob) Recursive call detected." << endl;
+ return -1;
+ }
+
+ bool destructiveClose = testWFlags( WDestructiveClose );
+ clearWFlags( WDestructiveClose );
+
+ bool wasShowModal = testWFlags( WShowModal );
+ setWFlags( WShowModal );
+ setResult( 0 );
+
+ show();
+
+ // start the job after showing the dialog
+ m_job->start();
+
+ in_loop = true;
+ QApplication::eventLoop()->enterLoop();
+
+ if ( !wasShowModal )
+ clearWFlags( WShowModal );
+
+ int res = result();
+
+ if ( destructiveClose )
+ delete this;
+
+ return res;
+}
+
+
+void K3bJobProgressDialog::hide()
+{
+ // we need to reimplement this since
+ // QDialog does not know if we are in a loop from startJob
+
+ if ( isHidden() )
+ return;
+
+ KDialog::hide();
+
+ if ( in_loop ) {
+ in_loop = FALSE;
+ QApplication::eventLoop()->exitLoop();
+ }
+}
+
+
+int K3bJobProgressDialog::waitForMedia( K3bDevice::Device* device,
+ int mediaState,
+ int mediaType,
+ const QString& message )
+{
+ return K3bEmptyDiscWaiter::wait( device, mediaState, mediaType, message, this );
+}
+
+
+bool K3bJobProgressDialog::questionYesNo( const QString& text,
+ const QString& caption,
+ const QString& yesText,
+ const QString& noText )
+{
+ return ( KMessageBox::questionYesNo( this,
+ text,
+ caption,
+ yesText.isEmpty() ? KStdGuiItem::yes() : KGuiItem(yesText),
+ noText.isEmpty() ? KStdGuiItem::no() : KGuiItem(noText) ) == KMessageBox::Yes );
+}
+
+
+void K3bJobProgressDialog::blockingInformation( const QString& text,
+ const QString& caption )
+{
+ KMessageBox::information( this, text, caption );
+}
+
+
+void K3bJobProgressDialog::slotThemeChanged()
+{
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ static_cast<QWidget*>(child( "frame4" ))->setPaletteBackgroundColor( theme->backgroundColor() );
+ static_cast<QWidget*>(child( "frame4" ))->setPaletteForegroundColor( theme->backgroundColor() );
+ static_cast<QWidget*>(child( "frame5" ))->setPaletteBackgroundColor( theme->backgroundColor() );
+ static_cast<QWidget*>(child( "frame5" ))->setPaletteForegroundColor( theme->backgroundColor() );
+ static_cast<QWidget*>(child( "progressHeaderFrame" ))->setPaletteBackgroundColor( theme->backgroundColor() );
+ static_cast<QWidget*>(child( "progressHeaderFrame" ))->setPaletteForegroundColor( theme->backgroundColor() );
+ static_cast<QWidget*>(child( "headerFrame" ))->setPaletteBackgroundColor( theme->backgroundColor() );
+ static_cast<QWidget*>(child( "headerFrame" ))->setPaletteForegroundColor( theme->backgroundColor() );
+ }
+}
+
+#include "k3bjobprogressdialog.moc"
diff --git a/src/k3bjobprogressdialog.h b/src/k3bjobprogressdialog.h
new file mode 100644
index 0000000..5bc1af2
--- /dev/null
+++ b/src/k3bjobprogressdialog.h
@@ -0,0 +1,173 @@
+/*
+ *
+ * $Id: k3bjobprogressdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_JOB_PROGRESSDIALOG_H_
+#define _K3B_JOB_PROGRESSDIALOG_H_
+
+#include <kdialog.h>
+
+#include "k3bdebuggingoutputfile.h"
+
+#include <k3bjobhandler.h>
+
+#include <qdatetime.h>
+#include <qfile.h>
+
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class KListView;
+class QFrame;
+class QGroupBox;
+class QLabel;
+class QListViewItem;
+class KProgress;
+class QPushButton;
+class QTimer;
+class K3bJob;
+class KCutLabel;
+class QCloseEvent;
+class QGridLayout;
+class QKeyEvent;
+class K3bJobProgressOSD;
+class K3bThemedLabel;
+
+
+class K3bJobProgressDialog : public KDialog, public K3bJobHandler
+{
+ Q_OBJECT
+
+ public:
+ K3bJobProgressDialog( QWidget* parent = 0,
+ const char* name = 0,
+ bool showSubProgress = true,
+ bool modal = FALSE,
+ WFlags fl = 0 );
+ virtual ~K3bJobProgressDialog();
+
+ virtual void setJob( K3bJob* job );
+ void setExtraInfo( QWidget *extra );
+
+ /**
+ * reimplemented for internal reasons
+ */
+ void show();
+
+ /**
+ * reimplemented for internal reasons
+ */
+ void hide();
+
+ /**
+ * This will show the dialog and then start the given job or
+ * if job == 0 the job set with setJob
+ * Use instead of exec()
+ */
+ int startJob( K3bJob* job = 0 );
+
+ QSize sizeHint() const;
+
+ /**
+ * @reimplemented from K3bJobHandler
+ */
+ int waitForMedia( K3bDevice::Device*,
+ int mediaState = K3bDevice::STATE_EMPTY,
+ int mediaType = K3bDevice::MEDIA_WRITABLE_CD,
+ const QString& message = QString::null );
+
+ /**
+ * @reimplemented from K3bJobHandler
+ */
+ bool questionYesNo( const QString& text,
+ const QString& caption = QString::null,
+ const QString& yesText = QString::null,
+ const QString& noText = QString::null );
+
+ /**
+ * reimplemented from K3bJobHandler
+ */
+ void blockingInformation( const QString& text,
+ const QString& caption = QString::null );
+
+ protected slots:
+ virtual void slotProcessedSize( int processed, int size );
+ virtual void slotProcessedSubSize( int processed, int size );
+ virtual void slotInfoMessage( const QString& infoString, int type );
+ virtual void slotDebuggingOutput( const QString&, const QString& );
+ virtual void slotNewSubTask(const QString& name);
+ virtual void slotNewTask(const QString& name);
+ virtual void slotFinished(bool);
+ virtual void slotCanceled();
+ virtual void slotStarted();
+
+
+ void slotCancelButtonPressed();
+ void slotUpdateTime();
+ void slotShowDebuggingOutput();
+
+ void slotProgress( int );
+
+ virtual void slotThemeChanged();
+
+ protected:
+ void closeEvent( QCloseEvent* );
+ void keyPressEvent( QKeyEvent* e );
+
+ void setupGUI();
+ void setupConnections();
+
+ K3bThemedLabel* m_labelJob;
+ K3bThemedLabel* m_labelJobDetails;
+ KListView* m_viewInfo;
+ K3bThemedLabel* m_labelTask;
+ K3bThemedLabel* m_labelElapsedTime;
+ KCutLabel* m_labelSubTask;
+ QLabel* m_labelSubProcessedSize;
+ KProgress* m_progressSubPercent;
+ QLabel* m_labelProcessedSize;
+ KProgress* m_progressPercent;
+ QFrame* m_frameExtraInfo;
+ QPushButton* m_buttonCancel;
+ QPushButton* m_buttonClose;
+ QPushButton* m_buttonShowDebug;
+ K3bThemedLabel* m_pixLabel;
+
+ QGridLayout* m_frameExtraInfoLayout;
+
+ private:
+ class Private;
+ Private* d;
+
+ K3bJob* m_job;
+ QTimer* m_timer;
+ QTime m_startTime;
+ QTime m_lastProgressUpdateTime;
+
+ K3bDebuggingOutputFile m_logFile;
+
+ QMap<QString, QStringList> m_debugOutputMap;
+
+ bool m_bCanceled;
+
+ QString m_plainCaption;
+
+ bool in_loop;
+
+ K3bJobProgressOSD* m_osd;
+};
+
+
+#endif
diff --git a/src/k3bjobprogressosd.cpp b/src/k3bjobprogressosd.cpp
new file mode 100644
index 0000000..0797c3a
--- /dev/null
+++ b/src/k3bjobprogressosd.cpp
@@ -0,0 +1,303 @@
+/*
+ *
+ * $Id: k3bjobprogressosd.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bjobprogressosd.h"
+
+#include <k3bthememanager.h>
+#include <k3bapplication.h>
+
+#include <kwin.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kcursor.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qapplication.h>
+
+#include <X11/Xlib.h>
+
+
+K3bJobProgressOSD::K3bJobProgressOSD( QWidget* parent, const char* name )
+ : QWidget( parent, name, WType_TopLevel | WNoAutoErase | WStyle_Customize | WX11BypassWM | WStyle_StaysOnTop ),
+ m_dirty(true),
+ m_progress(0),
+ m_dragging(false),
+ m_screen(0),
+ m_position(s_outerMargin, s_outerMargin)
+{
+ setFocusPolicy( NoFocus );
+ setBackgroundMode( NoBackground );
+
+ // dummy size
+ resize( 20, 20 );
+
+ // make sure we are always visible
+ KWin::setOnAllDesktops( winId(), true );
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()),
+ this, SLOT(refresh()) );
+ connect( kapp, SIGNAL(appearanceChanged()),
+ this, SLOT(refresh()) );
+}
+
+
+K3bJobProgressOSD::~K3bJobProgressOSD()
+{
+}
+
+
+void K3bJobProgressOSD::show()
+{
+ // start with 0 progress
+ setProgress(0);
+
+ if( m_dirty )
+ renderOSD();
+
+ QWidget::show();
+}
+
+
+void K3bJobProgressOSD::setText( const QString& text )
+{
+ if( m_text != text ) {
+ m_text = text;
+ refresh();
+ }
+}
+
+
+void K3bJobProgressOSD::setProgress( int p )
+{
+ if( m_progress != p ) {
+ m_progress = p;
+ refresh();
+ }
+}
+
+
+void K3bJobProgressOSD::setPosition( const QPoint& p )
+{
+ m_position = p;
+ reposition();
+}
+
+
+void K3bJobProgressOSD::refresh()
+{
+ if( isVisible() )
+ renderOSD();
+ else
+ m_dirty = true;
+}
+
+
+void K3bJobProgressOSD::renderOSD()
+{
+ // ----------------------------------------
+ // | Copying CD |
+ // | K3B ========== 40% |
+ // | |
+ // ----------------------------------------
+
+ // calculate needed size
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ QPixmap icon = KGlobal::iconLoader()->loadIcon( "k3b", KIcon::NoGroup, 32 );
+ int margin = 10;
+ int textWidth = fontMetrics().width( m_text );
+
+ // do not change the size every time the text changes, just in case we are too small
+ QSize newSize( QMAX( QMAX( 2*margin + icon.width() + margin + textWidth, 100 ), width() ),
+ QMAX( 2*margin + icon.height(), 2*margin + fontMetrics().height()*2 ) );
+
+ m_osdBuffer.resize( newSize );
+ QPainter p( &m_osdBuffer );
+
+ p.setPen( theme->foregroundColor() );
+
+ // draw the background and the frame
+ QRect thisRect( 0, 0, newSize.width(), newSize.height() );
+ p.fillRect( thisRect, theme->backgroundColor() );
+ p.drawRect( thisRect );
+
+ // draw the k3b icon
+ p.drawPixmap( margin, (newSize.height()-icon.height())/2, icon );
+
+ // draw the text
+ QSize textSize = fontMetrics().size( 0, m_text );
+ int textX = 2*margin + icon.width();
+ int textY = margin + fontMetrics().ascent();
+ p.drawText( textX, textY, m_text );
+
+ // draw the progress
+ textY += fontMetrics().descent() + 4;
+ QRect progressRect( textX, textY, newSize.width()-textX-margin, newSize.height()-textY-margin );
+ p.drawRect( progressRect );
+ progressRect.setWidth( m_progress > 0 ? m_progress*progressRect.width()/100 : 0 );
+ p.fillRect( progressRect, theme->foregroundColor() );
+
+ // reposition the osd
+ reposition( newSize );
+
+ m_dirty = false;
+
+ update();
+ }
+}
+
+
+void K3bJobProgressOSD::setScreen( int screen )
+{
+ const int n = QApplication::desktop()->numScreens();
+ m_screen = (screen >= n) ? n-1 : screen;
+ reposition();
+}
+
+
+void K3bJobProgressOSD::reposition( QSize newSize )
+{
+ if( !newSize.isValid() )
+ newSize = size();
+
+ QPoint newPos = m_position;
+ const QRect& screen = QApplication::desktop()->screenGeometry( m_screen );
+
+ // now to properly resize if put into one of the corners we interpret the position
+ // depending on the quadrant
+ int midH = screen.width()/2;
+ int midV = screen.height()/2;
+ if( newPos.x() > midH )
+ newPos.rx() -= newSize.width();
+ if( newPos.y() > midV )
+ newPos.ry() -= newSize.height();
+
+ newPos = fixupPosition( newPos );
+
+ // correct for screen position
+ newPos += screen.topLeft();
+
+ // ensure we are painted before we move
+ if( isVisible() )
+ paintEvent( 0 );
+
+ // fancy X11 move+resize, reduces visual artifacts
+ XMoveResizeWindow( x11Display(), winId(), newPos.x(), newPos.y(), newSize.width(), newSize.height() );
+}
+
+
+void K3bJobProgressOSD::paintEvent( QPaintEvent* )
+{
+ bitBlt( this, 0, 0, &m_osdBuffer );
+}
+
+
+void K3bJobProgressOSD::mousePressEvent( QMouseEvent* e )
+{
+ m_dragOffset = e->pos();
+
+ if( e->button() == LeftButton && !m_dragging ) {
+ grabMouse( KCursor::sizeAllCursor() );
+ m_dragging = true;
+ }
+ else if( e->button() == RightButton ) {
+ KPopupMenu m;
+ if( m.insertItem( i18n("Hide OSD") ) == m.exec( e->globalPos() ) )
+ hide();
+ }
+}
+
+
+void K3bJobProgressOSD::mouseReleaseEvent( QMouseEvent* )
+{
+ if( m_dragging ) {
+ m_dragging = false;
+ releaseMouse();
+ }
+}
+
+
+void K3bJobProgressOSD::mouseMoveEvent( QMouseEvent* e )
+{
+ if( m_dragging && this == mouseGrabber() ) {
+
+ // check if the osd has been dragged out of the current screen
+ int currentScreen = QApplication::desktop()->screenNumber( e->globalPos() );
+ if( currentScreen != -1 )
+ m_screen = currentScreen;
+
+ const QRect& screen = QApplication::desktop()->screenGeometry( m_screen );
+
+ // make sure the position is valid
+ m_position = fixupPosition( e->globalPos() - m_dragOffset - screen.topLeft() );
+
+ // move us to the new position
+ move( m_position );
+
+ // fix the position
+ int midH = screen.width()/2;
+ int midV = screen.height()/2;
+ if( m_position.x() + width() > midH )
+ m_position.rx() += width();
+ if( m_position.y() + height() > midV )
+ m_position.ry() += height();
+ }
+}
+
+
+QPoint K3bJobProgressOSD::fixupPosition( const QPoint& pp )
+{
+ QPoint p(pp);
+ const QRect& screen = QApplication::desktop()->screenGeometry( m_screen );
+ int maxY = screen.height() - height() - s_outerMargin;
+ int maxX = screen.width() - width() - s_outerMargin;
+
+ if( p.y() < s_outerMargin )
+ p.ry() = s_outerMargin;
+ else if( p.y() > maxY )
+ p.ry() = maxY;
+
+ if( p.x() < s_outerMargin )
+ p.rx() = s_outerMargin;
+ else if( p.x() > maxX )
+ p.rx() = screen.width() - s_outerMargin - width();
+
+ p += screen.topLeft();
+
+ return p;
+}
+
+
+void K3bJobProgressOSD::readSettings( KConfigBase* c )
+{
+ KConfigGroup grp( c, "OSD Position" );
+
+ setPosition( grp.readPointEntry( "Position", 0 ) );
+ setScreen( grp.readNumEntry( "Screen", 0 ) );
+}
+
+
+void K3bJobProgressOSD::saveSettings( KConfigBase* c )
+{
+ KConfigGroup grp( c, "OSD Position" );
+
+ grp.writeEntry( "Position", m_position );
+ grp.writeEntry( "Screen", m_screen );
+}
+
+#include "k3bjobprogressosd.moc"
diff --git a/src/k3bjobprogressosd.h b/src/k3bjobprogressosd.h
new file mode 100644
index 0000000..1bb9221
--- /dev/null
+++ b/src/k3bjobprogressosd.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * $Id: k3bjobprogressosd.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_JOB_PROGRESS_OSD_H_
+#define _K3B_JOB_PROGRESS_OSD_H_
+
+#include <qwidget.h>
+#include <qpixmap.h>
+
+class QPaintEvent;
+class QMouseEvent;
+class KConfigBase;
+
+/**
+ * An OSD displaying a text and a progress bar.
+ *
+ * Insprired by Amarok's OSD (I also took a bit of their code. :)
+ */
+class K3bJobProgressOSD : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bJobProgressOSD( QWidget* parent = 0, const char* name = 0 );
+ ~K3bJobProgressOSD();
+
+ int screen() const { return m_screen; }
+ const QPoint& position() const { return m_position; }
+
+ void readSettings( KConfigBase* );
+ void saveSettings( KConfigBase* );
+
+ public slots:
+ void setScreen( int );
+ void setText( const QString& );
+ void setProgress( int );
+
+ /**
+ * The position refers to one of the corners of the widget
+ * regarding on the value of the x and y coordinate.
+ * If for example the x coordinate is bigger than half the screen
+ * width it refers to the left edge of the widget.
+ */
+ void setPosition( const QPoint& );
+
+ void show();
+
+ protected:
+ void paintEvent( QPaintEvent* );
+ void mousePressEvent( QMouseEvent* );
+ void mouseReleaseEvent( QMouseEvent* );
+ void mouseMoveEvent( QMouseEvent* );
+ void renderOSD();
+ void reposition( QSize size = QSize() );
+
+ protected slots:
+ void refresh();
+
+ private:
+ /**
+ * Ensure that the position is inside m_screen
+ */
+ QPoint fixupPosition( const QPoint& p );
+ static const int s_outerMargin = 15;
+
+ QPixmap m_osdBuffer;
+ bool m_dirty;
+ QString m_text;
+ int m_progress;
+ bool m_dragging;
+ QPoint m_dragOffset;
+ int m_screen;
+ QPoint m_position;
+};
+
+#endif
diff --git a/src/k3blsofwrapper.cpp b/src/k3blsofwrapper.cpp
new file mode 100644
index 0000000..56d5d5b
--- /dev/null
+++ b/src/k3blsofwrapper.cpp
@@ -0,0 +1,108 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3blsofwrapper.h"
+
+#include <k3bdevice.h>
+#include <k3bprocess.h>
+#include <k3bglobals.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+static K3bLsofWrapper::Process createProcess( const QString& name, int pid )
+{
+ K3bLsofWrapper::Process p;
+ p.name = name;
+ p.pid = pid;
+ return p;
+}
+
+
+class K3bLsofWrapper::Private
+{
+public:
+ QValueList<Process> apps;
+ QString lsofBin;
+};
+
+
+K3bLsofWrapper::K3bLsofWrapper()
+{
+ d = new Private;
+}
+
+
+K3bLsofWrapper::~K3bLsofWrapper()
+{
+ delete d;
+}
+
+
+bool K3bLsofWrapper::checkDevice( K3bDevice::Device* dev )
+{
+ d->apps.clear();
+
+ if( !findLsofExecutable() )
+ return false;
+
+ // run lsof
+ KProcess p;
+ K3bProcessOutputCollector out( &p );
+
+ //
+ // We use the following output form:
+ // p<PID>
+ // c<COMMAND_NAME>
+ //
+ p << d->lsofBin << "-Fpc" << dev->blockDeviceName();
+
+ if( !p.start( KProcess::Block, KProcess::Stdout ) )
+ return false;
+
+ //
+ // now process its output
+ QStringList l = QStringList::split( "\n", out.output() );
+ for( QStringList::iterator it = l.begin(); it != l.end(); ++it ) {
+ int pid = (*it).mid(1).toInt();
+ QString app = (*(++it)).mid(1);
+
+ kdDebug() << "(K3bLsofWrapper) matched: app: " << app << " pid: " << pid << endl;
+
+ // we don't care about ourselves using the device ;)
+ if( pid != (int)::getpid() )
+ d->apps.append( createProcess( app, pid ) );
+ }
+
+ return true;
+}
+
+
+const QValueList<K3bLsofWrapper::Process>& K3bLsofWrapper::usingApplications() const
+{
+ return d->apps;
+}
+
+
+bool K3bLsofWrapper::findLsofExecutable()
+{
+ if( d->lsofBin.isEmpty() )
+ d->lsofBin = K3b::findExe( "lsof" );
+
+ return !d->lsofBin.isEmpty();
+}
diff --git a/src/k3blsofwrapper.h b/src/k3blsofwrapper.h
new file mode 100644
index 0000000..8ab11dc
--- /dev/null
+++ b/src/k3blsofwrapper.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_LSOF_WRAPPER_H_
+#define _K3B_LSOF_WRAPPER_H_
+
+#include <qvaluelist.h>
+
+namespace K3bDevice {
+ class Device;
+}
+
+
+class K3bLsofWrapper
+{
+ public:
+ K3bLsofWrapper();
+ ~K3bLsofWrapper();
+
+ /**
+ * Checks which processes currently have an open file descriptor
+ * to the device.
+ *
+ * \return true if lsof was successfully called.
+ */
+ bool checkDevice( K3bDevice::Device* );
+
+ struct Process {
+ QString name;
+ int pid;
+ };
+
+ /**
+ * \return A list of all applications that had an open
+ * handle on the device used in the last successful call
+ * to checkDevice.
+ */
+ const QValueList<Process>& usingApplications() const;
+
+ private:
+ bool findLsofExecutable();
+
+ class Private;
+ Private* d;
+};
+
+#endif
+
diff --git a/src/k3blsofwrapperdialog.cpp b/src/k3blsofwrapperdialog.cpp
new file mode 100644
index 0000000..e081e38
--- /dev/null
+++ b/src/k3blsofwrapperdialog.cpp
@@ -0,0 +1,127 @@
+/*
+ *
+ * $Id: k3bapplication.cpp 567271 2006-07-28 13:19:18Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3blsofwrapperdialog.h"
+#include "k3blsofwrapper.h"
+#include <k3brichtextlabel.h>
+
+#include <k3bdevice.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <qpushbutton.h>
+
+#include <sys/types.h>
+#include <signal.h>
+
+
+static QString joinProcessNames( const QValueList<K3bLsofWrapper::Process>& apps )
+{
+ QStringList l;
+ for( QValueList<K3bLsofWrapper::Process>::const_iterator it = apps.begin();
+ it != apps.end(); ++it )
+ l.append( (*it).name );
+ return l.join( ", " );
+}
+
+
+K3bLsofWrapperDialog::K3bLsofWrapperDialog( QWidget* parent )
+ : KDialogBase( KDialogBase::Swallow,
+ i18n("Device in use"),
+ Close|User1|User2,
+ Close,
+ parent,
+ 0,
+ true,
+ true,
+ KGuiItem( i18n("Quit the other applications") ),
+ KGuiItem( i18n("Check again") ) )
+{
+ setButtonText( Close, i18n("Continue") );
+
+ m_label = new K3bRichTextLabel( this );
+ setMainWidget( m_label );
+
+ connect( this, SIGNAL(user1Clicked()), SLOT(slotQuitOtherApps()) );
+ connect( this, SIGNAL(user2Clicked()), SLOT(slotCheckDevice()) );
+}
+
+
+K3bLsofWrapperDialog::~K3bLsofWrapperDialog()
+{
+}
+
+
+bool K3bLsofWrapperDialog::slotCheckDevice()
+{
+ K3bLsofWrapper lsof;
+ if( lsof.checkDevice( m_device ) ) {
+ const QValueList<K3bLsofWrapper::Process>& apps = lsof.usingApplications();
+ if( apps.count() > 0 ) {
+ m_label->setText( i18n("<p>Device <b>'%1'</b> is already in use by other applications "
+ "(<em>%2</em>)."
+ "<p>It is highly recommended to quit those before continuing. "
+ "Otherwise K3b might not be able to fully access the device."
+ "<p><em>Hint: Sometimes shutting down an application does not "
+ "happen instantly. In that case you might have to use the '%3' "
+ "button.")
+ .arg( m_device->vendor() + " - " + m_device->description() )
+ .arg( joinProcessNames(apps) )
+ .arg( actionButton( User2 )->text() ) );
+ return true;
+ }
+ }
+
+ // once no apps are running we can close the dialog
+ close();
+
+ return false;
+}
+
+
+void K3bLsofWrapperDialog::slotQuitOtherApps()
+{
+ K3bLsofWrapper lsof;
+ if( lsof.checkDevice( m_device ) ) {
+ const QValueList<K3bLsofWrapper::Process>& apps = lsof.usingApplications();
+ if( apps.count() > 0 ) {
+ if( KMessageBox::warningYesNo( this,
+ i18n("<p>Do you really want K3b to kill the following processes: <em>")
+ + joinProcessNames(apps) ) == KMessageBox::Yes ) {
+ for( QValueList<K3bLsofWrapper::Process>::const_iterator it = apps.begin();
+ it != apps.end(); ++it )
+ ::kill( (*it).pid, SIGTERM );
+ }
+ else
+ return;
+ }
+ }
+
+ // after quitting the other applications recheck for running ones
+ slotCheckDevice();
+}
+
+
+void K3bLsofWrapperDialog::checkDevice( K3bDevice::Device* dev, QWidget* parent )
+{
+ K3bLsofWrapperDialog dlg( parent );
+ dlg.m_device = dev;
+ if( dlg.slotCheckDevice() )
+ dlg.exec();
+}
+
+#include "k3blsofwrapperdialog.moc"
diff --git a/src/k3blsofwrapperdialog.h b/src/k3blsofwrapperdialog.h
new file mode 100644
index 0000000..e00da0b
--- /dev/null
+++ b/src/k3blsofwrapperdialog.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * $Id: k3bapplication.cpp 567271 2006-07-28 13:19:18Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_LSOF_WRAPPER_DIALOG_H_
+#define _K3B_LSOF_WRAPPER_DIALOG_H_
+
+#include <kdialogbase.h>
+
+class K3bRichTextLabel;
+namespace K3bDevice {
+ class Device;
+}
+
+class K3bLsofWrapperDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ ~K3bLsofWrapperDialog();
+
+ /**
+ * Check if other applications are currently using the device and if so
+ * warn the user and provide a quick solution to shut down these other
+ * applications.
+ *
+ * If the device is not in use this method simply returns.
+ */
+ static void checkDevice( K3bDevice::Device* dev, QWidget* parent = 0 );
+
+ private slots:
+ bool slotCheckDevice();
+ void slotQuitOtherApps();
+
+ private:
+ K3bLsofWrapperDialog( QWidget* parent );
+
+ K3bDevice::Device* m_device;
+ K3bRichTextLabel* m_label;
+};
+
+#endif
diff --git a/src/k3bmediacache.cpp b/src/k3bmediacache.cpp
new file mode 100644
index 0000000..fa9f51b
--- /dev/null
+++ b/src/k3bmediacache.cpp
@@ -0,0 +1,373 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmediacache.h"
+#include "k3bmedium.h"
+
+#include <k3bdevicemanager.h>
+#include <k3bdeviceglobals.h>
+#include <k3bscsicommand.h>
+#include <k3bcore.h>
+
+#include <kdebug.h>
+#include <kapplication.h>
+#include <klocale.h>
+
+#include <qthread.h>
+#include <qmutex.h>
+#include <qevent.h>
+
+
+// ////////////////////////////////////////////////////////////////////////////////
+// MEDIA CACHE SUPPORT CLASSES
+// ////////////////////////////////////////////////////////////////////////////////
+
+class K3bMediaCache::MediaChangeEvent : public QCustomEvent
+{
+public:
+ static const int EventCode;
+
+ MediaChangeEvent( K3bDevice::Device* dev )
+ : QCustomEvent( EventCode ),
+ m_device( dev ) {}
+
+ K3bDevice::Device* device() const { return m_device; }
+
+private:
+ K3bDevice::Device* m_device;
+};
+
+const int K3bMediaCache::MediaChangeEvent::EventCode = QEvent::User + 22;
+
+
+class K3bMediaCache::DeviceEntry
+{
+public:
+ DeviceEntry( K3bMediaCache* cache, K3bDevice::Device* dev );
+ ~DeviceEntry();
+
+ K3bMedium medium;
+
+ int blockedId;
+
+ QMutex mutex;
+
+ K3bMediaCache::PollThread* thread;
+
+ K3bMediaCache* cache;
+
+ void clear() {
+ medium.reset();
+ }
+};
+
+
+class K3bMediaCache::PollThread : public QThread
+{
+public:
+ PollThread( K3bMediaCache::DeviceEntry* de )
+ : m_deviceEntry( de ) {}
+
+protected:
+ void run();
+
+private:
+ K3bMediaCache::DeviceEntry* m_deviceEntry;
+};
+
+
+
+
+// ////////////////////////////////////////////////////////////////////////////////
+// MEDIA CACHE SUPPORT CLASSES IMPL
+// ////////////////////////////////////////////////////////////////////////////////
+
+
+K3bMediaCache::DeviceEntry::DeviceEntry( K3bMediaCache* c, K3bDevice::Device* dev )
+ : medium(dev),
+ blockedId(0),
+ cache(c)
+{
+ thread = new K3bMediaCache::PollThread( this );
+}
+
+
+K3bMediaCache::DeviceEntry::~DeviceEntry()
+{
+ delete thread;
+}
+
+
+void K3bMediaCache::PollThread::run()
+{
+ while( m_deviceEntry->blockedId == 0 ) {
+ bool unitReady = m_deviceEntry->medium.device()->testUnitReady();
+ bool mediumCached = ( m_deviceEntry->medium.diskInfo().diskState() != K3bDevice::STATE_NO_MEDIA );
+
+ //
+ // we only get the other information in case the disk state changed or if we have
+ // no info at all (FIXME: there are drives around that are not able to provide a proper
+ // disk state)
+ //
+ if( m_deviceEntry->medium.diskInfo().diskState() == K3bDevice::STATE_UNKNOWN ||
+ unitReady != mediumCached ) {
+
+ //
+ // The medium has changed. We need to update the information.
+ //
+ K3bMedium m( m_deviceEntry->medium.device() );
+ m.update();
+
+ // block the info since it is not valid anymore
+ m_deviceEntry->mutex.lock();
+
+ // m_deviceEntry->medium.update();
+ m_deviceEntry->medium = m;
+
+ //
+ // inform the media cache about the media change
+ //
+ if( m_deviceEntry->blockedId == 0 )
+ QApplication::postEvent( m_deviceEntry->cache,
+ new K3bMediaCache::MediaChangeEvent( m_deviceEntry->medium.device() ) );
+
+ // the information is valid. let the info go.
+ m_deviceEntry->mutex.unlock();
+ }
+
+ if( m_deviceEntry->blockedId == 0 )
+ QThread::sleep( 2 );
+ }
+}
+
+
+
+
+
+// ////////////////////////////////////////////////////////////////////////////////
+// MEDIA CACHE IMPL
+// ////////////////////////////////////////////////////////////////////////////////
+
+
+K3bMediaCache::K3bMediaCache( QObject* parent )
+ : QObject( parent )
+{
+}
+
+
+K3bMediaCache::~K3bMediaCache()
+{
+ clearDeviceList();
+}
+
+
+int K3bMediaCache::blockDevice( K3bDevice::Device* dev )
+{
+ DeviceEntry* e = findDeviceEntry( dev );
+ if( e ) {
+ if( e->blockedId )
+ return -1;
+ else {
+ // block the information
+ e->mutex.lock();
+
+ // create (hopefully) unique id
+ e->blockedId = KApplication::random();
+
+ // let the info go
+ e->mutex.unlock();
+
+ // wait for the thread to stop
+ e->thread->wait();
+
+ return e->blockedId;
+ }
+ }
+ else
+ return -1;
+}
+
+
+bool K3bMediaCache::unblockDevice( K3bDevice::Device* dev, int id )
+{
+ DeviceEntry* e = findDeviceEntry( dev );
+ if( e && e->blockedId && e->blockedId == id ) {
+ e->blockedId = 0;
+
+ // for security reasons we emit no medium signal at this point
+ // otherwise a job might resuse the old medium information
+ e->medium = K3bMedium( dev );
+ emit mediumChanged( dev );
+
+ // restart the poll thread
+ e->thread->start();
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+bool K3bMediaCache::isBlocked( K3bDevice::Device* dev )
+{
+ if( DeviceEntry* e = findDeviceEntry( dev ) )
+ return ( e->blockedId != 0 );
+ else
+ return false;
+}
+
+
+K3bMedium K3bMediaCache::medium( K3bDevice::Device* dev )
+{
+ if( DeviceEntry* e = findDeviceEntry( dev ) ) {
+ e->mutex.lock();
+ K3bMedium m = e->medium;
+ e->mutex.unlock();
+ return m;
+ }
+ else
+ return K3bMedium();
+}
+
+
+K3bDevice::DiskInfo K3bMediaCache::diskInfo( K3bDevice::Device* dev )
+{
+ if( DeviceEntry* e = findDeviceEntry( dev ) ) {
+ e->mutex.lock();
+ K3bDevice::DiskInfo di = e->medium.diskInfo();
+ e->mutex.unlock();
+ return di;
+ }
+ else
+ return K3bDevice::DiskInfo();
+}
+
+
+K3bDevice::Toc K3bMediaCache::toc( K3bDevice::Device* dev )
+{
+ if( DeviceEntry* e = findDeviceEntry( dev ) ) {
+ e->mutex.lock();
+ K3bDevice::Toc toc = e->medium.toc();
+ e->mutex.unlock();
+ return toc;
+ }
+ else
+ return K3bDevice::Toc();
+}
+
+
+K3bDevice::CdText K3bMediaCache::cdText( K3bDevice::Device* dev )
+{
+ if( DeviceEntry* e = findDeviceEntry( dev ) ) {
+ e->mutex.lock();
+ K3bDevice::CdText cdt = e->medium.cdText();
+ e->mutex.unlock();
+ return cdt;
+ }
+ else
+ return K3bDevice::CdText();
+}
+
+
+QValueList<int> K3bMediaCache::writingSpeeds( K3bDevice::Device* dev )
+{
+ if( DeviceEntry* e = findDeviceEntry( dev ) ) {
+ e->mutex.lock();
+ QValueList<int> ws = e->medium.writingSpeeds();
+ e->mutex.unlock();
+ return ws;
+ }
+ else
+ return QValueList<int>();
+}
+
+
+QString K3bMediaCache::mediumString( K3bDevice::Device* device, bool useContent )
+{
+ if( DeviceEntry* e = findDeviceEntry( device ) ) {
+ return e->medium.shortString( useContent );
+ }
+ else
+ return QString::null;
+}
+
+
+void K3bMediaCache::clearDeviceList()
+{
+ kdDebug() << k_funcinfo << endl;
+
+ // make all the threads stop
+ for( QMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
+ it != m_deviceMap.end(); ++it ) {
+ it.data()->blockedId = 1;
+ }
+
+ // and remove them
+ for( QMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
+ it != m_deviceMap.end(); ++it ) {
+ kdDebug() << k_funcinfo << " waiting for info thread " << it.key()->blockDeviceName() << " to finish" << endl;
+ it.data()->thread->wait();
+ delete it.data();
+ }
+
+ m_deviceMap.clear();
+}
+
+
+void K3bMediaCache::buildDeviceList( K3bDevice::DeviceManager* dm )
+{
+ // remember blocked ids
+ QMap<K3bDevice::Device*, int> blockedIds;
+ for( QMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
+ it != m_deviceMap.end(); ++it )
+ blockedIds.insert( it.key(), it.data()->blockedId );
+
+ clearDeviceList();
+
+ const QPtrList<K3bDevice::Device>& devices = dm->allDevices();
+ for( QPtrListIterator<K3bDevice::Device> it( devices ); *it; ++it ) {
+ m_deviceMap.insert( *it, new DeviceEntry( this, *it ) );
+ QMap<K3bDevice::Device*, int>::const_iterator bi_it = blockedIds.find( *it );
+ if( bi_it != blockedIds.end() )
+ m_deviceMap[*it]->blockedId = bi_it.data();
+ }
+
+ // start all the polling threads
+ for( QMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
+ it != m_deviceMap.end(); ++it ) {
+ if( !it.data()->blockedId )
+ it.data()->thread->start();
+ }
+}
+
+
+K3bMediaCache::DeviceEntry* K3bMediaCache::findDeviceEntry( K3bDevice::Device* dev )
+{
+ QMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.find( dev );
+ if( it != m_deviceMap.end() )
+ return it.data();
+ else
+ return 0;
+}
+
+
+void K3bMediaCache::customEvent( QCustomEvent* e )
+{
+ if( e->type() == MediaChangeEvent::EventCode )
+ emit mediumChanged( static_cast<MediaChangeEvent*>( e )->device() );
+}
+
+#include "k3bmediacache.moc"
diff --git a/src/k3bmediacache.h b/src/k3bmediacache.h
new file mode 100644
index 0000000..dd0dd0d
--- /dev/null
+++ b/src/k3bmediacache.h
@@ -0,0 +1,148 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_MEDIA_CACHE_H_
+#define _K3B_MEDIA_CACHE_H_
+
+#include <qobject.h>
+
+#include <qvaluelist.h>
+
+#include <k3bdevice.h>
+#include <k3btoc.h>
+#include <k3bcdtext.h>
+#include <k3bdiskinfo.h>
+
+#include "k3bmedium.h"
+
+namespace K3bDevice {
+ class DeviceManager;
+}
+
+class QCustomEvent;
+
+
+/**
+ * The Media Cache does know the status of all devices at all times
+ * (except for blocked devices).
+ *
+ * It should be used to get information about media and device status
+ * instead of the libk3bdevice methods for faster access.
+ *
+ * The Media Cache polls for new information every 2 seconds on all devices
+ * (except for blocked ones) and emits signals in case a device status changed
+ * (for example a media was inserted or removed).
+ *
+ * To start the media caching call buildDeviceList().
+ */
+class K3bMediaCache : public QObject
+{
+ Q_OBJECT
+
+ public:
+ K3bMediaCache( QObject* parent = 0 );
+ ~K3bMediaCache();
+
+ /**
+ * block a device so it will not be polled. This is used
+ * to disable polling on devices that are currently in use
+ * for burning.
+ *
+ * \return A unique id to be used to unblock the device or -1 if the device
+ * is already blocked.
+ */
+ int blockDevice( K3bDevice::Device* dev );
+
+ /**
+ * Unblock a device that has been blocked with block() before.
+ *
+ * \param id The id returned by the previous call to block(). This makes
+ * sure only the one who did the block may unblock the device.
+ *
+ * \return true if dev has been blocked with id before. false otherwise.
+ */
+ bool unblockDevice( K3bDevice::Device* dev, int id );
+
+ bool isBlocked( K3bDevice::Device* dev );
+
+ /**
+ * Read cached medium information.
+ */
+ K3bMedium medium( K3bDevice::Device* dev );
+
+ /**
+ * Read cached disk information.
+ */
+ K3bDevice::DiskInfo diskInfo( K3bDevice::Device* );
+
+ /**
+ * Read cached Table of contents.
+ */
+ K3bDevice::Toc toc( K3bDevice::Device* );
+
+ /**
+ * Read cached CD text from an Audio CD.
+ */
+ K3bDevice::CdText cdText( K3bDevice::Device* );
+
+ /**
+ * Read cached supported writing speeds.
+ */
+ QValueList<int> writingSpeeds( K3bDevice::Device* );
+
+ /**
+ * \see K3bMedium::shortString()
+ */
+ QString mediumString( K3bDevice::Device* device, bool useContent = true );
+
+ signals:
+ /**
+ * Signal emitted whenever a medium changes. That means when a new medium is inserted
+ * or an old one is removed.
+ *
+ * This signal will also be emitted when a previously blocked device becomes unblocked.
+ *
+ * Be aware though that the Media Cache will silently ignore removed devices. That means
+ * once should also listen to K3bDevice::DeviceManager::changed() in case a USB drive or
+ * something similar is removed.
+ */
+ void mediumChanged( K3bDevice::Device* dev );
+
+ public slots:
+ /**
+ * Build the device list and start the polling.
+ * It might make sense to connect this to K3bDevice::DeviceManager::changed()
+ */
+ void buildDeviceList( K3bDevice::DeviceManager* );
+
+ /**
+ * Clear the device list and stop all the polling.
+ * This is also done in the destructor.
+ */
+ void clearDeviceList();
+
+ private:
+ class PollThread;
+ class DeviceEntry;
+ class MediaChangeEvent;
+
+ QMap<K3bDevice::Device*, DeviceEntry*> m_deviceMap;
+
+ DeviceEntry* findDeviceEntry( K3bDevice::Device* );
+ void customEvent( QCustomEvent* );
+};
+
+#endif
diff --git a/src/k3bmediacontentsview.cpp b/src/k3bmediacontentsview.cpp
new file mode 100644
index 0000000..4f42595
--- /dev/null
+++ b/src/k3bmediacontentsview.cpp
@@ -0,0 +1,166 @@
+/*
+ *
+ * $Id: k3bmediacontentsview.cpp 627519 2007-01-26 22:37:51Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmediacontentsview.h"
+
+#include <k3bmediacache.h>
+#include <k3bapplication.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qwidgetstack.h>
+
+
+class K3bMediaContentsView::Private
+{
+public:
+ K3bMedium medium;
+ int supportedMediumContent;
+ int supportedMediumTypes;
+ int supportedMediumStates;
+
+ bool autoReload;
+};
+
+
+K3bMediaContentsView::K3bMediaContentsView( bool withHeader,
+ int mediumContent,
+ int mediumTypes,
+ int mediumState,
+ QWidget* parent,
+ const char* name )
+ : K3bContentsView( withHeader, parent, name )
+{
+ d = new Private;
+ d->supportedMediumContent = mediumContent;
+ d->supportedMediumTypes = mediumTypes;
+ d->supportedMediumStates = mediumState;
+ d->autoReload = true;
+
+ connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3bDevice::Device*)),
+ this, SLOT(slotMediumChanged(K3bDevice::Device*)) );
+}
+
+
+K3bMediaContentsView::~K3bMediaContentsView()
+{
+ delete d;
+}
+
+
+void K3bMediaContentsView::setAutoReload( bool b )
+{
+ d->autoReload = b;
+}
+
+
+int K3bMediaContentsView::supportedMediumContent() const
+{
+ return d->supportedMediumContent;
+}
+
+
+int K3bMediaContentsView::supportedMediumTypes() const
+{
+ return d->supportedMediumTypes;
+}
+
+
+int K3bMediaContentsView::supportedMediumStates() const
+{
+ return d->supportedMediumStates;
+}
+
+
+const K3bMedium& K3bMediaContentsView::medium() const
+{
+ return d->medium;
+}
+
+
+K3bDevice::Device* K3bMediaContentsView::device() const
+{
+ return medium().device();
+}
+
+
+void K3bMediaContentsView::setMedium( const K3bMedium& m )
+{
+ d->medium = m;
+}
+
+
+void K3bMediaContentsView::reload( K3bDevice::Device* dev )
+{
+ reload( k3bappcore->mediaCache()->medium( dev ) );
+}
+
+
+void K3bMediaContentsView::reload( const K3bMedium& m )
+{
+ setMedium( m );
+ reload();
+}
+
+
+void K3bMediaContentsView::reload()
+{
+ enableInteraction( true );
+ reloadMedium();
+}
+
+
+void K3bMediaContentsView::enableInteraction( bool enable )
+{
+ mainWidget()->setEnabled( enable );
+}
+
+
+void K3bMediaContentsView::slotMediumChanged( K3bDevice::Device* dev )
+{
+ // FIXME: derive a K3bContentsStack from QWidgetStack and let it set an active flag
+ // to replace this hack
+ if( QWidgetStack* stack = dynamic_cast<QWidgetStack*>( parentWidget() ) )
+ if( stack->visibleWidget() != this )
+ return;
+
+ if( !d->autoReload /*|| !isActive()*/ )
+ return;
+
+ if( dev == device() ) {
+ K3bMedium m = k3bappcore->mediaCache()->medium( dev );
+
+ // no need to reload if the medium did not change (this is even
+ // important since K3b blocks the devices in action and after
+ // the release they are signalled as changed)
+ if( m == medium() ) {
+ kdDebug() << k_funcinfo << " medium did not change" << endl;
+ enableInteraction( true );
+ }
+ else if( m.content() & supportedMediumContent() &&
+ m.diskInfo().mediaType() & supportedMediumTypes() &&
+ m.diskInfo().diskState() & supportedMediumStates() ) {
+ kdDebug() << k_funcinfo << " new supported medium found" << endl;
+ reload( m );
+ }
+ else {
+ kdDebug() << k_funcinfo << " unsupported medium found" << endl;
+ enableInteraction( false );
+ }
+ }
+}
+
+#include "k3bmediacontentsview.moc"
diff --git a/src/k3bmediacontentsview.h b/src/k3bmediacontentsview.h
new file mode 100644
index 0000000..7e60838
--- /dev/null
+++ b/src/k3bmediacontentsview.h
@@ -0,0 +1,116 @@
+/*
+ *
+ * $Id: k3bmediacontentsview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_MEDIUM_CONTENTS_VIEW_H_
+#define _K3B_MEDIUM_CONTENTS_VIEW_H_
+
+#include "k3bcontentsview.h"
+#include <k3bthememanager.h>
+#include <k3bmedium.h>
+
+class K3bThemedHeader;
+
+
+/**
+ * Abstract class from which all cd views must be derived. The contents view automatically handles medium changes for
+ * the selected device and reloads the contents if a new usable medium is inserted or disables the controls if the
+ * medium is just ejected. For this to work the proper content types have to be set.
+ *
+ * TODO: how about giving this one a KActionCollection so it can handle the toolbar automatically
+ */
+class K3bMediaContentsView : public K3bContentsView
+{
+ Q_OBJECT
+
+ public:
+ virtual ~K3bMediaContentsView();
+
+ const K3bMedium& medium() const;
+
+ /**
+ * Equals medium().device()
+ */
+ K3bDevice::Device* device() const;
+
+ /**
+ * \return A bitwise or of K3bMedium::ContentType which
+ * represents the content types that can be displayed by this
+ * medium view.
+ */
+ int supportedMediumContent() const;
+ int supportedMediumTypes() const;
+ int supportedMediumStates() const;
+
+ public slots:
+ /**
+ * Does some internal stuff and calls reloadMedium.
+ * Normally there is no need to call this manually.
+ */
+ void reload();
+
+ /**
+ * Has the same effect as reload( k3bappcore->mediaCache()->medium( dev ) );
+ */
+ void reload( K3bDevice::Device* dev );
+
+ /**
+ * Has the same effect as setMedium( m ), reload()
+ */
+ void reload( const K3bMedium& m );
+
+ /**
+ * Enable or disable auto reloading when a new medium is inserted.
+ * If enabled (the default) the view will be reloaded if a new usable
+ * (as determined by the supportedXXX methods) medium has been inserted
+ * into the current device.
+ */
+ void setAutoReload( bool b );
+
+ /**
+ * Enable or disable the controls of this view.
+ * The default implementation simply disables the whole window
+ */
+ virtual void enableInteraction( bool enable );
+
+ protected:
+ K3bMediaContentsView( bool withHeader,
+ int mediumContent,
+ int mediumTypes,
+ int mediumState,
+ QWidget* parent = 0,
+ const char* name = 0 );
+
+ /**
+ * Changes the medium without reloading the contents.
+ * Do not use, use reload( const K3bMedium& ) instead.
+ */
+ void setMedium( const K3bMedium& );
+
+ /**
+ * Called by reload. Reimplement to actually display
+ * the contents of the medium.
+ */
+ virtual void reloadMedium() = 0;
+
+ private slots:
+ void slotMediumChanged( K3bDevice::Device* );
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3bmediaselectioncombobox.cpp b/src/k3bmediaselectioncombobox.cpp
new file mode 100644
index 0000000..df51566
--- /dev/null
+++ b/src/k3bmediaselectioncombobox.cpp
@@ -0,0 +1,505 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmediaselectioncombobox.h"
+#include "k3bapplication.h"
+#include "k3bmediacache.h"
+
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bdeviceglobals.h>
+#include <k3bdiskinfo.h>
+#include <k3btoc.h>
+#include <k3bcdtext.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qfont.h>
+#include <qmap.h>
+#include <qvaluevector.h>
+#include <qtooltip.h>
+#include <qlistbox.h>
+
+
+class K3bMediaSelectionComboBox::ToolTip : public QToolTip
+{
+public:
+ ToolTip( K3bMediaSelectionComboBox* box );
+
+ void maybeTip( const QPoint &pos );
+
+private:
+ K3bMediaSelectionComboBox* m_box;
+};
+
+
+K3bMediaSelectionComboBox::ToolTip::ToolTip( K3bMediaSelectionComboBox* box )
+ : QToolTip( box->listBox()->viewport() ),
+ m_box( box )
+{
+}
+
+void K3bMediaSelectionComboBox::ToolTip::maybeTip( const QPoint& pos )
+{
+ if( !parentWidget() || !m_box )
+ return;
+
+ QListBoxItem* item = m_box->listBox()->itemAt( pos );
+ if( !item )
+ return;
+
+ int index = m_box->listBox()->index( item );
+
+ if( K3bDevice::Device* dev = m_box->deviceAt( index ) ) {
+ tip( m_box->listBox()->itemRect( item ),
+ m_box->mediumToolTip( k3bappcore->mediaCache()->medium( dev ) ) );
+ }
+}
+
+
+
+
+
+class K3bMediaSelectionComboBox::Private
+{
+public:
+ Private()
+ : ignoreDevice( 0 ) {
+ }
+
+ QMap<K3bDevice::Device*, int> deviceIndexMap;
+ QValueVector<K3bDevice::Device*> devices;
+
+ K3bDevice::Device* ignoreDevice;
+
+ // medium strings for every entry
+ QMap<QString, int> mediaStringMap;
+
+ int wantedMediumType;
+ int wantedMediumState;
+ int wantedMediumContent;
+
+ QFont font;
+};
+
+
+K3bMediaSelectionComboBox::K3bMediaSelectionComboBox( QWidget* parent )
+ : KComboBox( false, parent )
+{
+ d = new Private();
+
+ // set defaults
+ d->wantedMediumType = K3bDevice::MEDIA_WRITABLE_CD;
+ d->wantedMediumState = K3bDevice::STATE_EMPTY;
+ d->wantedMediumContent = K3bMedium::CONTENT_ALL;
+
+ d->font = font();
+
+ connect( this, SIGNAL(activated(int)),
+ this, SLOT(slotActivated(int)) );
+ connect( k3bcore->deviceManager(), SIGNAL(changed(K3bDevice::DeviceManager*)),
+ this, SLOT(slotDeviceManagerChanged(K3bDevice::DeviceManager*)) );
+ connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3bDevice::Device*)),
+ this, SLOT(slotMediumChanged(K3bDevice::Device*)) );
+ connect( this, SIGNAL(selectionChanged(K3bDevice::Device*)),
+ this, SLOT(slotUpdateToolTip(K3bDevice::Device*)) );
+
+ updateMedia();
+
+ // initialize the tooltip for the dropdown box
+ (void)new ToolTip( this );
+}
+
+
+K3bMediaSelectionComboBox::~K3bMediaSelectionComboBox()
+{
+ delete d;
+}
+
+
+void K3bMediaSelectionComboBox::setIgnoreDevice( K3bDevice::Device* dev )
+{
+ d->ignoreDevice = dev;
+ updateMedia();
+}
+
+
+K3bDevice::Device* K3bMediaSelectionComboBox::selectedDevice() const
+{
+ if( d->devices.count() > 0 )
+ return d->devices[currentItem()];
+ else
+ return 0;
+}
+
+
+QValueList<K3bDevice::Device*> K3bMediaSelectionComboBox::allDevices() const
+{
+ QValueList<K3bDevice::Device*> l;
+ for( unsigned int i = 0; i < d->devices.count(); ++i )
+ l.append( d->devices[i] );
+ return l;
+}
+
+
+void K3bMediaSelectionComboBox::setSelectedDevice( K3bDevice::Device* dev )
+{
+ if( dev && d->deviceIndexMap.contains( dev ) ) {
+ setCurrentItem( d->deviceIndexMap[dev] );
+ emit selectionChanged( dev );
+ }
+}
+
+
+void K3bMediaSelectionComboBox::setWantedMediumType( int type )
+{
+ if( type != 0 && type != d->wantedMediumType) {
+ d->wantedMediumType = type;
+ updateMedia();
+ }
+}
+
+
+void K3bMediaSelectionComboBox::setWantedMediumState( int state )
+{
+ if( state != 0 && state != d->wantedMediumState ) {
+ d->wantedMediumState = state;
+ updateMedia();
+ }
+}
+
+
+void K3bMediaSelectionComboBox::setWantedMediumContent( int content )
+{
+ if( content != d->wantedMediumContent ) {
+ d->wantedMediumContent = content;
+ updateMedia();
+ }
+}
+
+
+int K3bMediaSelectionComboBox::wantedMediumType() const
+{
+ return d->wantedMediumType;
+}
+
+
+int K3bMediaSelectionComboBox::wantedMediumState() const
+{
+ return d->wantedMediumState;
+}
+
+
+int K3bMediaSelectionComboBox::wantedMediumContent() const
+{
+ return d->wantedMediumContent;
+}
+
+
+void K3bMediaSelectionComboBox::slotActivated( int i )
+{
+ if( d->devices.count() > 0 )
+ emit selectionChanged( d->devices[i] );
+}
+
+
+void K3bMediaSelectionComboBox::slotMediumChanged( K3bDevice::Device* dev )
+{
+ updateMedium( dev );
+}
+
+
+void K3bMediaSelectionComboBox::clear()
+{
+ d->deviceIndexMap.clear();
+ d->mediaStringMap.clear();
+ d->devices.clear();
+ KComboBox::clear();
+}
+
+
+void K3bMediaSelectionComboBox::showNoMediumMessage()
+{
+ // make it italic
+ QFont f( d->font );
+ f.setItalic( true );
+ setFont( f );
+
+ insertItem( noMediumMessage() );
+}
+
+
+void K3bMediaSelectionComboBox::updateMedia()
+{
+ // reset font
+ setFont( d->font );
+
+ // remember set of devices
+ QValueVector<K3bDevice::Device*> oldDevices = d->devices;
+
+ // remember last selected medium
+ K3bDevice::Device* selected = selectedDevice();
+
+ clear();
+
+ //
+ // We need to only check a selection of the available devices based on the
+ // wanted media type.
+ //
+
+ // no ROM media -> we most likely want only CD/DVD writers
+ bool rwOnly = !( wantedMediumType() & (K3bDevice::MEDIA_CD_ROM|K3bDevice::MEDIA_DVD_ROM) );
+ bool dvdOnly = !( wantedMediumType() & (K3bDevice::MEDIA_CD_ROM|K3bDevice::MEDIA_WRITABLE_CD) );
+
+ QPtrList<K3bDevice::Device> devices = k3bcore->deviceManager()->allDevices();
+ if( dvdOnly ) {
+ if( rwOnly )
+ devices = k3bcore->deviceManager()->dvdWriter();
+ else
+ devices = k3bcore->deviceManager()->dvdReader();
+ }
+ else if( rwOnly )
+ devices = k3bcore->deviceManager()->cdWriter();
+ else
+ devices = k3bcore->deviceManager()->cdReader();
+
+ for( QPtrListIterator<K3bDevice::Device> it( devices ); *it; ++it ) {
+ if ( d->ignoreDevice == *it ) {
+ continue;
+ }
+
+ K3bMedium medium = k3bappcore->mediaCache()->medium( *it );
+
+ if( showMedium( medium ) ) {
+ addMedium( *it );
+ }
+ }
+
+ //
+ // Now in case no usable medium was found show the user a little message
+ //
+ if( d->devices.isEmpty() ) {
+ showNoMediumMessage();
+ if( selected != 0 ) {
+ // inform that we have no medium at all
+ emit selectionChanged( 0 );
+ }
+ }
+ else if( selected && d->deviceIndexMap.contains( selected ) ) {
+ setCurrentItem( d->deviceIndexMap[selected] );
+ }
+ else {
+ emit selectionChanged( selectedDevice() );
+ }
+
+ // did the selection of devices change
+ if( !(d->devices == oldDevices) ) {
+ emit newMedia();
+ for( unsigned int i = 0; i < d->devices.count(); ++i ) {
+ unsigned int j = 0;
+ for( j = 0; j < oldDevices.count(); ++j ) {
+ if( oldDevices[j] == d->devices[i] )
+ break;
+ }
+ if( j == oldDevices.count() ) {
+ // prefere a newly inserted medium over the previously selected
+ setSelectedDevice( d->devices[i] );
+ emit newMedium( d->devices[i] );
+ }
+ }
+ }
+}
+
+
+void K3bMediaSelectionComboBox::updateMedium( K3bDevice::Device* )
+{
+ // for now we simply rebuild the whole list
+ updateMedia();
+}
+
+
+void K3bMediaSelectionComboBox::addMedium( K3bDevice::Device* dev )
+{
+ //
+ // In case we only want an empty medium (this might happen in case the
+ // the medium is rewritable) we do not care about the contents but tell
+ // the user that the medium is rewritable.
+ // Otherwise we show the contents type since this might also be used
+ // for source selection.
+ //
+ QString s = mediumString( k3bappcore->mediaCache()->medium( dev ) );
+
+ //
+ // Now let's see if this string is already contained in the list
+ // and if so add the device name to both
+ //
+ if( d->mediaStringMap.contains( s ) ) {
+ //
+ // insert the modified string
+ //
+ insertItem( s + QString(" (%1 - %2)").arg(dev->vendor()).arg(dev->description()) );
+
+ //
+ // change the already existing string if we did not already do so
+ // (which happens if more than 2 entries have the same medium string)
+ //
+ int prevIndex = d->mediaStringMap[s];
+ if( prevIndex >= 0 )
+ changeItem( text(prevIndex) + QString(" (%1 - %2)").arg(d->devices[prevIndex]->vendor()).arg(d->devices[prevIndex]->description()),
+ prevIndex );
+
+ //
+ // mark the string as already changed
+ //
+ d->mediaStringMap[s] = -1;
+ }
+ else {
+ //
+ // insert the plain medium string
+ //
+ insertItem( s );
+ d->mediaStringMap[s] = count()-1;
+ }
+
+ //
+ // update the helper structures
+ //
+ d->deviceIndexMap[dev] = count()-1;
+ d->devices.append( dev );
+}
+
+
+void K3bMediaSelectionComboBox::slotDeviceManagerChanged( K3bDevice::DeviceManager* )
+{
+ updateMedia();
+}
+
+
+K3bDevice::Device* K3bMediaSelectionComboBox::deviceAt( unsigned int index )
+{
+ if( index < d->devices.count() )
+ return d->devices[index];
+ else
+ return 0;
+}
+
+
+bool K3bMediaSelectionComboBox::showMedium( const K3bMedium& m ) const
+{
+ //
+ // also use if wantedMediumState empty and medium rewritable
+ // because we can always format/erase/overwrite it
+ //
+ // DVD+RW and DVD-RW restr. ovwr. are never reported as appendable
+ //
+ return( m.diskInfo().mediaType() & d->wantedMediumType &&
+ m.content() & d->wantedMediumContent &&
+ ( m.diskInfo().diskState() & d->wantedMediumState
+ ||
+ ( d->wantedMediumState & K3bDevice::STATE_EMPTY &&
+ m.diskInfo().rewritable() )
+ ||
+ ( d->wantedMediumState & K3bDevice::STATE_INCOMPLETE &&
+ !m.diskInfo().empty() &&
+ m.diskInfo().mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR) ) )
+ );
+}
+
+
+QString K3bMediaSelectionComboBox::mediumString( const K3bMedium& medium ) const
+{
+ return medium.shortString( d->wantedMediumState != K3bDevice::STATE_EMPTY );
+}
+
+
+QString K3bMediaSelectionComboBox::mediumToolTip( const K3bMedium& m ) const
+{
+ return m.longString();
+}
+
+
+QString K3bMediaSelectionComboBox::noMediumMessage() const
+{
+ QString stateString;
+ if( d->wantedMediumContent == K3bMedium::CONTENT_ALL ) {
+ if( d->wantedMediumState == K3bDevice::STATE_EMPTY )
+ stateString = i18n("an empty %1 medium");
+ else if( d->wantedMediumState == K3bDevice::STATE_INCOMPLETE )
+ stateString = i18n("an appendable %1 medium");
+ else if( d->wantedMediumState == K3bDevice::STATE_COMPLETE )
+ stateString = i18n("a complete %1 medium");
+ else if( d->wantedMediumState & (K3bDevice::STATE_EMPTY|K3bDevice::STATE_INCOMPLETE) &&
+ !(d->wantedMediumState & K3bDevice::STATE_COMPLETE) )
+ stateString = i18n("an empty or appendable %1 medium");
+ else if( d->wantedMediumState & (K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE) )
+ stateString = i18n("a complete or appendable %1 medium");
+ else
+ stateString = i18n("a %1 medium");
+ }
+ else {
+ //
+ // we only handle the combinations that make sense here
+ //
+ if( d->wantedMediumContent & K3bMedium::CONTENT_VIDEO_CD ||
+ d->wantedMediumContent & K3bMedium::CONTENT_VIDEO_DVD )
+ stateString = i18n("a Video %1 medium");
+ else if( d->wantedMediumContent & K3bMedium::CONTENT_AUDIO &&
+ d->wantedMediumContent & K3bMedium::CONTENT_DATA )
+ stateString = i18n("a Mixed Mode %1 medium");
+ else if( d->wantedMediumContent & K3bMedium::CONTENT_AUDIO )
+ stateString = i18n("an Audio %1 medium");
+ else if( d->wantedMediumContent & K3bMedium::CONTENT_DATA )
+ stateString = i18n("a Data %1 medium");
+ else
+ stateString = i18n("an empty %1 medium");
+ }
+
+ // this is basically the same as in K3bEmptyDiskWaiter
+ // FIXME: include things like only rewritable dvd or cd since we will probably need that
+ QString mediumString;
+ if( d->wantedMediumType == (K3bDevice::MEDIA_CD_ALL|K3bDevice::MEDIA_DVD_ALL) )
+ mediumString = i18n("CD or DVD");
+ else if( d->wantedMediumType == K3bDevice::MEDIA_CD_ALL )
+ mediumString = i18n("CD");
+ else if( d->wantedMediumType == K3bDevice::MEDIA_DVD_ALL )
+ mediumString = i18n("DVD");
+ else if( (d->wantedMediumType & K3bDevice::MEDIA_WRITABLE_DVD) &&
+ (d->wantedMediumType & K3bDevice::MEDIA_WRITABLE_CD) )
+ mediumString = i18n("CD-R(W) or DVD%1R(W)").arg("");
+ else if( d->wantedMediumType & K3bDevice::MEDIA_WRITABLE_DVD_SL )
+ mediumString = i18n("DVD%1R(W)").arg("");
+ else if( d->wantedMediumType & K3bDevice::MEDIA_WRITABLE_DVD_DL )
+ mediumString = i18n("Double Layer DVD%1R").arg("");
+ else if( d->wantedMediumType & K3bDevice::MEDIA_WRITABLE_CD )
+ mediumString = i18n("CD-R(W)");
+ else if( d->wantedMediumType & K3bDevice::MEDIA_DVD_ROM )
+ mediumString = i18n("DVD-ROM");
+ else
+ mediumString = i18n("CD-ROM");
+
+ return i18n("Please insert %1...").arg( stateString.arg( mediumString ) );
+}
+
+
+void K3bMediaSelectionComboBox::slotUpdateToolTip( K3bDevice::Device* dev )
+{
+ // update the tooltip for the combobox (the tooltip for the dropdown box is created in the constructor)
+ QToolTip::remove( this );
+ if( dev )
+ QToolTip::add( this, mediumToolTip( k3bappcore->mediaCache()->medium( dev ) ) );
+}
+
+#include "k3bmediaselectioncombobox.moc"
diff --git a/src/k3bmediaselectioncombobox.h b/src/k3bmediaselectioncombobox.h
new file mode 100644
index 0000000..8a592c9
--- /dev/null
+++ b/src/k3bmediaselectioncombobox.h
@@ -0,0 +1,136 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_MEDIA_SELECTION_COMBOBOX_H_
+#define _K3B_MEDIA_SELECTION_COMBOBOX_H_
+
+#include <kcombobox.h>
+
+#include "k3bmedium.h"
+
+namespace K3bDevice {
+ class Device;
+ class DeviceManager;
+}
+
+/**
+ * Combo box which allows to select a media (in comparison
+ * to the K3bDeviceComboBox which allows to select a device.
+ *
+ * This class uses the K3bMediaCache to update it's status.
+ */
+class K3bMediaSelectionComboBox : public KComboBox
+{
+ Q_OBJECT
+
+ public:
+ K3bMediaSelectionComboBox( QWidget* parent );
+ virtual ~K3bMediaSelectionComboBox();
+
+ /**
+ * Although the widget allows selection of media this
+ * results in a device being selected.
+ */
+ K3bDevice::Device* selectedDevice() const;
+
+ QValueList<K3bDevice::Device*> allDevices() const;
+
+ int wantedMediumType() const;
+ int wantedMediumState() const;
+ int wantedMediumContent() const;
+
+ signals:
+ /**
+ * Be aware that his signal will also be emitted in case
+ * no medium is available with a null pointer.
+ */
+ void selectionChanged( K3bDevice::Device* );
+
+ /**
+ * This signal is emitted if the selection of media changed.
+ * This includes a change due to changing the wanted medium state.
+ */
+ void newMedia();
+
+ void newMedium( K3bDevice::Device* dev );
+
+ public slots:
+ /**
+ * Only works in case the device actually contains a usable medium.
+ * Otherwise the currently selected medium stays selected.
+ */
+ void setSelectedDevice( K3bDevice::Device* );
+
+ /**
+ * Set the wanted medium type. Defaults to writable CD.
+ *
+ * \param type a bitwise combination of the K3bDevice::MediaType enum
+ */
+ void setWantedMediumType( int type );
+
+ /**
+ * Set the wanted medium state. Defaults to empty media.
+ *
+ * \param state a bitwise combination of the K3bDevice::State enum
+ */
+ void setWantedMediumState( int state );
+
+ /**
+ * Set the wanted medium content type. The default is K3bMedium::CONTENT_ALL (i.e. ignore media
+ * content)
+ * Be aware that 0 maps to K3bMedium::CONTENT_NONE, i.e. empty media.
+ *
+ * \param content A bitwise or of K3bMedium::MediumContent
+ */
+ void setWantedMediumContent( int content );
+
+ /**
+ * Set the device to ignore. This device will not be checked for
+ * wanted media. This is many useful for media copy.
+ *
+ * \param dev The device to ignore or 0 to not ignore any device.
+ */
+ void setIgnoreDevice( K3bDevice::Device* dev );
+
+ private slots:
+ void slotMediumChanged( K3bDevice::Device* );
+ void slotDeviceManagerChanged( K3bDevice::DeviceManager* );
+ void slotActivated( int i );
+ void slotUpdateToolTip( K3bDevice::Device* );
+
+ protected:
+ void updateMedia();
+ virtual bool showMedium( const K3bMedium& ) const;
+ virtual QString mediumString( const K3bMedium& ) const;
+ virtual QString mediumToolTip( const K3bMedium& ) const;
+ virtual QString noMediumMessage() const;
+
+ private:
+ void updateMedium( K3bDevice::Device* );
+ void addMedium( K3bDevice::Device* );
+ void showNoMediumMessage();
+ void clear();
+
+ // usedby the tooltip
+ K3bDevice::Device* deviceAt( unsigned int index );
+
+ class ToolTip;
+ friend class ToolTip;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3bmediaselectiondialog.cpp b/src/k3bmediaselectiondialog.cpp
new file mode 100644
index 0000000..3607297
--- /dev/null
+++ b/src/k3bmediaselectiondialog.cpp
@@ -0,0 +1,127 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmediaselectiondialog.h"
+#include "k3bmediaselectioncombobox.h"
+#include "k3bmediacache.h"
+#include "k3bapplication.h"
+
+#include <klocale.h>
+
+#include <qlayout.h>
+#include <qlabel.h>
+
+
+K3bMediaSelectionDialog::K3bMediaSelectionDialog( QWidget* parent,
+ const QString& title,
+ const QString& text,
+ bool modal )
+ : KDialogBase( KDialogBase::Plain,
+ title.isEmpty() ? i18n("Medium Selection") : title,
+ Ok|Cancel,
+ Ok,
+ parent,
+ 0,
+ modal )
+{
+ QGridLayout* lay = new QGridLayout( plainPage() );
+
+ QLabel* label = new QLabel( text.isEmpty() ? i18n("Please select a medium:") : text, plainPage() );
+ m_combo = new K3bMediaSelectionComboBox( plainPage() );
+
+ // lay->setMargin( marginHint() );
+ lay->setSpacing( spacingHint() );
+ lay->addWidget( label, 0, 0 );
+ lay->addWidget( m_combo, 1, 0 );
+ lay->setRowStretch( 2, 1 );
+
+ connect( m_combo, SIGNAL(selectionChanged(K3bDevice::Device*)),
+ this, SLOT(slotSelectionChanged(K3bDevice::Device*)) );
+
+ slotSelectionChanged( m_combo->selectedDevice() );
+}
+
+
+K3bMediaSelectionDialog::~K3bMediaSelectionDialog()
+{
+}
+
+
+void K3bMediaSelectionDialog::setWantedMediumType( int type )
+{
+ m_combo->setWantedMediumType( type );
+}
+
+
+void K3bMediaSelectionDialog::setWantedMediumState( int state )
+{
+ m_combo->setWantedMediumState( state );
+}
+
+
+void K3bMediaSelectionDialog::setWantedMediumContent( int content )
+{
+ m_combo->setWantedMediumContent( content );
+}
+
+
+K3bDevice::Device* K3bMediaSelectionDialog::selectedDevice() const
+{
+ return m_combo->selectedDevice();
+}
+
+
+void K3bMediaSelectionDialog::slotSelectionChanged( K3bDevice::Device* dev )
+{
+ enableButtonOK( dev != 0 );
+}
+
+
+K3bDevice::Device* K3bMediaSelectionDialog::selectMedium( int type, int state, int content,
+ QWidget* parent,
+ const QString& title, const QString& text,
+ bool* canceled )
+{
+ K3bMediaSelectionDialog dlg( parent, title, text );
+ dlg.setWantedMediumType( type );
+ dlg.setWantedMediumState( state );
+ dlg.setWantedMediumContent( content );
+
+ // even if no usable medium is inserted the combobox shows the "insert one" message
+ // so it's not sufficient to check for just one entry to check if there only is a
+ // single useable medium
+ if( ( dlg.selectedDevice() && dlg.m_combo->count() == 1 )
+ || dlg.exec() == Accepted ) {
+ if( canceled )
+ *canceled = false;
+ return dlg.selectedDevice();
+ }
+ else {
+ if( canceled )
+ *canceled = true;
+ return 0;
+ }
+}
+
+
+K3bDevice::Device* K3bMediaSelectionDialog::selectMedium( int type, int state,
+ QWidget* parent,
+ const QString& title, const QString& text,
+ bool* canceled )
+{
+ return selectMedium( type, state, K3bMedium::CONTENT_ALL, parent, title, text, canceled );
+}
+
+#include "k3bmediaselectiondialog.moc"
diff --git a/src/k3bmediaselectiondialog.h b/src/k3bmediaselectiondialog.h
new file mode 100644
index 0000000..317767d
--- /dev/null
+++ b/src/k3bmediaselectiondialog.h
@@ -0,0 +1,87 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_MEDIA_SELECTION_DIALOG_H_
+#define _K3B_MEDIA_SELECTION_DIALOG_H_
+
+#include <kdialogbase.h>
+#include <k3bmedium.h>
+
+class K3bMediaSelectionComboBox;
+namespace K3bDevice {
+ class Device;
+}
+
+class K3bMediaSelectionDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Do not use the constructor. Use the static method instead.
+ */
+ K3bMediaSelectionDialog( QWidget* parent = 0,
+ const QString& title = QString::null,
+ const QString& text = QString::null,
+ bool modal = false );
+ ~K3bMediaSelectionDialog();
+
+ /**
+ * \see K3bMediaSelectionComboBox::setWantedMediumType()
+ */
+ void setWantedMediumType( int type );
+
+ /**
+ * \see K3bMediaSelectionComboBox::setWantedMediumState()
+ */
+ void setWantedMediumState( int state );
+
+ /**
+ * \see K3bMediaSelectionComboBox::setWantedMediumContent()
+ */
+ void setWantedMediumContent( int state );
+
+ /**
+ * Although the dialog is used to select a medium the result is the
+ * device containing that medium.
+ */
+ K3bDevice::Device* selectedDevice() const;
+
+ /**
+ * \deprecated
+ *
+ * Select a medium.
+ * If only one medium of the wanted type is found the method returns immideately
+ * without showing the dialog.
+ */
+ static K3bDevice::Device* selectMedium( int type, int state, QWidget* parent = 0,
+ const QString& title = QString::null,
+ const QString& text = QString::null,
+ bool* canceled = 0 );
+
+ static K3bDevice::Device* selectMedium( int type, int state, int content = K3bMedium::CONTENT_ALL,
+ QWidget* parent = 0,
+ const QString& title = QString::null,
+ const QString& text = QString::null,
+ bool* canceled = 0 );
+
+ private slots:
+ void slotSelectionChanged( K3bDevice::Device* );
+
+ private:
+ K3bMediaSelectionComboBox* m_combo;
+};
+
+#endif
diff --git a/src/k3bmedium.cpp b/src/k3bmedium.cpp
new file mode 100644
index 0000000..18d6257
--- /dev/null
+++ b/src/k3bmedium.cpp
@@ -0,0 +1,463 @@
+
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3bmedium.h"
+
+#include <k3bdeviceglobals.h>
+#include <k3bglobals.h>
+#include <k3biso9660.h>
+#include <k3biso9660backend.h>
+
+#include <klocale.h>
+#include <kio/global.h>
+
+/**
+ * Internal class used by K3bMedium
+ */
+class K3bMedium::Data : public KShared
+{
+public:
+ Data();
+
+ K3bDevice::Device* device;
+ K3bDevice::DiskInfo diskInfo;
+ K3bDevice::Toc toc;
+ K3bDevice::CdText cdText;
+ QValueList<int> writingSpeeds;
+ K3bIso9660SimplePrimaryDescriptor isoDesc;
+ int content;
+};
+
+
+
+K3bMedium::Data::Data()
+ : device( 0 ),
+ content( K3bMedium::CONTENT_NONE )
+{
+}
+
+
+K3bMedium::K3bMedium()
+{
+ d = new Data;
+}
+
+
+
+K3bMedium::K3bMedium( const K3bMedium& other )
+{
+ d = other.d;
+}
+
+
+K3bMedium::K3bMedium( K3bDevice::Device* dev )
+{
+ d = new Data;
+ d->device = dev;
+}
+
+
+K3bMedium::~K3bMedium()
+{
+}
+
+
+K3bMedium& K3bMedium::operator=( const K3bMedium& other )
+{
+ if( this != &other )
+ d = other.d;
+ return *this;
+}
+
+
+void K3bMedium::detach()
+{
+ if( d.count() > 1 )
+ d = new Data( *d );
+}
+
+
+void K3bMedium::setDevice( K3bDevice::Device* dev )
+{
+ if( d->device != dev ) {
+ reset();
+ d->device = dev;
+ }
+}
+
+K3bDevice::Device* K3bMedium::device() const
+{
+ return d->device;
+}
+
+
+const K3bDevice::DiskInfo& K3bMedium::diskInfo() const
+{
+ return d->diskInfo;
+}
+
+
+const K3bDevice::Toc& K3bMedium::toc() const
+{
+ return d->toc;
+}
+
+
+const K3bDevice::CdText& K3bMedium::cdText() const
+{
+ return d->cdText;
+}
+
+
+const QValueList<int>& K3bMedium::writingSpeeds() const
+{
+ return d->writingSpeeds;
+}
+
+
+int K3bMedium::content() const
+{
+ return d->content;
+}
+
+
+const K3bIso9660SimplePrimaryDescriptor& K3bMedium::iso9660Descriptor() const
+{
+ return d->isoDesc;
+}
+
+
+void K3bMedium::reset()
+{
+ detach();
+
+ d->diskInfo = K3bDevice::DiskInfo();
+ d->toc.clear();
+ d->cdText.clear();
+ d->writingSpeeds.clear();
+ d->content = CONTENT_NONE;
+
+ // clear the desc
+ d->isoDesc = K3bIso9660SimplePrimaryDescriptor();
+}
+
+
+void K3bMedium::update()
+{
+ if( d->device ) {
+ reset();
+
+ d->diskInfo = d->device->diskInfo();
+
+ if( d->diskInfo.diskState() != K3bDevice::STATE_NO_MEDIA ) {
+ kdDebug() << "(K3bMedium) found medium:" << endl
+ << "=====================================================" << endl;
+ d->diskInfo.debug();
+ kdDebug() << "=====================================================" << endl;
+ }
+
+ if( diskInfo().diskState() == K3bDevice::STATE_COMPLETE ||
+ diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE ) {
+ d->toc = d->device->readToc();
+ if( d->toc.contentType() == K3bDevice::AUDIO ||
+ d->toc.contentType() == K3bDevice::MIXED )
+ d->cdText = d->device->readCdText();
+ }
+
+ if( diskInfo().mediaType() & K3bDevice::MEDIA_WRITABLE ) {
+ d->writingSpeeds = d->device->determineSupportedWriteSpeeds();
+ }
+
+ analyseContent();
+ }
+}
+
+
+void K3bMedium::analyseContent()
+{
+ // set basic content types
+ switch( toc().contentType() ) {
+ case K3bDevice::AUDIO:
+ d->content = CONTENT_AUDIO;
+ break;
+ case K3bDevice::DATA:
+ case K3bDevice::DVD:
+ d->content = CONTENT_DATA;
+ break;
+ case K3bDevice::MIXED:
+ d->content = CONTENT_AUDIO|CONTENT_DATA;
+ break;
+ default:
+ d->content = CONTENT_NONE;
+ }
+
+ // analyze filesystem
+ if( d->content & CONTENT_DATA ) {
+ //kdDebug() << "(K3bMedium) Checking file system." << endl;
+
+ unsigned long startSec = 0;
+
+ if( diskInfo().numSessions() > 1 ) {
+ // We use the last data track
+ // this way we get the latest session on a ms cd
+ K3bDevice::Toc::const_iterator it = toc().end();
+ --it; // this is valid since there is at least one data track
+ while( it != toc().begin() && (*it).type() != K3bDevice::Track::DATA )
+ --it;
+ startSec = (*it).firstSector().lba();
+ }
+ else {
+ // use first data track
+ K3bDevice::Toc::const_iterator it = toc().begin();
+ while( it != toc().end() && (*it).type() != K3bDevice::Track::DATA )
+ ++it;
+ startSec = (*it).firstSector().lba();
+ }
+
+ //kdDebug() << "(K3bMedium) Checking file system at " << startSec << endl;
+
+ // force the backend since we don't need decryption
+ // which just slows down the whole process
+ K3bIso9660 iso( new K3bIso9660DeviceBackend( d->device ) );
+ iso.setStartSector( startSec );
+ iso.setPlainIso9660( true );
+ if( iso.open() ) {
+ d->isoDesc = iso.primaryDescriptor();
+ kdDebug() << "(K3bMedium) found volume id from start sector " << startSec
+ << ": '" << d->isoDesc.volumeId << "'" << endl;
+
+ if( diskInfo().isDvdMedia() ) {
+ // Every VideoDVD needs to have a VIDEO_TS.IFO file
+ if( iso.firstIsoDirEntry()->entry( "VIDEO_TS/VIDEO_TS.IFO" ) != 0 )
+ d->content |= CONTENT_VIDEO_DVD;
+ }
+ else {
+ kdDebug() << "(K3bMedium) checking for VCD." << endl;
+
+ // check for VCD
+ const K3bIso9660Entry* vcdEntry = iso.firstIsoDirEntry()->entry( "VCD/INFO.VCD" );
+ const K3bIso9660Entry* svcdEntry = iso.firstIsoDirEntry()->entry( "SVCD/INFO.SVD" );
+ const K3bIso9660File* vcdInfoFile = 0;
+ if( vcdEntry ) {
+ kdDebug() << "(K3bMedium) found vcd entry." << endl;
+ if( vcdEntry->isFile() )
+ vcdInfoFile = static_cast<const K3bIso9660File*>(vcdEntry);
+ }
+ if( svcdEntry && !vcdInfoFile ) {
+ kdDebug() << "(K3bMedium) found svcd entry." << endl;
+ if( svcdEntry->isFile() )
+ vcdInfoFile = static_cast<const K3bIso9660File*>(svcdEntry);
+ }
+
+ if( vcdInfoFile ) {
+ char buffer[8];
+
+ if ( vcdInfoFile->read( 0, buffer, 8 ) == 8 &&
+ ( !qstrncmp( buffer, "VIDEO_CD", 8 ) ||
+ !qstrncmp( buffer, "SUPERVCD", 8 ) ||
+ !qstrncmp( buffer, "HQ-VCD ", 8 ) ) )
+ d->content |= CONTENT_VIDEO_CD;
+ }
+ }
+ } // opened iso9660
+ }
+}
+
+
+QString K3bMedium::shortString( bool useContent ) const
+{
+ QString mediaTypeString = K3bDevice::mediaTypeString( diskInfo().mediaType(), true );
+
+ if( diskInfo().diskState() == K3bDevice::STATE_UNKNOWN ) {
+ return i18n("No medium information");
+ }
+
+ else if( diskInfo().diskState() == K3bDevice::STATE_NO_MEDIA ) {
+ return i18n("No medium present");
+ }
+
+ else if( diskInfo().diskState() == K3bDevice::STATE_EMPTY ) {
+ return i18n("Empty %1 medium").arg( mediaTypeString );
+ }
+
+ else {
+ if( useContent ) {
+ // AUDIO + MIXED
+ if( toc().contentType() == K3bDevice::AUDIO ||
+ toc().contentType() == K3bDevice::MIXED ) {
+ if( !cdText().performer().isEmpty() || !cdText().title().isEmpty() ) {
+ return QString("%1 - %2 (%3)")
+ .arg( cdText().performer() )
+ .arg( cdText().title() )
+ .arg( toc().contentType() == K3bDevice::AUDIO ? i18n("Audio CD") : i18n("Mixed CD") );
+ }
+ else if( toc().contentType() == K3bDevice::AUDIO ) {
+ return i18n("Audio CD");
+ }
+ else {
+ return i18n("%1 (Mixed CD)").arg( beautifiedVolumeId() );
+ }
+ }
+
+ // DATA CD and DVD
+ else if( !volumeId().isEmpty() ) {
+ if( content() & CONTENT_VIDEO_DVD ) {
+ return QString("%1 (%2)").arg( beautifiedVolumeId() ).arg( i18n("Video DVD") );
+ }
+ else if( content() & CONTENT_VIDEO_CD ) {
+ return QString("%1 (%2)").arg( beautifiedVolumeId() ).arg( i18n("Video CD") );
+ }
+ else if( diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE ) {
+ return i18n("%1 (Appendable Data %2)").arg( beautifiedVolumeId(), mediaTypeString );
+ }
+ else {
+ return i18n("%1 (Complete Data %2)").arg( beautifiedVolumeId(), mediaTypeString );
+ }
+ }
+ else {
+ if( diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE ) {
+ return i18n("Appendable Data %1").arg( mediaTypeString );
+ }
+ else {
+ return i18n("Complete Data %1").arg( mediaTypeString );
+ }
+ }
+ }
+
+ // without content
+ else {
+ if( diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE ) {
+ return i18n("Appendable %1 medium").arg( mediaTypeString );
+ }
+ else {
+ return i18n("Complete %1 medium").arg( mediaTypeString );
+ }
+ }
+ }
+}
+
+
+QString K3bMedium::longString() const
+{
+ QString s = QString("<p><nobr><b>%1 %2</b> (%3)</nobr>"
+ "<p>")
+ .arg( d->device->vendor() )
+ .arg( d->device->description() )
+ .arg( d->device->blockDeviceName() )
+ + shortString( true );
+
+ if( diskInfo().diskState() == K3bDevice::STATE_COMPLETE ||
+ diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE ) {
+ s += "<br>" + i18n("%1 in %n track", "%1 in %n tracks", toc().count() )
+ .arg( KIO::convertSize(diskInfo().size().mode1Bytes() ) );
+ if( diskInfo().numSessions() > 1 )
+ s += i18n(" and %n session", " and %n sessions", diskInfo().numSessions() );
+ }
+
+ if( diskInfo().diskState() == K3bDevice::STATE_EMPTY ||
+ diskInfo().diskState() == K3bDevice::STATE_INCOMPLETE )
+ s += "<br>" + i18n("Free space: %1")
+ .arg( KIO::convertSize( diskInfo().remainingSize().mode1Bytes() ) );
+
+ if( !diskInfo().empty() && diskInfo().rewritable() )
+ s += "<br>" + i18n("Capacity: %1")
+ .arg( KIO::convertSize( diskInfo().capacity().mode1Bytes() ) );
+
+ return s;
+}
+
+
+const QString& K3bMedium::volumeId() const
+{
+ return iso9660Descriptor().volumeId;
+}
+
+
+QString K3bMedium::beautifiedVolumeId() const
+{
+ const QString& oldId = volumeId();
+ QString newId;
+
+ bool newWord = true;
+ for( unsigned int i = 0; i < oldId.length(); ++i ) {
+ QChar c = oldId[i];
+ //
+ // first let's handle the cases where we do not change
+ // the id anyway
+ //
+ // In case the id already contains spaces or lower case chars
+ // it is likely that it already looks good and does ignore
+ // the restricted iso9660 charset (like almost every project
+ // created with K3b)
+ //
+ if( c.isLetter() && c.lower() == c )
+ return oldId;
+ else if( c.isSpace() )
+ return oldId;
+
+ // replace underscore with space
+ else if( c.unicode() == 95 ) {
+ newId.append( ' ' );
+ newWord = true;
+ }
+
+ // from here on only upper case chars and numbers and stuff
+ else if( c.isLetter() ) {
+ if( newWord ) {
+ newId.append( c );
+ newWord = false;
+ }
+ else {
+ newId.append( c.lower() );
+ }
+ }
+ else {
+ newId.append( c );
+ }
+ }
+
+ return newId;
+}
+
+
+bool K3bMedium::operator==( const K3bMedium& other )
+{
+ if( this->d == other.d )
+ return true;
+
+ return( this->device() == other.device() &&
+ this->diskInfo() == other.diskInfo() &&
+ this->toc() == other.toc() &&
+ this->cdText() == other.cdText() &&
+ this->content() == other.content() &&
+ this->iso9660Descriptor() == other.iso9660Descriptor() );
+}
+
+
+bool K3bMedium::operator!=( const K3bMedium& other )
+{
+ if( this->d == other.d )
+ return false;
+
+ return( this->device() != other.device() ||
+ this->diskInfo() != other.diskInfo() ||
+ this->toc() != other.toc() ||
+ this->cdText() != other.cdText() ||
+ this->content() != other.content() ||
+ this->iso9660Descriptor() != other.iso9660Descriptor() );
+}
diff --git a/src/k3bmedium.h b/src/k3bmedium.h
new file mode 100644
index 0000000..22b8c00
--- /dev/null
+++ b/src/k3bmedium.h
@@ -0,0 +1,134 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_MEDIUM_H_
+#define _K3B_MEDIUM_H_
+
+#include <k3bdiskinfo.h>
+#include <k3btoc.h>
+#include <k3bcdtext.h>
+#include <k3bdevice.h>
+#include <k3biso9660.h>
+
+#include <ksharedptr.h>
+
+
+/**
+ * K3bMedium represents a medium in K3b.
+ *
+ * It is implicetely shared, thus copying is very fast.
+ */
+class K3bMedium
+{
+ public:
+ K3bMedium();
+ K3bMedium( const K3bMedium& );
+ K3bMedium( K3bDevice::Device* dev );
+ ~K3bMedium();
+
+ K3bMedium& operator=( const K3bMedium& );
+
+ void setDevice( K3bDevice::Device* dev );
+
+ /**
+ * Resets everything to default values except the device.
+ * This means empty toc, cd text, no writing speeds, and a diskinfo
+ * with state UNKNOWN.
+ */
+ void reset();
+
+ /**
+ * Updates the medium information if the device is not null.
+ * Do not use this in the GUI thread since it uses blocking
+ * K3bdevice methods.
+ */
+ void update();
+
+ K3bDevice::Device* device() const;
+ const K3bDevice::DiskInfo& diskInfo() const;
+ const K3bDevice::Toc& toc() const;
+ const K3bDevice::CdText& cdText() const;
+
+ /**
+ * The writing speeds the device supports with the inserted medium.
+ * With older devices this list might even be empty for writable
+ * media. In that case refer to K3bDevice::Device::maxWriteSpeed
+ * combined with a manual speed selection.
+ */
+ const QValueList<int>& writingSpeeds() const;
+ const QString& volumeId() const;
+
+ /**
+ * This method tries to make a volume identificator witch uses a reduced character set
+ * look more beautiful by, for example, replacing '_' with a space or replacing all upper
+ * case words.
+ *
+ * Volume ids already containing spaces or lower case characters are left unchanged.
+ */
+ QString beautifiedVolumeId() const;
+
+ /**
+ * Content type. May be combined by a binary OR.
+ */
+ enum MediumContent {
+ CONTENT_NONE = 0x1,
+ CONTENT_AUDIO = 0x2,
+ CONTENT_DATA = 0x4,
+ CONTENT_VIDEO_CD = 0x8,
+ CONTENT_VIDEO_DVD = 0x10,
+ CONTENT_ALL = 0xFF
+ };
+
+ /**
+ * \return a bitwise combination of MediumContent.
+ * A VideoCD for example may have the following content:
+ * CONTENT_AUDIO|CONTENT_DATA|CONTENT_VIDEO_CD
+ */
+ int content() const;
+
+ /**
+ * \return The volume descriptor from the ISO9660 filesystem.
+ */
+ const K3bIso9660SimplePrimaryDescriptor& iso9660Descriptor() const;
+
+ /**
+ * \return A short one-liner string representing the medium.
+ * This string may be used for labels or selection boxes.
+ * \param useContent if true the content of the CD/DVD will be used, otherwise
+ * the string will simply be something like "empty DVD-R medium".
+ */
+ QString shortString( bool useContent = true ) const;
+
+ /**
+ * \return A HTML formatted string decribing this medium. This includes the device, the
+ * medium type, the contents type, and some detail information like the number of
+ * tracks.
+ * This string may be used for tooltips or short descriptions.
+ */
+ QString longString() const;
+
+ bool operator==( const K3bMedium& other );
+ bool operator!=( const K3bMedium& other );
+
+ private:
+ void analyseContent();
+
+ void detach();
+
+ class Data;
+ KSharedPtr<Data> d;
+};
+
+#endif
diff --git a/src/k3bminibutton.cpp b/src/k3bminibutton.cpp
new file mode 100644
index 0000000..0d0a1db
--- /dev/null
+++ b/src/k3bminibutton.cpp
@@ -0,0 +1,77 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * K3bMiniButton is based on KDockButton_Private
+ * 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bminibutton.h"
+
+#include <qpainter.h>
+
+
+K3bMiniButton::K3bMiniButton( QWidget *parent, const char * name )
+ :QPushButton( parent, name ),
+ m_mouseOver( false )
+{
+ setFocusPolicy( NoFocus );
+}
+
+K3bMiniButton::~K3bMiniButton()
+{
+}
+
+
+void K3bMiniButton::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( m_mouseOver && !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 K3bMiniButton::enterEvent( QEvent * )
+{
+ m_mouseOver = true;
+ repaint();
+}
+
+
+void K3bMiniButton::leaveEvent( QEvent * )
+{
+ m_mouseOver = false;
+ repaint();
+}
+
+#include "k3bminibutton.moc"
diff --git a/src/k3bminibutton.h b/src/k3bminibutton.h
new file mode 100644
index 0000000..b3d38a0
--- /dev/null
+++ b/src/k3bminibutton.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * K3bMiniButton is based on KDockButton_Private
+ * 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_MINI_BUTTON_H_
+#define _K3B_MINI_BUTTON_H_
+
+#include <qpushbutton.h>
+
+class QPainter;
+class QEvent;
+
+
+/**
+ * K3bMiniButton is a minimalistic button mainly used
+ * to show a pixmap.
+ */
+class K3bMiniButton : public QPushButton
+{
+ Q_OBJECT
+
+ public:
+ K3bMiniButton( QWidget *parent=0, const char *name=0 );
+ virtual ~K3bMiniButton();
+
+ protected:
+ virtual void drawButton( QPainter * );
+ virtual void enterEvent( QEvent * );
+ virtual void leaveEvent( QEvent * );
+
+ private:
+ bool m_mouseOver;
+};
+
+#endif
diff --git a/src/k3bmixedprojectinterface.cpp b/src/k3bmixedprojectinterface.cpp
new file mode 100644
index 0000000..3b5004e
--- /dev/null
+++ b/src/k3bmixedprojectinterface.cpp
@@ -0,0 +1,46 @@
+/*
+ *
+ * $Id: k3bmixedprojectinterface.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmixedprojectinterface.h"
+#include "k3bdataprojectinterface.h"
+#include "k3baudioprojectinterface.h"
+
+#include <kapplication.h>
+#include <dcopclient.h>
+
+#include <k3bmixeddoc.h>
+#include <k3bdatadoc.h>
+#include <k3baudiodoc.h>
+
+
+K3bMixedProjectInterface::K3bMixedProjectInterface( K3bMixedDoc* doc, const char* name )
+ : K3bProjectInterface( doc, name ),
+ m_mixedDoc( doc )
+{
+ m_dataInterface = new K3bDataProjectInterface( doc->dataDoc(), objId() + "-datapart" );
+ m_audioInterface = new K3bAudioProjectInterface( doc->audioDoc(), objId() + "-audiopart" );
+}
+
+
+DCOPRef K3bMixedProjectInterface::dataPart() const
+{
+ return DCOPRef( kapp->dcopClient()->appId(), m_dataInterface->objId() );
+}
+
+
+DCOPRef K3bMixedProjectInterface::audioPart() const
+{
+ return DCOPRef( kapp->dcopClient()->appId(), m_audioInterface->objId() );
+}
diff --git a/src/k3bmixedprojectinterface.h b/src/k3bmixedprojectinterface.h
new file mode 100644
index 0000000..21892d1
--- /dev/null
+++ b/src/k3bmixedprojectinterface.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * $Id: k3bmixedprojectinterface.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_MIXED_PROJECT_INTERFACE_H_
+#define _K3B_MIXED_PROJECT_INTERFACE_H_
+
+#include "k3bprojectinterface.h"
+
+#include <dcopref.h>
+
+class K3bMixedDoc;
+class K3bDataProjectInterface;
+class K3bAudioProjectInterface;
+
+
+class K3bMixedProjectInterface : public K3bProjectInterface
+{
+ K_DCOP
+
+ public:
+ K3bMixedProjectInterface( K3bMixedDoc*, const char* name = 0 );
+
+ k_dcop:
+ DCOPRef dataPart() const;
+ DCOPRef audioPart() const;
+
+ private:
+ K3bMixedDoc* m_mixedDoc;
+
+ K3bDataProjectInterface* m_dataInterface;
+ K3bAudioProjectInterface* m_audioInterface;
+};
+
+#endif
diff --git a/src/k3bmusicbrainz.cpp b/src/k3bmusicbrainz.cpp
new file mode 100644
index 0000000..f0415af
--- /dev/null
+++ b/src/k3bmusicbrainz.cpp
@@ -0,0 +1,103 @@
+/*
+ *
+ * $Id: k3bmusicbrainz.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_MUSICBRAINZ
+
+#include "k3bmusicbrainz.h"
+
+#include <musicbrainz/mb_c.h>
+
+#include <kprotocolmanager.h>
+#include <kurl.h>
+#include <kdebug.h>
+
+
+class K3bMusicBrainz::Private
+{
+public:
+ musicbrainz_t mb;
+
+ QStringList titles;
+ QStringList artists;
+};
+
+
+K3bMusicBrainz::K3bMusicBrainz()
+{
+ d = new Private;
+ d->mb = mb_New();
+ mb_UseUTF8( d->mb, 1 );
+}
+
+
+K3bMusicBrainz::~K3bMusicBrainz()
+{
+ mb_Delete( d->mb );
+ delete d;
+}
+
+
+int K3bMusicBrainz::query( const QCString& trm )
+{
+ d->titles.clear();
+ d->artists.clear();
+
+ if( KProtocolManager::useProxy() ) {
+ KURL proxy = KProtocolManager::proxyFor("http");
+ mb_SetProxy( d->mb, const_cast<char*>(proxy.host().latin1()), short(proxy.port()) );
+ }
+
+ char* args[2];
+ args[0] = trm.data();
+ args[1] = 0;
+
+ if( mb_QueryWithArgs( d->mb, (char*)MBQ_TrackInfoFromTRMId, (char**)args ) ) {
+
+ unsigned int i = 1;
+ while( mb_Select(d->mb, (char*)MBS_Rewind) && mb_Select1( d->mb, (char*)MBS_SelectTrack, i ) ) {
+ QCString data(256);
+ mb_GetResultData( d->mb, (char*)MBE_TrackGetArtistName, data.data(), 256 );
+ d->artists.append( QString::fromUtf8( data ).stripWhiteSpace() );
+ mb_GetResultData( d->mb, (char*)MBE_TrackGetTrackName, data.data(), 256 );
+ d->titles.append( QString::fromUtf8( data ).stripWhiteSpace() );
+
+ ++i;
+ }
+
+ return i-1;
+ }
+ else {
+ char buffer[256];
+ mb_GetQueryError( d->mb, buffer, 256 );
+ kdDebug() << "(K3bMusicBrainz) query error: " << buffer << endl;
+ return 0;
+ }
+}
+
+
+const QString& K3bMusicBrainz::title( unsigned int i ) const
+{
+ return d->titles[i];
+}
+
+
+const QString& K3bMusicBrainz::artist( unsigned int i ) const
+{
+ return d->artists[i];
+}
+
+#endif
diff --git a/src/k3bmusicbrainz.h b/src/k3bmusicbrainz.h
new file mode 100644
index 0000000..6cf5d06
--- /dev/null
+++ b/src/k3bmusicbrainz.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * $Id: k3bmusicbrainz.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_MUSICBRAINZ_H_
+#define _K3B_MUSICBRAINZ_H_
+
+#include <config.h>
+
+#ifdef HAVE_MUSICBRAINZ
+
+#include <qcstring.h>
+#include <qstring.h>
+
+
+/**
+ * A wrapper class around libmusicbrainz. Use in combination with K3bTRM.
+ *
+ * Tries to determine the artist and title related to a trm.
+ */
+class K3bMusicBrainz
+{
+ public:
+ K3bMusicBrainz();
+ ~K3bMusicBrainz();
+
+ /**
+ * \return number of found results.
+ */
+ int query( const QCString& trm );
+
+ const QString& title( unsigned int i = 0 ) const;
+ const QString& artist( unsigned int i = 0 ) const;
+
+ private:
+ class Private;
+ Private* d;
+};
+
+
+#endif
+
+#endif
diff --git a/src/k3bpassivepopup.cpp b/src/k3bpassivepopup.cpp
new file mode 100644
index 0000000..d1865cf
--- /dev/null
+++ b/src/k3bpassivepopup.cpp
@@ -0,0 +1,280 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bpassivepopup.h"
+#include "k3bwidgetshoweffect.h"
+#include "k3btimeoutwidget.h"
+#include "k3bminibutton.h"
+
+#include "k3bthememanager.h"
+#include <k3bapplication.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kguiitem.h>
+#include <kpushbutton.h>
+#include <kactivelabel.h>
+
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qmainwindow.h>
+#include <qmessagebox.h>
+#include <qstyle.h>
+#include <qtooltip.h>
+#include <qfont.h>
+
+
+static const char* const sticky_xpm[] = {
+ "5 5 2 1",
+ "# c black",
+ ". c None",
+ "#####",
+ "#...#",
+ "#...#",
+ "#...#",
+ "#####"
+};
+
+static QPixmap themedMessageBoxIcon( K3bPassivePopup::MessageType mt )
+{
+ QString icon_name;
+ QMessageBox::Icon qIcon;
+
+ switch( mt ) {
+ case K3bPassivePopup::Information:
+ qIcon = QMessageBox::Information;
+ icon_name = "messagebox_info";
+ break;
+ case K3bPassivePopup::Warning:
+ qIcon = QMessageBox::Warning;
+ icon_name = "messagebox_warning";
+ break;
+ case K3bPassivePopup::Error:
+ qIcon = QMessageBox::Critical;
+ icon_name = "messagebox_critical";
+ break;
+ default:
+ return QPixmap();
+ break;
+ }
+
+ QPixmap ret = KApplication::kApplication()->iconLoader()->loadIcon(icon_name, KIcon::NoGroup, KIcon::SizeMedium, KIcon::DefaultState, 0, true);
+
+ if( ret.isNull() )
+ return QMessageBox::standardIcon( qIcon );
+ else
+ return ret;
+}
+
+
+class K3bPassivePopup::Private
+{
+public:
+ int timeout;
+ int showEffect;
+
+ K3bTimeoutWidget* timeoutWidget;
+ QLabel* titleLabel;
+ KActiveLabel* messageLabel;
+ QLabel* pixmapLabel;
+ K3bMiniButton* closeButton;
+ K3bMiniButton* stickyButton;
+};
+
+
+K3bPassivePopup::K3bPassivePopup( QWidget* parent )
+ : QFrame( parent )
+{
+ d = new Private;
+ d->timeout = 6000;
+ d->showEffect = 0;
+
+ setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
+ // setWFlags( Qt::WX11BypassWM );
+
+ QVBoxLayout* mainLay = new QVBoxLayout( this );
+ mainLay->setMargin( frameWidth() );
+ mainLay->setSpacing( 0 );
+
+ QGridLayout* grid = new QGridLayout;
+ grid->setMargin( 9 );
+ grid->setSpacing( 6 );
+
+ d->titleLabel = new QLabel( this );
+ d->titleLabel->setMargin( 5 );
+ d->titleLabel->setAlignment( Qt::AlignCenter );
+ QFont fnt( d->titleLabel->font() );
+ fnt.setBold( true );
+ d->titleLabel->setFont( fnt );
+
+ d->messageLabel = new KActiveLabel( this );
+
+ d->pixmapLabel = new QLabel( this );
+ d->pixmapLabel->setAlignment( Qt::AlignTop );
+
+ d->timeoutWidget = new K3bTimeoutWidget( this );
+ connect( d->timeoutWidget, SIGNAL(timeout()), this, SLOT(slotClose()) );
+
+ d->closeButton = new K3bMiniButton( d->titleLabel );
+ d->closeButton->setPixmap( style().stylePixmap( QStyle::SP_TitleBarCloseButton, this ) );
+ d->closeButton->setFixedSize( d->closeButton->pixmap()->width(), d->closeButton->pixmap()->height() );
+ QToolTip::add( d->closeButton, i18n("Close") );
+ connect( d->closeButton, SIGNAL(clicked()), this, SLOT(slotClose()) );
+
+ d->stickyButton = new K3bMiniButton( d->titleLabel );
+ d->stickyButton->setToggleButton( true );
+ d->stickyButton->setPixmap( const_cast< const char** >( sticky_xpm ) );
+ d->stickyButton->setFixedSize( d->closeButton->pixmap()->width(), d->closeButton->pixmap()->height() );
+ QToolTip::add( d->stickyButton, i18n("Keep Open") );
+ connect( d->stickyButton, SIGNAL(toggled(bool)), this, SLOT(slotSticky(bool)) );
+
+ grid->addWidget( d->pixmapLabel, 0, 0 );
+ grid->addWidget( d->messageLabel, 0, 1 );
+ grid->addWidget( d->timeoutWidget, 0, 2 );
+ grid->setColStretch( 1, 1 );
+
+ mainLay->addWidget( d->titleLabel );
+ mainLay->addLayout( grid, 1 );
+
+ QHBoxLayout* titleLay = new QHBoxLayout( d->titleLabel );
+ titleLay->setMargin( d->titleLabel->margin() );
+ titleLay->setSpacing( 2 );
+ titleLay->addStretch();
+ titleLay->addWidget( d->stickyButton );
+ titleLay->addWidget( d->closeButton );
+
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ d->titleLabel->setPaletteBackgroundColor( theme->backgroundColor() );
+ d->titleLabel->setPaletteForegroundColor( theme->foregroundColor() );
+ }
+
+ setTitle( QString::null );
+ setMessageType( Information );
+}
+
+
+K3bPassivePopup::~K3bPassivePopup()
+{
+ delete d;
+}
+
+
+void K3bPassivePopup::setShowCloseButton( bool b )
+{
+ d->closeButton->setShown( b );
+ adjustSize();
+}
+
+
+void K3bPassivePopup::setShowCountdown( bool b )
+{
+ d->timeoutWidget->setShown( b );
+ d->stickyButton->setShown( b );
+}
+
+
+void K3bPassivePopup::setMessage( const QString& m )
+{
+ d->messageLabel->setText( "<qt>" + m );
+ adjustSize();
+}
+
+
+void K3bPassivePopup::setTitle( const QString& t )
+{
+ d->titleLabel->setText( t );
+ // d->titleLabel->setShown( !t.isEmpty() );
+ adjustSize();
+}
+
+
+void K3bPassivePopup::setTimeout( int msecs )
+{
+ d->timeout = msecs;
+}
+
+
+void K3bPassivePopup::setMessageType( MessageType m )
+{
+ d->pixmapLabel->setPixmap( themedMessageBoxIcon( m ) );
+ adjustSize();
+}
+
+
+void K3bPassivePopup::slideIn()
+{
+ d->showEffect = K3bWidgetShowEffect::Slide;
+ connect( K3bWidgetShowEffect::showWidget( this, (K3bWidgetShowEffect::Effect)d->showEffect ), SIGNAL(widgetShown(QWidget*)),
+ this, SLOT(slotShown()) );
+}
+
+
+void K3bPassivePopup::slotShown()
+{
+ if( d->timeoutWidget->isVisible() ) {
+ d->timeoutWidget->setTimeout( d->timeout );
+ d->timeoutWidget->start();
+ }
+ else
+ QTimer::singleShot( d->timeout, this, SLOT(slotClose()) );
+}
+
+
+void K3bPassivePopup::slotHidden()
+{
+ deleteLater();
+}
+
+
+void K3bPassivePopup::slotClose()
+{
+ if( d->showEffect != 0 ) {
+ connect( K3bWidgetShowEffect::hideWidget( this, (K3bWidgetShowEffect::Effect)d->showEffect ), SIGNAL(widgetHidden(QWidget*)),
+ this, SLOT(slotHidden()) );
+ }
+ else
+ deleteLater();
+}
+
+
+void K3bPassivePopup::slotSticky( bool b )
+{
+ if( b ) {
+ d->timeoutWidget->pause();
+ }
+ else {
+ d->timeoutWidget->resume();
+ }
+}
+
+
+void K3bPassivePopup::showPopup( const QString& message,
+ const QString& title,
+ MessageType messageType,
+ bool countdown,
+ bool button )
+{
+ K3bPassivePopup* pop = new K3bPassivePopup( static_cast<QMainWindow*>(qApp->mainWidget())->centralWidget() );
+ pop->setMessage( message );
+ pop->setTitle( title );
+ pop->setMessageType( messageType );
+ pop->setShowCloseButton( button );
+ pop->setShowCountdown( countdown );
+ pop->slideIn();
+}
+
+#include "k3bpassivepopup.moc"
diff --git a/src/k3bpassivepopup.h b/src/k3bpassivepopup.h
new file mode 100644
index 0000000..e567d7e
--- /dev/null
+++ b/src/k3bpassivepopup.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_PASSIVE_POPUP_H_
+#define _K3B_PASSIVE_POPUP_H_
+
+#include <qframe.h>
+
+class K3bTimeoutWidget;
+class KActiveLabel;
+class KPushButton;
+class QLabel;
+
+
+/**
+ * A message box which is closed using a timer or a close button
+ * It will delete itself once it has been closed.
+ */
+class K3bPassivePopup : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ K3bPassivePopup( QWidget* parent );
+ ~K3bPassivePopup();
+
+ enum MessageType {
+ Information,
+ Warning,
+ Error
+ };
+
+ /**
+ * This will show the popup using K3bWidgetShowEffect::Slide and close it the
+ * same way.
+ */
+ void slideIn();
+
+ static void showPopup( const QString& message,
+ const QString& title = QString::null,
+ MessageType messageType = Information,
+ bool countdown = true,
+ bool button = true );
+
+ public slots:
+ void setShowCloseButton( bool b );
+ void setShowCountdown( bool b );
+ void setMessage( const QString& m );
+ void setTitle( const QString& t );
+ void setTimeout( int msecs );
+ void setMessageType( MessageType m );
+
+ private slots:
+ void slotShown();
+ void slotHidden();
+ void slotClose();
+ void slotSticky( bool );
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3bprojectinterface.cpp b/src/k3bprojectinterface.cpp
new file mode 100644
index 0000000..46968fd
--- /dev/null
+++ b/src/k3bprojectinterface.cpp
@@ -0,0 +1,138 @@
+/*
+ *
+ * $Id: k3bprojectinterface.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bprojectinterface.h"
+#include "k3bburnprogressdialog.h"
+#include <k3bdoc.h>
+#include <k3bview.h>
+#include <k3bmsf.h>
+#include <k3bcore.h>
+#include <k3bdevicemanager.h>
+#include <k3bjob.h>
+
+#include <qtimer.h>
+
+
+//static
+QCString K3bProjectInterface::newIfaceName()
+{
+ static int s_docIFNumber = 0;
+ QCString name;
+ name.setNum( s_docIFNumber++ );
+ name.prepend("K3bProject-");
+ return name;
+}
+
+
+K3bProjectInterface::K3bProjectInterface( K3bDoc* doc, const char* name )
+ : DCOPObject( name ? QCString(name) : newIfaceName() ),
+ m_doc( doc )
+{
+}
+
+
+K3bProjectInterface::~K3bProjectInterface()
+{
+}
+
+void K3bProjectInterface::addUrls( const QStringList& urls )
+{
+ m_doc->addUrls( KURL::List(urls) );
+}
+
+void K3bProjectInterface::addUrl( const QString& url )
+{
+ m_doc->addUrl( KURL(url) );
+}
+
+void K3bProjectInterface::burn()
+{
+ // we want to return this method immediately
+ QTimer::singleShot( 0, m_doc->view(), SLOT(slotBurn()) );
+}
+
+
+bool K3bProjectInterface::directBurn()
+{
+ if( m_doc->burner() ) {
+ K3bJobProgressDialog* dlg = 0;
+ if( m_doc->onlyCreateImages() )
+ dlg = new K3bJobProgressDialog( m_doc->view() );
+ else
+ dlg = new K3bBurnProgressDialog( m_doc->view() );
+
+ K3bJob* job = m_doc->newBurnJob( dlg );
+
+ dlg->startJob( job );
+
+ delete job;
+ delete dlg;
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+void K3bProjectInterface::setBurnDevice( const QString& name )
+{
+ if( K3bDevice::Device* dev = k3bcore->deviceManager()->findDevice( name ) )
+ m_doc->setBurner( dev );
+}
+
+
+int K3bProjectInterface::length() const
+{
+ return m_doc->length().lba();
+}
+
+
+KIO::filesize_t K3bProjectInterface::size() const
+{
+ return m_doc->size();
+}
+
+
+const QString& K3bProjectInterface::imagePath() const
+{
+ return m_doc->tempDir();
+}
+
+
+QString K3bProjectInterface::projectType() const
+{
+ switch( m_doc->type() ) {
+ case K3bDoc::AUDIO:
+ return "audiocd";
+ case K3bDoc::DATA:
+ return "datacd";
+ case K3bDoc::MIXED:
+ return "mixedcd";
+ case K3bDoc::VCD:
+ return "videocd";
+ case K3bDoc::MOVIX:
+ return "emovixcd";
+ case K3bDoc::MOVIX_DVD:
+ return "emovixdvd";
+ case K3bDoc::DVD:
+ return "datadvd";
+ case K3bDoc::VIDEODVD:
+ return "videodvd";
+ default:
+ return "unknown";
+ }
+}
diff --git a/src/k3bprojectinterface.h b/src/k3bprojectinterface.h
new file mode 100644
index 0000000..8deb848
--- /dev/null
+++ b/src/k3bprojectinterface.h
@@ -0,0 +1,91 @@
+/*
+ *
+ * $Id: k3bprojectinterface.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_PROJECT_INTERFACE_H_
+#define _K3B_PROJECT_INTERFACE_H_
+
+#include <dcopobject.h>
+#include <kio/global.h>
+#include <qstringlist.h>
+
+class K3bDoc;
+
+/**
+ * Base class for all project interfaces
+ */
+class K3bProjectInterface : public DCOPObject
+{
+ K_DCOP
+
+ public:
+ K3bProjectInterface( K3bDoc*, const char* name = 0 );
+ virtual ~K3bProjectInterface();
+
+ // Generate a name for this interface. Automatically used if name=0 is
+ // passed to the constructor
+ static QCString newIfaceName();
+
+ k_dcop:
+ virtual void addUrls( const QStringList& urls );
+ virtual void addUrl( const QString& url );
+
+ /**
+ * Opens the burn dialog
+ */
+ virtual void burn();
+
+ /**
+ * Starts the burning immedeately
+ * \return true if the burning could be started. Be aware that the return
+ * value does not say anything about the success of the burning
+ * process.
+ */
+ virtual bool directBurn();
+
+ virtual void setBurnDevice( const QString& blockdevicename );
+
+ /**
+ * \return the length of the project in blocks (frames).
+ */
+ virtual int length() const;
+
+ /**
+ * \return size of the project in bytes.
+ */
+ virtual KIO::filesize_t size() const;
+
+ virtual const QString& imagePath() const;
+
+ /**
+ * \return A string representation of the project type. One of:
+ * \li "datacd" - Data CD
+ * \li "audiocd" - Audio CD
+ * \li "mixedcd" - Mixed Mode CD
+ * \li "videocd" - Video
+ * \li "emovixcd" - eMovix CD
+ * \li "datadvd" - Data DVD
+ * \li "videodvd" - Video DVD
+ * \li "emovixdvd" - eMovix DVD
+ *
+ * Be aware that this is not the same as K3bDoc::documentType for historical reasons.
+ */
+ virtual QString projectType() const;
+
+ private:
+ K3bDoc* m_doc;
+};
+
+#endif
diff --git a/src/k3bprojectmanager.cpp b/src/k3bprojectmanager.cpp
new file mode 100644
index 0000000..0c6d65f
--- /dev/null
+++ b/src/k3bprojectmanager.cpp
@@ -0,0 +1,653 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bprojectmanager.h"
+
+#include "k3bprojectinterface.h"
+#include "k3bdataprojectinterface.h"
+#include "k3baudioprojectinterface.h"
+#include "k3bmixedprojectinterface.h"
+#include "kostore/koStore.h"
+#include "kostore/koStoreDevice.h"
+#include "k3bapplication.h"
+#include "k3binteractiondialog.h"
+
+#include <k3baudiodoc.h>
+#include <k3baudiodatasourceiterator.h>
+#include <k3baudiocdtracksource.h>
+#include <k3bdatadoc.h>
+#include <k3bdvddoc.h>
+#include <k3bvideodvddoc.h>
+#include <k3bmixeddoc.h>
+#include <k3bvcddoc.h>
+#include <k3bmovixdoc.h>
+#include <k3bmovixdvddoc.h>
+#include <k3bglobals.h>
+#include <k3bisooptions.h>
+#include <k3bdevicemanager.h>
+
+#include <qptrlist.h>
+#include <qmap.h>
+#include <qtextstream.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qapplication.h>
+#include <qcursor.h>
+
+#include <kurl.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+
+class K3bProjectManager::Private
+{
+public:
+ QPtrList<K3bDoc> projects;
+ K3bDoc* activeProject;
+ QMap<K3bDoc*, K3bProjectInterface*> projectInterfaceMap;
+
+ int audioUntitledCount;
+ int dataUntitledCount;
+ int mixedUntitledCount;
+ int vcdUntitledCount;
+ int movixUntitledCount;
+ int movixDvdUntitledCount;
+ int dvdUntitledCount;
+ int videoDvdUntitledCount;
+};
+
+
+
+
+K3bProjectManager::K3bProjectManager( QObject* parent, const char* name )
+ : QObject( parent, name )
+{
+ d = new Private();
+ d->activeProject = 0;
+
+ d->audioUntitledCount = 0;
+ d->dataUntitledCount = 0;
+ d->mixedUntitledCount = 0;
+ d->vcdUntitledCount = 0;
+ d->movixUntitledCount = 0;
+ d->movixDvdUntitledCount = 0;
+ d->dvdUntitledCount = 0;
+ d->videoDvdUntitledCount = 0;
+}
+
+K3bProjectManager::~K3bProjectManager()
+{
+ delete d;
+}
+
+
+const QPtrList<K3bDoc>& K3bProjectManager::projects() const
+{
+ return d->projects;
+}
+
+
+void K3bProjectManager::addProject( K3bDoc* doc )
+{
+ if( !d->projects.containsRef( doc ) ) {
+ kdDebug() << "(K3bProjectManager) adding doc " << doc->URL().path() << endl;
+
+ d->projects.append(doc);
+
+ connect( doc, SIGNAL(changed(K3bDoc*)),
+ this, SLOT(slotProjectChanged(K3bDoc*)) );
+
+ emit newProject( doc );
+ }
+}
+
+
+void K3bProjectManager::removeProject( K3bDoc* doc )
+{
+ //
+ // QPtrList.findRef seems to be buggy. Everytime we search for the
+ // first added item it is not found!
+ //
+ for( QPtrListIterator<K3bDoc> it( d->projects );
+ it.current(); ++it ) {
+ if( it.current() == doc ) {
+
+ // remove the DCOP interface
+ QMap<K3bDoc*, K3bProjectInterface*>::iterator it = d->projectInterfaceMap.find( doc );
+ if( it != d->projectInterfaceMap.end() ) {
+ // delete the interface
+ delete it.data();
+ d->projectInterfaceMap.remove( it );
+ }
+
+ d->projects.removeRef(doc);
+ emit closingProject(doc);
+
+ return;
+ }
+ }
+ kdDebug() << "(K3bProjectManager) unable to find doc: " << doc->URL().path() << endl;
+}
+
+
+K3bDoc* K3bProjectManager::findByUrl( const KURL& url )
+{
+ for( QPtrListIterator<K3bDoc> it( d->projects );
+ it.current(); ++it ) {
+ K3bDoc* doc = it.current();
+ if( doc->URL() == url )
+ return doc;
+ }
+ return 0;
+}
+
+
+bool K3bProjectManager::isEmpty() const
+{
+ return d->projects.isEmpty();
+}
+
+
+void K3bProjectManager::setActive( K3bDoc* doc )
+{
+ if( !doc ) {
+ d->activeProject = 0L;
+ emit activeProjectChanged( 0L );
+ return;
+ }
+
+ //
+ // QPtrList.findRef seems to be buggy. Everytime we search for the
+ // first added item it is not found!
+ //
+ for( QPtrListIterator<K3bDoc> it( d->projects );
+ it.current(); ++it ) {
+ if( it.current() == doc ) {
+ d->activeProject = doc;
+ emit activeProjectChanged(doc);
+ }
+ }
+}
+
+
+K3bDoc* K3bProjectManager::activeProject() const
+{
+ return d->activeProject;
+}
+
+
+K3bDoc* K3bProjectManager::createEmptyProject( K3bDoc::DocType type )
+{
+ K3bDoc* doc = 0;
+ QString fileName;
+
+ switch( type ) {
+ case K3bDoc::AUDIO: {
+ doc = new K3bAudioDoc( this );
+ fileName = i18n("AudioCD%1").arg(d->audioUntitledCount++);
+ break;
+ }
+
+ case K3bDoc::DATA: {
+ doc = new K3bDataDoc( this );
+ fileName = i18n("DataCD%1").arg(d->dataUntitledCount++);
+ break;
+ }
+
+ case K3bDoc::MIXED: {
+ doc = new K3bMixedDoc( this );
+ fileName=i18n("MixedCD%1").arg(d->mixedUntitledCount++);
+ break;
+ }
+
+ case K3bDoc::VCD: {
+ doc = new K3bVcdDoc( this );
+ fileName=i18n("VideoCD%1").arg(d->vcdUntitledCount++);
+ break;
+ }
+
+ case K3bDoc::MOVIX: {
+ doc = new K3bMovixDoc( this );
+ fileName=i18n("eMovixCD%1").arg(d->movixUntitledCount++);
+ break;
+ }
+
+ case K3bDoc::MOVIX_DVD: {
+ doc = new K3bMovixDvdDoc( this );
+ fileName=i18n("eMovixDVD%1").arg(d->movixDvdUntitledCount++);
+ break;
+ }
+
+ case K3bDoc::DVD: {
+ doc = new K3bDvdDoc( this );
+ fileName = i18n("DataDVD%1").arg(d->dvdUntitledCount++);
+ break;
+ }
+
+ case K3bDoc::VIDEODVD: {
+ doc = new K3bVideoDvdDoc( this );
+ fileName = i18n("VideoDVD%1").arg(d->videoDvdUntitledCount++);
+ break;
+ }
+ }
+
+ KURL url;
+ url.setFileName(fileName);
+ doc->setURL(url);
+
+ doc->newDocument();
+
+ loadDefaults( doc );
+
+ return doc;
+}
+
+
+K3bDoc* K3bProjectManager::createProject( K3bDoc::DocType type )
+{
+ K3bDoc* doc = createEmptyProject( type );
+
+ // create the dcop interface
+ dcopInterface( doc );
+
+ addProject( doc );
+
+ return doc;
+}
+
+
+void K3bProjectManager::loadDefaults( K3bDoc* doc )
+{
+ KConfig* c = kapp->config();
+
+ QString oldGroup = c->group();
+
+ QString cg = "default " + doc->typeString() + " settings";
+
+ // earlier K3b versions loaded the saved settings
+ // so that is what we do as a default
+ int i = KConfigGroup( c, "General Options" ).readNumEntry( "action dialog startup settings",
+ K3bInteractionDialog::LOAD_SAVED_SETTINGS );
+ if( i == K3bInteractionDialog::LOAD_K3B_DEFAULTS )
+ return; // the default k3b settings are the ones everyone starts with
+ else if( i == K3bInteractionDialog::LOAD_LAST_SETTINGS )
+ cg = "last used " + cg;
+
+ c->setGroup( cg );
+
+ QString mode = c->readEntry( "writing_mode" );
+ if ( mode == "dao" )
+ doc->setWritingMode( K3b::DAO );
+ else if( mode == "tao" )
+ doc->setWritingMode( K3b::TAO );
+ else if( mode == "raw" )
+ doc->setWritingMode( K3b::RAW );
+ else
+ doc->setWritingMode( K3b::WRITING_MODE_AUTO );
+
+ doc->setDummy( c->readBoolEntry( "simulate", false ) );
+ doc->setOnTheFly( c->readBoolEntry( "on_the_fly", true ) );
+ doc->setRemoveImages( c->readBoolEntry( "remove_image", true ) );
+ doc->setOnlyCreateImages( c->readBoolEntry( "only_create_image", false ) );
+ doc->setBurner( k3bcore->deviceManager()->findDevice( c->readEntry( "writer_device" ) ) );
+ // Default = 0 (Auto)
+ doc->setSpeed( c->readNumEntry( "writing_speed", 0 ) );
+ doc->setWritingApp( K3b::writingAppFromString( c->readEntry( "writing_app" ) ) );
+
+
+ switch( doc->type() ) {
+ case K3bDoc::AUDIO: {
+ K3bAudioDoc* audioDoc = static_cast<K3bAudioDoc*>(doc);
+
+ audioDoc->writeCdText( c->readBoolEntry( "cd_text", true ) );
+ audioDoc->setHideFirstTrack( c->readBoolEntry( "hide_first_track", false ) );
+ audioDoc->setNormalize( c->readBoolEntry( "normalize", false ) );
+ audioDoc->setAudioRippingParanoiaMode( c->readNumEntry( "paranoia mode", 0 ) );
+ audioDoc->setAudioRippingRetries( c->readNumEntry( "read retries", 128 ) );
+ audioDoc->setAudioRippingIgnoreReadErrors( c->readBoolEntry( "ignore read errors", false ) );
+
+ break;
+ }
+
+ case K3bDoc::MOVIX:
+ case K3bDoc::MOVIX_DVD: {
+ K3bMovixDoc* movixDoc = static_cast<K3bMovixDoc*>(doc);
+
+ movixDoc->setSubtitleFontset( c->readEntry("subtitle_fontset") );
+
+ movixDoc->setLoopPlaylist( c->readNumEntry("loop", 1 ) );
+ movixDoc->setAdditionalMPlayerOptions( c->readEntry( "additional_mplayer_options" ) );
+ movixDoc->setUnwantedMPlayerOptions( c->readEntry( "unwanted_mplayer_options" ) );
+
+ movixDoc->setBootMessageLanguage( c->readEntry("boot_message_language") );
+
+ movixDoc->setDefaultBootLabel( c->readEntry( "default_boot_label" ) );
+
+ movixDoc->setShutdown( c->readBoolEntry( "shutdown", false) );
+ movixDoc->setReboot( c->readBoolEntry( "reboot", false ) );
+ movixDoc->setEjectDisk( c->readBoolEntry( "eject", false ) );
+ movixDoc->setRandomPlay( c->readBoolEntry( "random_play", false ) );
+ movixDoc->setNoDma( c->readBoolEntry( "no_dma", false ) );
+ // fallthrough
+ }
+
+ case K3bDoc::DATA:
+ case K3bDoc::DVD: {
+ K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>(doc);
+
+ dataDoc->setIsoOptions( K3bIsoOptions::load( c, false ) );
+
+ QString datamode = c->readEntry( "data_track_mode" );
+ if( datamode == "mode1" )
+ dataDoc->setDataMode( K3b::MODE1 );
+ else if( datamode == "mode2" )
+ dataDoc->setDataMode( K3b::MODE2 );
+ else
+ dataDoc->setDataMode( K3b::DATA_MODE_AUTO );
+
+ dataDoc->setVerifyData( c->readBoolEntry( "verify data", false ) );
+
+ QString s = c->readEntry( "multisession mode" );
+ if( s == "none" )
+ dataDoc->setMultiSessionMode( K3bDataDoc::NONE );
+ else if( s == "start" )
+ dataDoc->setMultiSessionMode( K3bDataDoc::START );
+ else if( s == "continue" )
+ dataDoc->setMultiSessionMode( K3bDataDoc::CONTINUE );
+ else if( s == "finish" )
+ dataDoc->setMultiSessionMode( K3bDataDoc::FINISH );
+ else
+ dataDoc->setMultiSessionMode( K3bDataDoc::AUTO );
+
+ break;
+ }
+
+ case K3bDoc::VIDEODVD: {
+ // the only defaults we need here are the volume id and stuff
+ K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>(doc);
+ dataDoc->setIsoOptions( K3bIsoOptions::load( c, false ) );
+ dataDoc->setVerifyData( c->readBoolEntry( "verify data", false ) );
+ break;
+ }
+
+ case K3bDoc::MIXED: {
+ K3bMixedDoc* mixedDoc = static_cast<K3bMixedDoc*>(doc);
+
+ mixedDoc->audioDoc()->writeCdText( c->readBoolEntry( "cd_text", true ) );
+ mixedDoc->audioDoc()->setNormalize( c->readBoolEntry( "normalize", false ) );
+
+ // load mixed type
+ if( c->readEntry( "mixed_type" ) == "last_track" )
+ mixedDoc->setMixedType( K3bMixedDoc::DATA_LAST_TRACK );
+ else if( c->readEntry( "mixed_type" ) == "first_track" )
+ mixedDoc->setMixedType( K3bMixedDoc::DATA_FIRST_TRACK );
+ else
+ mixedDoc->setMixedType( K3bMixedDoc::DATA_SECOND_SESSION );
+
+ QString datamode = c->readEntry( "data_track_mode" );
+ if( datamode == "mode1" )
+ mixedDoc->dataDoc()->setDataMode( K3b::MODE1 );
+ else if( datamode == "mode2" )
+ mixedDoc->dataDoc()->setDataMode( K3b::MODE2 );
+ else
+ mixedDoc->dataDoc()->setDataMode( K3b::DATA_MODE_AUTO );
+
+ mixedDoc->dataDoc()->setIsoOptions( K3bIsoOptions::load( c, false ) );
+
+ if( mixedDoc->dataDoc()->isoOptions().volumeID().isEmpty() )
+ mixedDoc->dataDoc()->setVolumeID( doc->URL().fileName() );
+
+ break;
+ }
+
+ case K3bDoc::VCD: {
+ K3bVcdDoc* vcdDoc = static_cast<K3bVcdDoc*>(doc);
+
+ // FIXME: I think we miss a lot here!
+
+ vcdDoc->vcdOptions()->setPbcEnabled( c->readBoolEntry( "Use Playback Control", false ) );
+ vcdDoc->vcdOptions()->setPbcNumkeysEnabled( c->readBoolEntry( "Use numeric keys to navigate chapters", false ) );
+ vcdDoc->vcdOptions()->setPbcPlayTime( c->readNumEntry( "Play each Sequence/Segment", 1 ) );
+ vcdDoc->vcdOptions()->setPbcWaitTime( c->readNumEntry( "Time to wait after each Sequence/Segment", 2 ) );
+
+ if( vcdDoc->vcdOptions()->volumeId().isEmpty() )
+ vcdDoc->vcdOptions()->setVolumeId( doc->URL().fileName() );
+
+ break;
+ }
+ }
+
+ if( doc->type() == K3bDoc::DATA ||
+ doc->type() == K3bDoc::MOVIX ||
+ doc->type() == K3bDoc::MOVIX_DVD ||
+ doc->type() == K3bDoc::VIDEODVD ||
+ doc->type() == K3bDoc::DVD ) {
+ if( static_cast<K3bDataDoc*>(doc)->isoOptions().volumeID().isEmpty() )
+ static_cast<K3bDataDoc*>(doc)->setVolumeID( doc->URL().fileName() );
+ }
+
+ doc->setModified( false );
+
+ c->setGroup( oldGroup );
+}
+
+
+K3bProjectInterface* K3bProjectManager::dcopInterface( K3bDoc* doc )
+{
+ QMap<K3bDoc*, K3bProjectInterface*>::iterator it = d->projectInterfaceMap.find( doc );
+ if( it == d->projectInterfaceMap.end() ) {
+ K3bProjectInterface* dcopInterface = 0;
+ if( doc->type() == K3bDoc::DATA || doc->type() == K3bDoc::DVD )
+ dcopInterface = new K3bDataProjectInterface( static_cast<K3bDataDoc*>(doc) );
+ else if( doc->type() == K3bDoc::AUDIO )
+ dcopInterface = new K3bAudioProjectInterface( static_cast<K3bAudioDoc*>(doc) );
+ else if( doc->type() == K3bDoc::MIXED )
+ dcopInterface = new K3bMixedProjectInterface( static_cast<K3bMixedDoc*>(doc) );
+ else
+ dcopInterface = new K3bProjectInterface( doc );
+ d->projectInterfaceMap[doc] = dcopInterface;
+ return dcopInterface;
+ }
+ else
+ return it.data();
+}
+
+
+K3bDoc* K3bProjectManager::openProject( const KURL& url )
+{
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+
+ QString tmpfile;
+ KIO::NetAccess::download( url, tmpfile, 0L );
+
+ // ///////////////////////////////////////////////
+ // first check if it's a store or an old plain xml file
+ bool success = false;
+ QDomDocument xmlDoc;
+
+ // try opening a store
+ KoStore* store = KoStore::createStore( tmpfile, KoStore::Read );
+ if( store ) {
+ if( !store->bad() ) {
+ // try opening the document inside the store
+ if( store->open( "maindata.xml" ) ) {
+ QIODevice* dev = store->device();
+ dev->open( IO_ReadOnly );
+ if( xmlDoc.setContent( dev ) )
+ success = true;
+ dev->close();
+ store->close();
+ }
+ }
+
+ delete store;
+ }
+
+ if( !success ) {
+ // try reading an old plain document
+ QFile f( tmpfile );
+ if ( f.open( IO_ReadOnly ) ) {
+ //
+ // First check if this is really an xml file beacuse if this is a very big file
+ // the setContent method blocks for a very long time
+ //
+ char test[5];
+ if( f.readBlock( test, 5 ) ) {
+ if( ::strncmp( test, "<?xml", 5 ) ) {
+ kdDebug() << "(K3bDoc) " << url.path() << " seems to be no xml file." << endl;
+ QApplication::restoreOverrideCursor();
+ return 0;
+ }
+ f.reset();
+ }
+ else {
+ kdDebug() << "(K3bDoc) could not read from file." << endl;
+ QApplication::restoreOverrideCursor();
+ return 0;
+ }
+ if( xmlDoc.setContent( &f ) )
+ success = true;
+ f.close();
+ }
+ }
+
+ // ///////////////////////////////////////////////
+ KIO::NetAccess::removeTempFile( tmpfile );
+
+ if( !success ) {
+ kdDebug() << "(K3bDoc) could not open file " << url.path() << endl;
+ QApplication::restoreOverrideCursor();
+ return 0;
+ }
+
+ // check the documents DOCTYPE
+ K3bDoc::DocType type = K3bDoc::AUDIO;
+ if( xmlDoc.doctype().name() == "k3b_audio_project" )
+ type = K3bDoc::AUDIO;
+ else if( xmlDoc.doctype().name() == "k3b_data_project" )
+ type = K3bDoc::DATA;
+ else if( xmlDoc.doctype().name() == "k3b_vcd_project" )
+ type = K3bDoc::VCD;
+ else if( xmlDoc.doctype().name() == "k3b_mixed_project" )
+ type = K3bDoc::MIXED;
+ else if( xmlDoc.doctype().name() == "k3b_movix_project" )
+ type = K3bDoc::MOVIX;
+ else if( xmlDoc.doctype().name() == "k3b_movixdvd_project" )
+ type = K3bDoc::MOVIX_DVD;
+ else if( xmlDoc.doctype().name() == "k3b_dvd_project" )
+ type = K3bDoc::DVD;
+ else if( xmlDoc.doctype().name() == "k3b_video_dvd_project" )
+ type = K3bDoc::VIDEODVD;
+ else {
+ kdDebug() << "(K3bDoc) unknown doc type: " << xmlDoc.doctype().name() << endl;
+ QApplication::restoreOverrideCursor();
+ return 0;
+ }
+
+ // we do not know yet if we will be able to actually open the project, so don't inform others yet
+ K3bDoc* newDoc = createEmptyProject( type );
+
+ // ---------
+ // load the data into the document
+ QDomElement root = xmlDoc.documentElement();
+ if( newDoc->loadDocumentData( &root ) ) {
+ newDoc->setURL( url );
+ newDoc->setSaved( true );
+ newDoc->setModified( false );
+
+ // ok, finish the doc setup, inform the others about the new project
+ dcopInterface( newDoc );
+ addProject( newDoc );
+
+ // FIXME: find a better way to tell everyone (especially the projecttabwidget)
+ // that the doc is not changed
+ emit projectSaved( newDoc );
+
+ kdDebug() << "(K3bProjectManager) loading project done." << endl;
+ }
+ else {
+ delete newDoc;
+ newDoc = 0;
+ }
+
+ QApplication::restoreOverrideCursor();
+
+ return newDoc;
+}
+
+
+bool K3bProjectManager::saveProject( K3bDoc* doc, const KURL& url )
+{
+ QString tmpfile;
+ KIO::NetAccess::download( url, tmpfile, 0L );
+
+ bool success = false;
+
+ // create the store
+ KoStore* store = KoStore::createStore( tmpfile, KoStore::Write, "application/x-k3b" );
+ if( store ) {
+ if( store->bad() ) {
+ delete store;
+ }
+ else {
+ // open the document inside the store
+ store->open( "maindata.xml" );
+
+ // save the data in the document
+ QDomDocument xmlDoc( "k3b_" + doc->typeString() + "_project" );
+
+ xmlDoc.appendChild( xmlDoc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
+ QDomElement docElem = xmlDoc.createElement( "k3b_" + doc->typeString() + "_project" );
+ xmlDoc.appendChild( docElem );
+ success = doc->saveDocumentData( &docElem );
+ if( success ) {
+ KoStoreDevice dev(store);
+ dev.open( IO_WriteOnly );
+ QTextStream xmlStream( &dev );
+ xmlDoc.save( xmlStream, 0 );
+
+ doc->setURL( url );
+ doc->setModified( false );
+ }
+
+ // close the document inside the store
+ store->close();
+
+ // remove the store (destructor writes the store to disk)
+ delete store;
+
+ doc->setSaved( success );
+
+ if( success ) {
+ emit projectSaved( doc );
+ }
+ }
+ }
+
+ KIO::NetAccess::removeTempFile( tmpfile );
+
+ return success;
+}
+
+
+void K3bProjectManager::slotProjectChanged( K3bDoc* doc )
+{
+ emit projectChanged( doc );
+}
+
+#include "k3bprojectmanager.moc"
diff --git a/src/k3bprojectmanager.h b/src/k3bprojectmanager.h
new file mode 100644
index 0000000..60d9c80
--- /dev/null
+++ b/src/k3bprojectmanager.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_PROJECT_MANAGER_H_
+#define _K3B_PROJECT_MANAGER_H_
+
+#include <qobject.h>
+#include <qptrlist.h>
+#include <k3bdoc.h>
+
+
+class KURL;
+class K3bProjectInterface;
+
+
+class K3bProjectManager : public QObject
+{
+ Q_OBJECT
+
+ public:
+ K3bProjectManager( QObject* parent = 0, const char* name = 0 );
+ virtual ~K3bProjectManager();
+
+ const QPtrList<K3bDoc>& projects() const;
+
+ /**
+ * Create a new project including loading user defaults and creating
+ * the dcop interface.
+ */
+ K3bDoc* createProject( K3bDoc::DocType type );
+
+ /**
+ * Opens a K3b project.
+ * \return 0 if url does not point to a valid k3b project file, the new project otherwise.
+ */
+ K3bDoc* openProject( const KURL &url );
+
+ /**
+ * saves the document under filename and format.
+ */
+ bool saveProject( K3bDoc*, const KURL &url );
+
+ K3bDoc* activeDoc() const { return activeProject(); }
+ K3bDoc* activeProject() const;
+ K3bDoc* findByUrl( const KURL& url );
+ bool isEmpty() const;
+
+ /**
+ * Will create if none exists.
+ */
+ K3bProjectInterface* dcopInterface( K3bDoc* doc );
+
+ public slots:
+ void addProject( K3bDoc* );
+ void removeProject( K3bDoc* );
+ void setActive( K3bDoc* );
+ void loadDefaults( K3bDoc* );
+
+ signals:
+ void newProject( K3bDoc* );
+ void projectSaved( K3bDoc* );
+ void closingProject( K3bDoc* );
+ void projectChanged( K3bDoc* doc );
+ void activeProjectChanged( K3bDoc* );
+
+ private slots:
+ void slotProjectChanged( K3bDoc* doc );
+
+ private:
+ // used internal
+ K3bDoc* createEmptyProject( K3bDoc::DocType );
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3bprojecttabwidget.cpp b/src/k3bprojecttabwidget.cpp
new file mode 100644
index 0000000..d86fad4
--- /dev/null
+++ b/src/k3bprojecttabwidget.cpp
@@ -0,0 +1,216 @@
+/*
+ *
+ * $Id: k3bprojecttabwidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#include "k3bprojecttabwidget.h"
+#include "k3bapplication.h"
+#include "k3bprojectmanager.h"
+
+#include <k3bview.h>
+#include <k3bdoc.h>
+
+#include <kaction.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kurldrag.h>
+#include <klocale.h>
+
+#include <qevent.h>
+#include <qtabbar.h>
+
+
+class K3bProjectTabWidget::ProjectData
+{
+public:
+ ProjectData()
+ : doc(0),
+ modified(false) {
+ }
+
+ ProjectData( K3bDoc* doc_ )
+ : doc(doc_),
+ modified(false) {
+ }
+
+ // the project
+ K3bDoc* doc;
+
+ // is the project marked modified here
+ bool modified;
+};
+
+
+
+K3bProjectTabWidget::K3bProjectTabWidget( QWidget *parent, const char *name, WFlags f )
+ : QTabWidget( parent, name, f )
+{
+ tabBar()->setAcceptDrops(true);
+ tabBar()->installEventFilter( this );
+
+ m_projectActionMenu = new KActionMenu( i18n("Project"), this );
+}
+
+
+K3bProjectTabWidget::~K3bProjectTabWidget()
+{
+}
+
+
+void K3bProjectTabWidget::addTab( QWidget* child, const QString& label )
+{
+ QTabWidget::addTab( child, label );
+ tabBar()->setShown( count() != 1 );
+}
+
+
+void K3bProjectTabWidget::addTab( QWidget* child, const QIconSet& iconset, const QString& label )
+{
+ QTabWidget::addTab( child, iconset, label );
+ tabBar()->setShown( count() != 1 );
+}
+
+
+void K3bProjectTabWidget::addTab( QWidget* child, QTab* tab )
+{
+ QTabWidget::addTab( child, tab );
+ tabBar()->setShown( count() != 1 );
+}
+
+
+void K3bProjectTabWidget::insertTab( QWidget* child, const QString& label, int index )
+{
+ QTabWidget::insertTab( child, label, index );
+ tabBar()->setShown( count() != 1 );
+}
+
+
+void K3bProjectTabWidget::insertTab( QWidget* child, const QIconSet& iconset, const QString& label, int index )
+{
+ QTabWidget::insertTab( child, iconset, label, index );
+ tabBar()->setShown( count() != 1 );
+}
+
+
+void K3bProjectTabWidget::insertTab( QWidget* child, QTab* tab, int index )
+{
+ QTabWidget::insertTab( child, tab, index );
+ tabBar()->setShown( count() != 1 );
+}
+
+
+void K3bProjectTabWidget::removePage( QWidget* w )
+{
+ QTabWidget::removePage( w );
+ tabBar()->setShown( count() != 1 );
+}
+
+
+void K3bProjectTabWidget::insertTab( K3bDoc* doc )
+{
+ QTabWidget::insertTab( doc->view(), doc->URL().fileName() );
+ connect( k3bappcore->projectManager(), SIGNAL(projectSaved(K3bDoc*)), this, SLOT(slotDocSaved(K3bDoc*)) );
+ connect( doc, SIGNAL(changed(K3bDoc*)), this, SLOT(slotDocChanged(K3bDoc*)) );
+
+ m_projectDataMap[doc] = ProjectData( doc );
+
+ if( doc->isModified() )
+ slotDocChanged( doc );
+ else
+ slotDocSaved( doc );
+}
+
+
+void K3bProjectTabWidget::insertAction( KAction* action )
+{
+ m_projectActionMenu->insert( action );
+}
+
+
+void K3bProjectTabWidget::slotDocChanged( K3bDoc* doc )
+{
+ // we need to cache the icon changes since the changed() signal will be emitted very often
+ if( !m_projectDataMap[doc].modified ) {
+ setTabIconSet( doc->view(), SmallIconSet( "filesave" ) );
+ m_projectDataMap[doc].modified = true;
+
+ // we need this one for the session management
+ changeTab( doc->view(), doc->URL().fileName() );
+ }
+}
+
+
+void K3bProjectTabWidget::slotDocSaved( K3bDoc* doc )
+{
+ setTabIconSet( doc->view(), QIconSet() );
+ changeTab( doc->view(), doc->URL().fileName() );
+}
+
+
+K3bDoc* K3bProjectTabWidget::projectAt( const QPoint& pos ) const
+{
+ QTab* tab = tabBar()->selectTab( pos );
+ if( tab ) {
+ QWidget* w = page( tabBar()->indexOf( tab->identifier() ) );
+ if( K3bView* view = dynamic_cast<K3bView*>(w) )
+ return view->doc();
+ }
+
+ return 0;
+}
+
+
+bool K3bProjectTabWidget::eventFilter( QObject* o, QEvent* e )
+{
+ if( o == tabBar() ) {
+ if( e->type() == QEvent::MouseButtonPress ) {
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ if( me->button() == Qt::RightButton ) {
+ if( projectAt( me->pos() ) ) {
+ // we need change the tab because the actions work on the current tab
+ QTab* clickedTab = tabBar()->selectTab( me->pos() );
+ if( clickedTab ) {
+ tabBar()->setCurrentTab( clickedTab );
+
+ // show the popup menu
+ m_projectActionMenu->popup( me->globalPos() );
+ }
+ }
+ return true;
+ }
+ }
+
+ else if( e->type() == QEvent::DragMove ) {
+ QDragMoveEvent* de = static_cast<QDragMoveEvent*>(e);
+ de->accept( KURLDrag::canDecode(de) && projectAt(de->pos()) );
+ return true;
+ }
+
+ else if( e->type() == QEvent::Drop ) {
+ QDropEvent* de = static_cast<QDropEvent*>(e);
+ KURL::List l;
+ if( KURLDrag::decode( de, l ) ) {
+ if( K3bDoc* doc = projectAt( de->pos() ) )
+ dynamic_cast<K3bView*>(doc->view())->addUrls( l );
+ }
+ return true;
+ }
+ }
+
+ return QTabWidget::eventFilter( o, e );
+}
+
+#include "k3bprojecttabwidget.moc"
+
diff --git a/src/k3bprojecttabwidget.h b/src/k3bprojecttabwidget.h
new file mode 100644
index 0000000..048a8bc
--- /dev/null
+++ b/src/k3bprojecttabwidget.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * $Id: k3bprojecttabwidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BPROJECTTABWIDGET_H
+#define K3BPROJECTTABWIDGET_H
+
+#include <qtabwidget.h>
+#include <kurl.h>
+
+class KAction;
+class KActionMenu;
+class K3bDoc;
+
+
+/**
+ * An enhanced Tab Widget that hides the tabbar in case only one page has been inserted
+ * and shows a context menu fpr K3b projects.
+ *
+ * @author Sebastian Trueg
+ */
+class K3bProjectTabWidget : public QTabWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bProjectTabWidget( QWidget *parent = 0, const char *name = 0, WFlags = 0 );
+ ~K3bProjectTabWidget();
+
+ void insertTab( K3bDoc* );
+
+ void addTab( QWidget * child, const QString & label );
+ void addTab( QWidget * child, const QIconSet & iconset, const QString & label );
+ void addTab( QWidget * child, QTab * tab );
+ void insertTab( QWidget * child, const QString & label, int index = -1 );
+ void insertTab( QWidget * child, const QIconSet & iconset, const QString & label, int index = -1 );
+ void insertTab( QWidget * child, QTab * tab, int index = -1 );
+
+ /**
+ * \return the project for the tab at position \p pos or 0 in case the tab is
+ * not a project tab.
+ */
+ K3bDoc* projectAt( const QPoint& pos ) const;
+
+ /**
+ * inserts the given action into the popup menu for the tabs
+ */
+ void insertAction( KAction* );
+
+ bool eventFilter( QObject* o, QEvent* e );
+
+ public slots:
+ void removePage( QWidget* );
+
+ private slots:
+ void slotDocChanged( K3bDoc* );
+ void slotDocSaved( K3bDoc* );
+
+ private:
+ KActionMenu* m_projectActionMenu;
+
+ class ProjectData;
+ QMap<K3bDoc*, ProjectData> m_projectDataMap;
+};
+
+#endif
diff --git a/src/k3bservicemenuinstaller.cpp b/src/k3bservicemenuinstaller.cpp
new file mode 100644
index 0000000..82122e2
--- /dev/null
+++ b/src/k3bservicemenuinstaller.cpp
@@ -0,0 +1,119 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bservicemenuinstaller.h"
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <kdebug.h>
+
+
+class K3bServiceInstaller::Private
+{
+public:
+ QString app;
+ QStringList allServiceMenus;
+ QStringList allServiceMenuFiles;
+ QString konqiServicemenusFolder;
+
+ void update() {
+ // the list of installable servicemenus the application provides
+ allServiceMenus = KGlobal::dirs()->findAllResources( "data",
+ "k3b/servicemenus/*.desktop",
+ false,
+ true );
+
+ // just the filenames
+ allServiceMenuFiles.clear();
+ for( unsigned int i = 0; i < allServiceMenus.count(); ++i )
+ allServiceMenuFiles.append( allServiceMenus[i].section( '/', -1 ) );
+
+ // the local konqueror servicemenu folder (we just create it here to be on the safe side)
+ konqiServicemenusFolder = KGlobal::dirs()->saveLocation( "data", "konqueror/servicemenus/", true );
+ }
+};
+
+
+K3bServiceInstaller::K3bServiceInstaller( const QString& appname )
+{
+ d = new Private;
+ d->app = appname;
+}
+
+
+K3bServiceInstaller::~K3bServiceInstaller()
+{
+ delete d;
+}
+
+
+bool K3bServiceInstaller::allInstalled() const
+{
+ d->update();
+
+ for( unsigned int i = 0; i < d->allServiceMenuFiles.count(); ++i )
+ if( !KIO::NetAccess::exists( d->konqiServicemenusFolder + d->allServiceMenuFiles[i], true, 0 ) ) {
+ kdDebug() << "(K3bServiceInstaller) service menu " << d->konqiServicemenusFolder << d->allServiceMenuFiles[i]
+ << " does not exist." << endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+bool K3bServiceInstaller::install( QWidget* parent )
+{
+ d->update();
+
+ bool success = true;
+
+ // simply link all the globally installed K3b service menus to the local konqi service menu folder
+ for( unsigned int i = 0; i < d->allServiceMenus.count(); ++i )
+ if( !KIO::NetAccess::file_copy( KURL::fromPathOrURL( d->allServiceMenus[i] ),
+ KURL::fromPathOrURL( d->konqiServicemenusFolder + d->allServiceMenuFiles[i] ), -1,
+ true, false, parent ) )
+ success = false;
+
+ if( !success && parent )
+ KMessageBox::error( parent,
+ KIO::NetAccess::lastErrorString(),
+ i18n("Failed to copy service menu files") );
+
+ return success;
+}
+
+
+bool K3bServiceInstaller::remove( QWidget* parent )
+{
+ d->update();
+
+ bool success = true;
+
+ for( unsigned int i = 0; i < d->allServiceMenuFiles.count(); ++i )
+ if( KIO::NetAccess::exists( d->konqiServicemenusFolder + d->allServiceMenuFiles[i], true, parent ) )
+ if( !KIO::NetAccess::del( d->konqiServicemenusFolder + d->allServiceMenuFiles[i], parent ) )
+ success = false;
+
+ if( !success && parent )
+ KMessageBox::error( parent,
+ KIO::NetAccess::lastErrorString(),
+ i18n("Failed to remove service menu files") );
+
+ return success;
+}
diff --git a/src/k3bservicemenuinstaller.h b/src/k3bservicemenuinstaller.h
new file mode 100644
index 0000000..6e06caf
--- /dev/null
+++ b/src/k3bservicemenuinstaller.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_SERVICE_MENU_INSTALLER_H_
+#define _K3B_SERVICE_MENU_INSTALLER_H_
+
+#include <qstring.h>
+
+class QWidget;
+
+
+/**
+ * The K3bServiceInstaller installs konqueror servicemenus locally.
+ * These servicemenus have to be installed in the appdata dir under
+ * the subfolder "servicemenus".
+ */
+class K3bServiceInstaller
+{
+ public:
+ K3bServiceInstaller( const QString& appname = "k3b" );
+ ~K3bServiceInstaller();
+
+ /**
+ * Checks if all servicemenus are properly installed.
+ */
+ bool allInstalled() const;
+
+ /**
+ * If parent != 0 a messagebox will be shown in case of an error.
+ */
+ bool install( QWidget* parent = 0 );
+
+ /**
+ * If parent != 0 a messagebox will be shown in case of an error.
+ */
+ bool remove( QWidget* parent = 0 );
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3bsidepanel.cpp b/src/k3bsidepanel.cpp
new file mode 100644
index 0000000..8e40352
--- /dev/null
+++ b/src/k3bsidepanel.cpp
@@ -0,0 +1,108 @@
+/*
+ *
+ * $Id: k3bsidepanel.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bsidepanel.h"
+#include "k3b.h"
+#include "k3bfiletreeview.h"
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include <qtoolbutton.h>
+#include <qframe.h>
+#include <qlayout.h>
+
+
+
+K3bSidePanel::K3bSidePanel( K3bMainWindow* m, QWidget* parent, const char* name )
+ : QToolBox( parent, name ),
+ m_mainWindow(m)
+{
+ // our first widget is the tree view
+ m_fileTreeView = new K3bFileTreeView( this );
+ addItem( m_fileTreeView, SmallIconSet( "folder_open" ), i18n("Folders") );
+
+ // CD projects
+ QFrame* cdProjectsFrame = createPanel();
+ addItem( cdProjectsFrame, SmallIconSet( "cdrom_unmount" ), i18n("CD Tasks") );
+ addButton( cdProjectsFrame, m_mainWindow->action( "file_new_audio" ) );
+ addButton( cdProjectsFrame, m_mainWindow->action( "file_new_data" ) );
+ addButton( cdProjectsFrame, m_mainWindow->action( "file_new_mixed" ) );
+ addButton( cdProjectsFrame, m_mainWindow->action( "file_new_vcd" ) );
+ addButton( cdProjectsFrame, m_mainWindow->action( "file_new_movix" ) );
+ QGridLayout* grid = (QGridLayout*)cdProjectsFrame->layout();
+ grid->setRowSpacing( grid->numRows(), 15 );
+ addButton( cdProjectsFrame, m_mainWindow->action( "tools_copy_cd" ) );
+ addButton( cdProjectsFrame, m_mainWindow->action( "tools_write_cd_image" ) );
+ addButton( cdProjectsFrame, m_mainWindow->action( "tools_blank_cdrw" ) );
+ grid->setRowStretch( grid->numRows()+1, 1 );
+
+ // DVD projects
+ QFrame* dvdProjectsFrame = createPanel();
+ addItem( dvdProjectsFrame, SmallIconSet( "dvd_unmount" ), i18n("DVD Tasks") );
+ addButton( dvdProjectsFrame, m_mainWindow->action( "file_new_dvd" ) );
+ addButton( dvdProjectsFrame, m_mainWindow->action( "file_new_video_dvd" ) );
+ addButton( dvdProjectsFrame, m_mainWindow->action( "file_new_movix_dvd" ) );
+ grid = (QGridLayout*)dvdProjectsFrame->layout();
+ grid->setRowSpacing( grid->numRows(), 15 );
+ addButton( dvdProjectsFrame, m_mainWindow->action( "tools_copy_dvd" ) );
+ addButton( dvdProjectsFrame, m_mainWindow->action( "tools_write_dvd_iso" ) );
+ addButton( dvdProjectsFrame, m_mainWindow->action( "tools_format_dvd" ) );
+ grid->setRowStretch( grid->numRows()+1, 1 );
+
+
+ // Tools
+ // TODO sidepanel tools
+}
+
+
+K3bSidePanel::~K3bSidePanel()
+{
+}
+
+
+QFrame* K3bSidePanel::createPanel()
+{
+ QFrame* frame = new QFrame( this );
+ frame->setPaletteBackgroundColor( Qt::white );
+ QGridLayout* grid = new QGridLayout( frame );
+ grid->setMargin( 5 );
+ grid->setSpacing( 5 );
+ return frame;
+}
+
+
+void K3bSidePanel::addButton( QFrame* frame, KAction* a )
+{
+ if( a ) {
+ QToolButton* b = new QToolButton( frame );
+ b->setTextLabel( a->toolTip(), true );
+ b->setTextLabel( a->text(), false );
+ b->setIconSet( a->iconSet(KIcon::Small) );
+ b->setUsesTextLabel( true );
+ b->setAutoRaise( true );
+ b->setTextPosition( QToolButton::BesideIcon );
+
+ connect( b, SIGNAL(clicked()), a, SLOT(activate()) );
+
+ QGridLayout* grid = (QGridLayout*)(frame->layout());
+ grid->addWidget( b, grid->numRows(), 0 );
+ }
+ else
+ kdDebug() << "(K3bSidePanel) null action." << endl;
+}
+
+#include "k3bsidepanel.moc"
diff --git a/src/k3bsidepanel.h b/src/k3bsidepanel.h
new file mode 100644
index 0000000..2be17ff
--- /dev/null
+++ b/src/k3bsidepanel.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * $Id: k3bsidepanel.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_SIDE_PANEL_H_
+#define _K3B_SIDE_PANEL_H_
+
+#include <qtoolbox.h>
+
+class K3bMainWindow;
+class K3bFileTreeView;
+class QFrame;
+class KAction;
+
+
+class K3bSidePanel : public QToolBox
+{
+ Q_OBJECT
+
+ public:
+ K3bSidePanel( K3bMainWindow*, QWidget* parent = 0, const char* name = 0 );
+ ~K3bSidePanel();
+
+ /**
+ * This should be removed in the future. For now we need it because of the
+ * bad design of the dirview. :(
+ */
+ K3bFileTreeView* fileTreeView() const { return m_fileTreeView; }
+
+ private:
+ K3bMainWindow* m_mainWindow;
+ K3bFileTreeView* m_fileTreeView;
+
+ QFrame* createPanel();
+ void addButton( QFrame* frame, KAction* action );
+};
+
+#endif
diff --git a/src/k3bsplash.cpp b/src/k3bsplash.cpp
new file mode 100644
index 0000000..dc49bf5
--- /dev/null
+++ b/src/k3bsplash.cpp
@@ -0,0 +1,129 @@
+/*
+ *
+ * $Id: k3bsplash.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bsplash.h"
+
+#include <k3bthememanager.h>
+#include <k3bapplication.h>
+
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qevent.h>
+#include <qstring.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+
+
+K3bSplash::K3bSplash( QWidget* parent, const char* name )
+ : QVBox( parent, name,
+ WStyle_Customize|
+ WDestructiveClose|
+ /* WStyle_Splash|*/
+ WX11BypassWM|
+ WStyle_NoBorder|
+ WStyle_StaysOnTop )
+{
+ setMargin( 0 );
+ setSpacing( 0 );
+
+ QLabel* copyrightLabel = new QLabel( kapp->aboutData()->copyrightStatement(), this );
+ copyrightLabel->setMargin( 5 );
+ copyrightLabel->setPaletteBackgroundColor( black );
+ copyrightLabel->setPaletteForegroundColor( white );
+ copyrightLabel->setAlignment( AlignRight );
+
+ QLabel* picLabel = new QLabel( this );
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ picLabel->setPaletteBackgroundColor( theme->backgroundColor() );
+ picLabel->setPixmap( theme->pixmap( K3bTheme::SPLASH ) );
+ }
+
+ m_infoBox = new QLabel( this );
+ m_infoBox->setMargin( 5 );
+ m_infoBox->setPaletteBackgroundColor( black );
+ m_infoBox->setPaletteForegroundColor( white );
+
+ // Set geometry, with support for Xinerama systems
+ QRect r;
+ r.setSize(sizeHint());
+ int ps = QApplication::desktop()->primaryScreen();
+ r.moveCenter( QApplication::desktop()->screenGeometry(ps).center() );
+ setGeometry(r);
+}
+
+
+K3bSplash::~K3bSplash()
+{
+}
+
+
+void K3bSplash::mousePressEvent( QMouseEvent* )
+{
+ close();
+}
+
+
+void K3bSplash::show()
+{
+ QVBox::show();
+ // make sure the splash screen is shown immediately
+ qApp->processEvents();
+}
+
+
+void K3bSplash::addInfo( const QString& s )
+{
+ m_infoBox->setText( s );
+
+ qApp->processEvents();
+}
+
+
+// void K3bSplash::paintEvent( QPaintEvent* e )
+// {
+// // first let the window paint the background and the child widget
+// QWidget::paintEvent( e );
+
+// // now create the text we want to display
+// // find the lower left corner and paint it on top of the pixmap
+// QPainter p( this );
+// p.setPen( Qt::blue );
+
+// QFontMetrics fm = p.fontMetrics();
+
+// QString line1 = QString( "K3b version %1" ).arg(VERSION);
+// QString line2( "(c) 2001 by Sebastian Trueg" );
+// QString line3( "licenced under the GPL" );
+
+// QRect rect1 = fm.boundingRect( line1 );
+// QRect rect2 = fm.boundingRect( line2 );
+// QRect rect3 = fm.boundingRect( line3 );
+
+// int textH = rect1.height() + rect2.height() + rect3.height() + 2 * fm.leading() + 2 + rect2.height() /*hack because the boundingRect method seems not to work properly! :-(*/;
+// int textW = QMAX( rect1.width(), QMAX( rect2.width(), rect3.width() ) ) + 2;
+
+// int startX = 10;
+// int startY = height() - 10 - textH;
+
+// p.drawText( startX, startY, textW, textH, 0, QString("%1\n%2\n%3").arg(line1).arg(line2).arg(line3) );
+// }
+
+
+#include "k3bsplash.moc"
diff --git a/src/k3bsplash.h b/src/k3bsplash.h
new file mode 100644
index 0000000..c4e6979
--- /dev/null
+++ b/src/k3bsplash.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * $Id: k3bsplash.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BSPLASH_H
+#define K3BSPLASH_H
+
+#include <qvbox.h>
+
+class QLabel;
+class QMouseEvent;
+class QPaintEvent;
+class QString;
+
+
+class K3bSplash : public QVBox
+{
+Q_OBJECT
+
+ public:
+ K3bSplash( QWidget* parent = 0, const char* name = 0 );
+ ~K3bSplash();
+
+ public slots:
+ void show();
+ void addInfo( const QString& );
+
+ protected:
+ void mousePressEvent( QMouseEvent* );
+ // void paintEvent( QPaintEvent* );
+
+ private:
+ QLabel* m_infoBox;
+};
+
+#endif
diff --git a/src/k3bstatusbarmanager.cpp b/src/k3bstatusbarmanager.cpp
new file mode 100644
index 0000000..b6e603d
--- /dev/null
+++ b/src/k3bstatusbarmanager.cpp
@@ -0,0 +1,250 @@
+/*
+ *
+ * $Id: k3bstatusbarmanager.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bstatusbarmanager.h"
+#include <k3bcore.h>
+#include "k3bbusywidget.h"
+#include "k3b.h"
+#include <k3bversion.h>
+#include <k3bglobals.h>
+#include "k3bprojectmanager.h"
+#include "k3bapplication.h"
+#include <k3baudiodoc.h>
+#include <k3bdatadoc.h>
+#include <k3bmixeddoc.h>
+#include <k3bvcddoc.h>
+#include <k3bdiritem.h>
+#include <k3bview.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kio/global.h>
+#include <kstatusbar.h>
+#include <kaboutdata.h>
+#include <kaction.h>
+
+#include <qlabel.h>
+#include <qhbox.h>
+#include <qfile.h>
+#include <qtimer.h>
+#include <qevent.h>
+#include <qtooltip.h>
+
+
+
+K3bStatusBarManager::K3bStatusBarManager( K3bMainWindow* parent )
+ : QObject(parent),
+ m_mainWindow(parent)
+{
+ // setup free temp space box
+ QHBox* boxFreeTemp = new QHBox( m_mainWindow->statusBar() );
+ boxFreeTemp->setSpacing(2);
+
+ m_labelProjectInfo = new QLabel( m_mainWindow->statusBar() );
+
+ m_pixFreeTemp = new QLabel( boxFreeTemp );
+ (void)new QLabel( i18n("Temp:"), boxFreeTemp );
+ m_pixFreeTemp->setPixmap( SmallIcon("folder_green") );
+ m_labelFreeTemp = new QLabel( boxFreeTemp );
+ boxFreeTemp->installEventFilter( this );
+
+ // setup info area
+ m_labelInfoMessage = new QLabel( " ", m_mainWindow->statusBar() );
+
+ // setup version info
+ m_versionBox = new QLabel( QString("K3b %1").arg(kapp->aboutData()->version()), m_mainWindow->statusBar() );
+ m_versionBox->installEventFilter( this );
+
+ // setup the statusbar
+ m_mainWindow->statusBar()->addWidget( m_labelInfoMessage, 1 ); // for showing some info
+ m_mainWindow->statusBar()->addWidget( m_labelProjectInfo, 0, true );
+ // a spacer item
+ m_mainWindow->statusBar()->addWidget( new QLabel( " ", m_mainWindow->statusBar() ), 0, true );
+ m_mainWindow->statusBar()->addWidget( boxFreeTemp, 0, true );
+ // a spacer item
+ m_mainWindow->statusBar()->addWidget( new QLabel( " ", m_mainWindow->statusBar() ), 0, true );
+ m_mainWindow->statusBar()->addWidget( m_versionBox, 0, true );
+
+ connect( m_mainWindow, SIGNAL(configChanged(KConfig*)), this, SLOT(update()) );
+ connect( m_mainWindow->actionCollection(), SIGNAL(actionStatusText(const QString&)),
+ this, SLOT(showActionStatusText(const QString&)) );
+ connect( m_mainWindow->actionCollection(), SIGNAL(clearStatusText()),
+ this, SLOT(clearActionStatusText()) );
+ connect( k3bappcore->projectManager(), SIGNAL(activeProjectChanged(K3bDoc*)),
+ this, SLOT(slotActiveProjectChanged(K3bDoc*)) );
+ connect( k3bappcore->projectManager(), SIGNAL(projectChanged(K3bDoc*)),
+ this, SLOT(slotActiveProjectChanged(K3bDoc*)) );
+ connect( (m_updateTimer = new QTimer( this )), SIGNAL(timeout()), this, SLOT(slotUpdateProjectStats()) );
+
+ update();
+}
+
+
+K3bStatusBarManager::~K3bStatusBarManager()
+{
+}
+
+
+void K3bStatusBarManager::update()
+{
+ QString path = K3b::defaultTempPath();
+
+ if( !QFile::exists( path ) )
+ path.truncate( path.findRev('/') );
+
+ unsigned long size, avail;
+ if( K3b::kbFreeOnFs( path, size, avail ) )
+ slotFreeTempSpace( path, size, 0, avail );
+ else
+ m_labelFreeTemp->setText(i18n("No info"));
+
+ if( path != QToolTip::textFor( m_labelFreeTemp->parentWidget() ) ) {
+ QToolTip::remove( m_labelFreeTemp->parentWidget() );
+ QToolTip::add( m_labelFreeTemp->parentWidget(), path );
+ }
+}
+
+
+void K3bStatusBarManager::slotFreeTempSpace(const QString&,
+ unsigned long kbSize,
+ unsigned long,
+ unsigned long kbAvail)
+{
+ m_labelFreeTemp->setText(KIO::convertSizeFromKB(kbAvail) + "/" +
+ KIO::convertSizeFromKB(kbSize) );
+
+ // if we have less than 640 MB that is not good
+ if( kbAvail < 655360 )
+ m_pixFreeTemp->setPixmap( SmallIcon("folder_red") );
+ else
+ m_pixFreeTemp->setPixmap( SmallIcon("folder_green") );
+
+ // update the display every second
+ QTimer::singleShot( 2000, this, SLOT(update()) );
+}
+
+
+void K3bStatusBarManager::showActionStatusText( const QString& text )
+{
+ m_mainWindow->statusBar()->message( text );
+}
+
+
+void K3bStatusBarManager::clearActionStatusText()
+{
+ m_mainWindow->statusBar()->clear();
+}
+
+
+bool K3bStatusBarManager::eventFilter( QObject* o, QEvent* e )
+{
+ if( e->type() == QEvent::MouseButtonDblClick ) {
+ if( o == m_labelFreeTemp->parentWidget() )
+ m_mainWindow->showOptionDialog( 0 ); // FIXME: use an enumeration for the option pages
+ else if( o == m_versionBox )
+ if( KAction* a = m_mainWindow->action( "help_about_app" ) )
+ a->activate();
+ }
+
+ return QObject::eventFilter( o, e );
+}
+
+
+static QString dataDocStats( K3bDataDoc* dataDoc )
+{
+ return i18n("1 file in %1", "%n files in %1", dataDoc->root()->numFiles() )
+ .arg( i18n("1 folder", "%n folders", dataDoc->root()->numDirs()+1 ) );
+}
+
+
+void K3bStatusBarManager::slotActiveProjectChanged( K3bDoc* doc )
+{
+ if( doc && doc == k3bappcore->projectManager()->activeProject() ) {
+ // cache updates
+ if( !m_updateTimer->isActive() ) {
+ slotUpdateProjectStats();
+ m_updateTimer->start( 1000, false );
+ }
+ }
+ else if( !doc ) {
+ m_labelProjectInfo->setText( QString() );
+ }
+}
+
+
+void K3bStatusBarManager::slotUpdateProjectStats()
+{
+ K3bDoc* doc = k3bappcore->projectManager()->activeProject();
+ if( doc ) {
+ switch( doc->type() ) {
+ case K3bDoc::AUDIO: {
+ K3bAudioDoc* audioDoc = static_cast<K3bAudioDoc*>( doc );
+ m_labelProjectInfo->setText( i18n("Audio CD (1 track)", "Audio CD (%n tracks)", audioDoc->numOfTracks() ) );
+ break;
+ }
+
+ case K3bDoc::DATA: {
+ K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>( doc );
+ m_labelProjectInfo->setText( i18n("Data CD (%1)").arg(dataDocStats(dataDoc)) );
+ break;
+ }
+
+ case K3bDoc::MIXED: {
+ K3bAudioDoc* audioDoc = static_cast<K3bMixedDoc*>( doc )->audioDoc();
+ K3bDataDoc* dataDoc = static_cast<K3bMixedDoc*>( doc )->dataDoc();
+ m_labelProjectInfo->setText( i18n("Mixed CD (1 track and %1)", "Mixed CD (%n tracks and %1)", audioDoc->numOfTracks() )
+ .arg( dataDocStats(dataDoc)) );
+ break;
+ }
+
+ case K3bDoc::VCD: {
+ K3bVcdDoc* vcdDoc = static_cast<K3bVcdDoc*>( doc );
+ m_labelProjectInfo->setText( i18n("Video CD (1 track)", "Video CD (%n tracks)", vcdDoc->numOfTracks() ) );
+ break;
+ }
+
+ case K3bDoc::MOVIX: {
+ K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>( doc );
+ m_labelProjectInfo->setText( i18n("eMovix CD (%1)").arg(dataDocStats(dataDoc)) );
+ break;
+ }
+
+ case K3bDoc::MOVIX_DVD: {
+ K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>( doc );
+ m_labelProjectInfo->setText( i18n("eMovix DVD (%1)").arg(dataDocStats(dataDoc)) );
+ break;
+ }
+
+ case K3bDoc::DVD: {
+ K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>( doc );
+ m_labelProjectInfo->setText( i18n("Data DVD (%1)").arg(dataDocStats(dataDoc)) );
+ break;
+ }
+
+ case K3bDoc::VIDEODVD: {
+ K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>( doc );
+ m_labelProjectInfo->setText( i18n("Video DVD (%1)").arg(dataDocStats(dataDoc)) );
+ break;
+ }
+ }
+ }
+ else {
+ m_labelProjectInfo->setText( QString() );
+ }
+}
+
+#include "k3bstatusbarmanager.moc"
diff --git a/src/k3bstatusbarmanager.h b/src/k3bstatusbarmanager.h
new file mode 100644
index 0000000..d8db737
--- /dev/null
+++ b/src/k3bstatusbarmanager.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * $Id: k3bstatusbarmanager.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef K3B_STATUSBAR_MANAGER_H
+#define K3B_STATUSBAR_MANAGER_H
+
+#include <qobject.h>
+
+class QLabel;
+class K3bMainWindow;
+class QEvent;
+class K3bDoc;
+class QTimer;
+
+class K3bStatusBarManager : public QObject
+{
+ Q_OBJECT
+
+ public:
+ K3bStatusBarManager( K3bMainWindow* parent );
+ ~K3bStatusBarManager();
+
+ public slots:
+ void update();
+
+ private slots:
+ void slotFreeTempSpace( const QString&, unsigned long, unsigned long, unsigned long );
+ void showActionStatusText( const QString& text );
+ void clearActionStatusText();
+ void slotActiveProjectChanged( K3bDoc* doc );
+ void slotUpdateProjectStats();
+
+ private:
+ bool eventFilter( QObject* o, QEvent* e );
+
+ QLabel* m_labelInfoMessage;
+ QLabel* m_pixFreeTemp;
+ QLabel* m_labelFreeTemp;
+ QLabel* m_versionBox;
+ QLabel* m_labelProjectInfo;
+
+ K3bMainWindow* m_mainWindow;
+
+ QTimer* m_updateTimer;
+};
+
+#endif
diff --git a/src/k3bsystemproblemdialog.cpp b/src/k3bsystemproblemdialog.cpp
new file mode 100644
index 0000000..17f9376
--- /dev/null
+++ b/src/k3bsystemproblemdialog.cpp
@@ -0,0 +1,690 @@
+/*
+ *
+ * $Id: k3bsystemproblemdialog.cpp 655079 2007-04-17 17:17:08Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include <config.h>
+
+
+#include "k3bapplication.h"
+#include "k3bsystemproblemdialog.h"
+#include "k3bpassivepopup.h"
+#include "k3bthemedheader.h"
+#include <k3btitlelabel.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bstdguiitems.h>
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bversion.h>
+#include <k3bglobals.h>
+#include <k3bpluginmanager.h>
+#include <k3bplugin.h>
+#include <k3bprocess.h>
+#include <k3bthememanager.h>
+#include <k3bcore.h>
+
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qfileinfo.h>
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <ktextedit.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kglobal.h>
+
+#ifdef HAVE_ICONV_H
+#include <langinfo.h>
+#endif
+
+#include <fstab.h>
+
+
+static QString markupString( const QString& s_ )
+{
+ QString s(s_);
+ s.replace( '<', "&lt;" );
+ s.replace( '>', "&gt;" );
+ return s;
+}
+
+
+K3bSystemProblem::K3bSystemProblem( int t,
+ const QString& p,
+ const QString& d,
+ const QString& s,
+ bool k )
+ : type(t),
+ problem(p),
+ details(d),
+ solution(s),
+ solvableByK3bSetup(k)
+{
+}
+
+
+K3bSystemProblemDialog::K3bSystemProblemDialog( const QValueList<K3bSystemProblem>& problems,
+ QWidget* parent,
+ const char* name )
+ : KDialog( parent, name )
+{
+ setCaption( i18n("System Configuration Problems") );
+
+ // setup the title
+ // ---------------------------------------------------------------------------------------------------
+ K3bThemedHeader* titleFrame = new K3bThemedHeader( this );
+ titleFrame->setTitle( i18n("System Configuration Problems"),
+ i18n("1 problem", "%n problems", problems.count() ) );
+
+ m_closeButton = new QPushButton( i18n("Close"), this );
+ connect( m_closeButton, SIGNAL(clicked()), this, SLOT(close()) );
+ m_checkDontShowAgain = new QCheckBox( i18n("Do not show again"), this );
+
+#ifdef HAVE_K3BSETUP
+ m_k3bsetupButton = new QPushButton( i18n("Start K3bSetup2"), this );
+ connect( m_k3bsetupButton, SIGNAL(clicked()), this, SLOT(slotK3bSetup()) );
+#endif
+
+ // setup the problem view
+ // ---------------------------------------------------------------------------------------------------
+ KTextEdit* view = new KTextEdit( this );
+ view->setReadOnly(true);
+ view->setTextFormat(RichText);
+
+
+ // layout everything
+ QGridLayout* grid = new QGridLayout( this );
+ grid->setMargin( marginHint() );
+ grid->setSpacing( spacingHint() );
+ grid->addMultiCellWidget( titleFrame, 0, 0, 0, 1 );
+ grid->addMultiCellWidget( view, 1, 1, 0, 1 );
+ grid->addWidget( m_checkDontShowAgain, 2, 0 );
+ QHBoxLayout* buttonBox = new QHBoxLayout;
+ buttonBox->setSpacing( spacingHint() );
+ buttonBox->setMargin( 0 );
+#ifdef HAVE_K3BSETUP
+ buttonBox->addWidget( m_k3bsetupButton );
+#endif
+ buttonBox->addWidget( m_closeButton );
+ grid->addLayout( buttonBox, 2, 1 );
+ grid->setColStretch( 0, 1 );
+ grid->setRowStretch( 1, 1 );
+
+ QString text = "<html>";
+
+ for( QValueList<K3bSystemProblem>::const_iterator it = problems.begin();
+ it != problems.end(); ++it ) {
+ const K3bSystemProblem& p = *it;
+
+ text.append( "<p><b>" );
+ if( p.type == K3bSystemProblem::CRITICAL )
+ text.append( "<span style=\"color:red\">" );
+ text.append( markupString( p.problem ) );
+ if( p.type == K3bSystemProblem::CRITICAL )
+ text.append( "</span>" );
+ text.append( "</b><br>" );
+ text.append( markupString( p.details ) + "<br>" );
+ if( !p.solution.isEmpty() )
+ text.append( "<i>" + i18n("Solution") + "</i>: " + p.solution );
+#ifdef HAVE_K3BSETUP
+ else if( p.solvableByK3bSetup )
+ text.append( "<i>" + i18n("Solution") + "</i>: " + i18n("Use K3bSetup to solve this problem.") );
+#endif
+ text.append( "</p>" );
+ }
+
+ text.append( "</html>" );
+
+ view->setText(text);
+ view->setCursorPosition(0,0);
+ view->ensureCursorVisible();
+}
+
+
+void K3bSystemProblemDialog::closeEvent( QCloseEvent* e )
+{
+ if( m_checkDontShowAgain->isChecked() ) {
+ KConfigGroup grp( kapp->config(), "General Options" );
+ grp.writeEntry( "check system config", false );
+ }
+
+ e->accept();
+}
+
+
+void K3bSystemProblemDialog::checkSystem( QWidget* parent,
+ const char* name )
+{
+ QValueList<K3bSystemProblem> problems;
+
+ if( k3bcore->deviceManager()->cdWriter().isEmpty() ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::NON_CRITICAL,
+ i18n("No CD/DVD writer found."),
+ i18n("K3b did not find an optical writing device in your system. Thus, "
+ "you will not be able to burn CDs or DVDs. However, you can still "
+ "use other K3b features like audio track extraction or audio "
+ "transcoding or ISO9660 image creation."),
+ false ) );
+ }
+ else {
+ // 1. cdrecord, cdrdao
+ if( !k3bcore->externalBinManager()->foundBin( "cdrecord" ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("Unable to find %1 executable").arg("cdrecord"),
+ i18n("K3b uses cdrecord to actually write CDs."),
+ i18n("Install the cdrtools package which contains "
+ "cdrecord."),
+ false ) );
+ }
+ else {
+ if( k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "outdated" ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::NON_CRITICAL,
+ i18n("Used %1 version %2 is outdated").arg("cdrecord").arg(k3bcore->externalBinManager()->binObject( "cdrecord" )->version),
+ i18n("Although K3b supports all cdrtools versions since "
+ "1.10 it is highly recommended to at least use "
+ "version 2.0."),
+ i18n("Install a more recent version of the cdrtools."),
+ false ) );
+ }
+
+/*
+#ifdef Q_OS_LINUX
+
+ //
+ // Since kernel 2.6.8 older cdrecord versions are not able to use the SCSI subsystem when running suid root anymore
+ // So far we ignore the suid root issue with kernel >= 2.6.8 and cdrecord < 2.01.01a02
+ //
+ // Kernel 2.6.16.something seems to introduce another problem which was apparently worked around in cdrecord 2.01.01a05
+ //
+ if( K3b::simpleKernelVersion() >= K3bVersion( 2, 6, 8 ) &&
+ k3bcore->externalBinManager()->binObject( "cdrecord" )->version < K3bVersion( 2, 1, 1, "a05" ) &&
+ !k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "wodim" ) ) {
+ if( k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "suidroot" ) )
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("%1 will be run with root privileges on kernel >= 2.6.8").arg("cdrecord <= 2.01.01a05"),
+ i18n("Since Linux kernel 2.6.8 %1 will not work when run suid "
+ "root for security reasons anymore.").arg("cdrecord <= 2.01.01a05"),
+ QString::null,
+ true ) );
+ }
+#ifdef CDRECORD_SUID_ROOT_CHECK
+ else if( !k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "suidroot" ) && getuid() != 0 ) // not root
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("%1 will be run without root privileges").arg("cdrecord"),
+ i18n("It is highly recommended to configure cdrecord "
+ "to run with root privileges. Only then cdrecord "
+ "runs with high priority which increases the overall "
+ "stability of the burning process. Apart from that "
+ "it allows changing the size of the used burning buffer. "
+ "A lot of user problems could be solved this way. This is also "
+ "true when using SuSE's resmgr."),
+ QString::null,
+ true ) );
+#endif // CDRECORD_SUID_ROOT_CHECK
+#endif
+*/
+ }
+ if( !k3bcore->externalBinManager()->foundBin( "cdrdao" ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("Unable to find %1 executable").arg("cdrdao"),
+ i18n("K3b uses cdrdao to actually write CDs."),
+ i18n("Install the cdrdao package."),
+ false ) );
+ }
+/*
+ else {
+#ifdef Q_OS_LINUX
+#ifdef CDRECORD_SUID_ROOT_CHECK
+ if( !k3bcore->externalBinManager()->binObject( "cdrdao" )->hasFeature( "suidroot" ) && getuid() != 0 )
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("%1 will be run without root privileges").arg("cdrdao"),
+ i18n("It is highly recommended to configure cdrdao "
+ "to run with root privileges to increase the "
+ "overall stability of the burning process."),
+ QString::null,
+ true ) );
+#endif // CDRECORD_SUID_ROOT_CHECK
+#endif
+ }
+*/
+ }
+
+ if( !k3bcore->deviceManager()->dvdWriter().isEmpty() ) {
+ if( !k3bcore->externalBinManager()->foundBin( "growisofs" ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("Unable to find %1 executable").arg("growisofs"),
+ i18n("K3b uses growisofs to actually write dvds. "
+ "Without growisofs you will not be able to write dvds. "
+ "Make sure to install at least version 5.10."),
+ i18n("Install the dvd+rw-tools package."),
+ false ) );
+ }
+ else {
+ if( k3bcore->externalBinManager()->binObject( "growisofs" )->version < K3bVersion( 5, 10 ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("Used %1 version %2 is outdated").arg("growisofs").arg(k3bcore->externalBinManager()->binObject( "growisofs" )->version),
+ i18n("K3b needs at least growisofs version 5.10 to write dvds. "
+ "All older versions will not work and K3b will refuse to use them."),
+ i18n("Install a more recent version of %1.").arg("growisofs"),
+ false ) );
+ }
+ else if( k3bcore->externalBinManager()->binObject( "growisofs" )->version < K3bVersion( 5, 12 ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::NON_CRITICAL,
+ i18n("Used %1 version %2 is outdated").arg("growisofs").arg(k3bcore->externalBinManager()->binObject( "growisofs" )->version),
+ i18n("K3b will not be able to copy DVDs on-the-fly or write a DVD+RW in multiple "
+ "sessions using a growisofs "
+ "version older than 5.12."),
+ i18n("Install a more recent version of %1.").arg("growisofs"),
+ false ) );
+ }
+ else if( k3bcore->externalBinManager()->binObject( "growisofs" )->version < K3bVersion( 7, 0 ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::NON_CRITICAL,
+ i18n("Used %1 version %2 is outdated").arg("growisofs").arg(k3bcore->externalBinManager()->binObject( "growisofs" )->version),
+ i18n("It is highly recommended to use growisofs 7.0 or higher. "
+ "K3b won't be able to write a DVD+RW in multiple "
+ "sessions using a growisofs version older than 7.0." ),
+ i18n("Install a more recent version of %1.").arg("growisofs"),
+ false ) );
+ }
+ // for now we ignore the suid root bit becasue of the memorylocked issue
+// else if( !k3bcore->externalBinManager()->binObject( "growisofs" )->hasFeature( "suidroot" ) ) {
+// problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+// i18n("%1 will be run without root privileges").arg("growisofs"),
+// i18n("It is highly recommended to configure growisofs "
+// "to run with root privileges. Only then growisofs "
+// "runs with high priority which increases the overall "
+// "stability of the burning process."),
+// QString::null,
+// true ) );
+// }
+ }
+
+ if( !k3bcore->externalBinManager()->foundBin( "dvd+rw-format" ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("Unable to find %1 executable").arg("dvd+rw-format"),
+ i18n("K3b uses dvd+rw-format to format DVD-RWs and DVD+RWs."),
+ i18n("Install the dvd+rw-tools package."),
+ false ) );
+ }
+ }
+
+ if( !k3bcore->externalBinManager()->foundBin( "mkisofs" ) ) {
+
+ }
+ else if( k3bcore->externalBinManager()->binObject( "mkisofs" )->hasFeature( "outdated" ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("Used %1 version %2 is outdated")
+ .arg("mkisofs")
+ .arg(k3bcore->externalBinManager()->binObject( "mkisofs" )->version),
+ i18n("K3b needs at least mkisofs version 1.14. Older versions may introduce problems "
+ "when creating data projects."),
+ i18n("Install a more recent version of %1.").arg("mkisofs"),
+ false ) );
+ }
+
+ // 2. device check
+ bool atapiReader = false;
+ bool atapiWriter = false;
+ bool dvd_r_dl = false;
+ for( QPtrListIterator<K3bDevice::Device> it( k3bcore->deviceManager()->readingDevices() );
+ it.current(); ++it ) {
+ if( it.current()->interfaceType() == K3bDevice::IDE )
+ atapiReader = true;
+ if( it.current()->type() & K3bDevice::DEVICE_DVD_R_DL )
+ dvd_r_dl = true;
+ }
+
+
+ // check automounted devices
+ QPtrList<K3bDevice::Device> automountedDevices = checkForAutomounting();
+ for( QPtrListIterator<K3bDevice::Device> it( automountedDevices );
+ it.current(); ++it ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::NON_CRITICAL,
+ i18n("Device %1 - %2 is automounted.")
+ .arg(it.current()->vendor()).arg(it.current()->description()),
+ i18n("K3b is not able to unmount automounted devices. Thus, especially "
+ "DVD+RW rewriting might fail. There is no need to report this as "
+ "a bug or feature wish; it is not possible to solve this problem "
+ "from within K3b."),
+ i18n("Replace the automounting entries in /etc/fstab with old-fashioned "
+ "ones or use a user-space mounting solution like pmount or ivman."),
+ false ) );
+ }
+
+
+ if( atapiWriter ) {
+ if( !K3b::plainAtapiSupport() &&
+ !K3b::hackedAtapiSupport() ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("No ATAPI writing support in kernel"),
+ i18n("Your kernel does not support writing without "
+ "SCSI emulation but there is at least one "
+ "writer in your system not configured to use "
+ "SCSI emulation."),
+ i18n("The best and recommended solution is to enable "
+ "ide-scsi (SCSI emulation) for all devices. "
+ "This way you won't have any problems."
+ "Be aware that you may still enable DMA on ide-scsi "
+ "emulated drives."),
+ false ) );
+ }
+ else {
+ // we have atapi support in some way in the kernel
+
+ if( k3bcore->externalBinManager()->foundBin( "cdrecord" ) ) {
+
+ if( !( k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "hacked-atapi" ) &&
+ K3b::hackedAtapiSupport() ) &&
+ !( k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "plain-atapi" ) &&
+ K3b::plainAtapiSupport() ) ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("%1 %2 does not support ATAPI").arg("cdrecord").arg(k3bcore->externalBinManager()->binObject("cdrecord")->version),
+ i18n("The configured version of %1 does not "
+ "support writing to ATAPI devices without "
+ "SCSI emulation and there is at least one writer "
+ "in your system not configured to use "
+ "SCSI emulation.").arg("cdrecord"),
+ i18n("The best and recommended solution is to enable "
+ "ide-scsi (SCSI emulation) for all devices. "
+ "This way you won't have any problems. Or you install "
+ "(or select as the default) a more recent version of %1.").arg("cdrtools"),
+ false ) );
+ }
+ }
+
+ if( k3bcore->externalBinManager()->foundBin( "cdrdao" ) ) {
+
+ if( !k3bcore->externalBinManager()->binObject( "cdrdao" )->hasFeature( "hacked-atapi" ) &&
+ !k3bcore->externalBinManager()->binObject( "cdrdao" )->hasFeature( "plain-atapi") ) {
+ // FIXME: replace ">" with "&gt;"
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("%1 %2 does not support ATAPI")
+ .arg("cdrdao").arg(k3bcore->externalBinManager()->binObject("cdrdao")->version),
+ i18n("The configured version of %1 does not "
+ "support writing to ATAPI devices without "
+ "SCSI emulation and there is at least one writer "
+ "in your system not configured to use "
+ "SCSI emulation.").arg("cdrdao"),
+ K3b::simpleKernelVersion() > K3bVersion( 2, 5, 0 )
+ ? i18n("Install cdrdao >= 1.1.8 which supports writing to "
+ "ATAPI devices directly.")
+ : i18n("The best, and recommended, solution is to use "
+ "ide-scsi (SCSI emulation) for all writer devices: "
+ "this way you will not have any problems; or, you can install "
+ "(or select as the default) a more recent version of %1.").arg("cdrdao"),
+ false ) );
+ }
+ }
+ }
+ }
+
+ if( dvd_r_dl && k3bcore->externalBinManager()->foundBin( "growisofs" ) ) {
+ if( k3bcore->externalBinManager()->binObject( "growisofs" )->version < K3bVersion( 6, 0 ) )
+ problems.append( K3bSystemProblem( K3bSystemProblem::NON_CRITICAL,
+ i18n("Used %1 version %2 is outdated").arg("growisofs").arg(k3bcore->externalBinManager()->binObject( "growisofs" )->version),
+ i18n("K3b won't be able to write DVD-R Dual Layer media using a growisofs "
+ "version older than 6.0."),
+ i18n("Install a more recent version of growisofs."),
+ false ) );
+ }
+
+ for( QPtrListIterator<K3bDevice::Device> it( k3bcore->deviceManager()->allDevices() );
+ it.current(); ++it ) {
+ K3bDevice::Device* dev = it.current();
+
+ if( !QFileInfo( dev->blockDeviceName() ).isWritable() )
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("No write access to device %1").arg(dev->blockDeviceName()),
+ i18n("K3b needs write access to all the devices to perform certain tasks. "
+ "Without it you might encounter problems with %1 - %2").arg(dev->vendor()).arg(dev->description()),
+ i18n("Make sure you have write access to %1. In case you are not using "
+ "devfs or udev K3bSetup is able to do this for you.").arg(dev->blockDeviceName()),
+ false ) );
+
+
+ if( !dev->genericDevice().isEmpty() &&
+ !QFileInfo( dev->genericDevice() ).isWritable() )
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("No write access to generic SCSI device %1").arg(dev->genericDevice()),
+ i18n("Without write access to the generic device you might "
+ "encounter problems with Audio CD ripping from %1 - %2").arg(dev->vendor()).arg(dev->description()),
+ i18n("Make sure you have write access to %1. In case you are not using "
+ "devfs or udev K3bSetup is able to do this for you.").arg(dev->genericDevice()),
+ false ) );
+
+ if( dev->interfaceType() == K3bDevice::IDE && !dmaActivated( dev ) )
+ problems.append( K3bSystemProblem( K3bSystemProblem::CRITICAL,
+ i18n("DMA disabled on device %1 - %2").arg(dev->vendor()).arg(dev->description()),
+ i18n("With most modern CD/DVD devices enabling DMA highly increases "
+ "read/write performance. If you experience very low writing speeds "
+ "this is probably the cause."),
+ i18n("Enable DMA temporarily as root with 'hdparm -d 1 %1'.").arg(dev->blockDeviceName()) ) );
+ }
+
+
+ //
+ // Check if the user specified some user parameters and warn about it
+ //
+ const QMap<QString, K3bExternalProgram*>& programMap = k3bcore->externalBinManager()->programs();
+ for( QMap<QString, K3bExternalProgram*>::const_iterator it = programMap.constBegin();
+ it != programMap.constEnd(); ++it ) {
+ const K3bExternalProgram* p = it.data();
+ if( !p->userParameters().isEmpty() ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::WARNING,
+ i18n("User parameters specified for external program %1").arg(p->name()),
+ i18n("Sometimes it may be nessessary to specify user parameters in addition to "
+ "the parameters generated by K3b. This is simply a warning to make sure that "
+ "these parameters are really wanted and won't be part of some bug report."),
+ i18n("To remove the user parameters for the external program %1 open the "
+ "K3b settings page 'Programs' and choose the tab 'User Parameters'.")
+ .arg(p->name()),
+ false ) );
+ }
+ }
+
+ //
+ // Way too many users are complaining about K3b not being able to decode mp3 files. So just warn them about
+ // the legal restrictions with many distros
+ //
+/*
+ QPtrList<K3bPlugin> plugins = k3bcore->pluginManager()->plugins( "AudioDecoder" );
+ bool haveMp3Decoder = false;
+ for( QPtrListIterator<K3bPlugin> it( plugins ); *it; ++it ) {
+ if( it.current()->pluginInfo().name() == "K3b MAD Decoder" ) {
+ haveMp3Decoder = true;
+ break;
+ }
+ }
+ if( !haveMp3Decoder ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::WARNING,
+ i18n("Mp3 Audio Decoder plugin not found."),
+ i18n("K3b could not load or find the Mp3 decoder plugin. This means that you will not "
+ "be able to create Audio CDs from Mp3 files. Many Linux distributions do not "
+ "include Mp3 support for legal reasons."),
+ i18n("To enable Mp3 support, please install the MAD Mp3 decoding library as well as the "
+ "K3b MAD Mp3 decoder plugin (the latter may already be installed but not functional "
+ "due to the missing libmad). Some distributions allow installation of Mp3 support "
+ "via an online update tool (i.e. SuSE's YOU)."),
+ false ) );
+ }
+*/
+
+#ifdef HAVE_ICONV_H
+ char* codec = nl_langinfo( CODESET );
+ if( strcmp( codec, "ANSI_X3.4-1968" ) == 0 ) {
+ //
+ // On a glibc system the system locale defaults to ANSI_X3.4-1968
+ // It is very unlikely that one would set the locale to ANSI_X3.4-1968
+ // intentionally
+ //
+ problems.append( K3bSystemProblem( K3bSystemProblem::WARNING,
+ i18n("System locale charset is ANSI_X3.4-1968"),
+ i18n("Your system's locale charset (i.e. the charset used to encode filenames) "
+ "is set to ANSI_X3.4-1968. It is highly unlikely that this has been done "
+ "intentionally. Most likely the locale is not set at all. An invalid setting "
+ "will result in problems when creating data projects."),
+ i18n("To properly set the locale charset make sure the LC_* environment variables "
+ "are set. Normally the distribution setup tools take care of this."),
+ false ) );
+ }
+#endif
+
+
+ //
+ // Never run K3b as root and especially not suid root! The latter is not possible anyway since
+ // the kdelibs refuse it.
+ //
+ if( ::getuid() == 0 ) {
+ problems.append( K3bSystemProblem( K3bSystemProblem::WARNING,
+ i18n("Running K3b as root user"),
+ i18n("It is not recommended to run K3b under the root user account. "
+ "This introduces unnecessary security risks."),
+ i18n("Run K3b from a proper user account and setup the device and "
+ "external tool permissions appropriately.")
+#ifdef HAVE_K3BSETUP
+ + ' ' + i18n("The latter can be done via K3bSetup.")
+#endif
+ ,
+ true ) );
+ }
+
+
+ kdDebug() << "(K3bCore) System problems:" << endl;
+ for( QValueList<K3bSystemProblem>::const_iterator it = problems.begin();
+ it != problems.end(); ++it ) {
+ const K3bSystemProblem& p = *it;
+
+ switch( p.type ) {
+ case K3bSystemProblem::CRITICAL:
+ kdDebug() << " CRITICAL" << endl;
+ break;
+ case K3bSystemProblem::NON_CRITICAL:
+ kdDebug() << " NON_CRITICAL" << endl;
+ break;
+ case K3bSystemProblem::WARNING:
+ kdDebug() << " WARNING" << endl;
+ break;
+ }
+ kdDebug() << " PROBLEM: " << p.problem << endl
+ << " DETAILS: " << p.details << endl
+ << " SOLUTION: " << p.solution << endl << endl;
+
+ }
+ if( problems.isEmpty() ) {
+ kdDebug() << " - none - " << endl;
+ //K3bPassivePopup::showPopup( i18n("No problems found in system configuration."), i18n("System Problems") );
+ }
+ else {
+ static K3bSystemProblemDialog* s_openDlg = 0;
+ if( s_openDlg )
+ s_openDlg->close();
+ K3bSystemProblemDialog dlg( problems, parent, name );
+ s_openDlg = &dlg;
+ dlg.exec();
+ s_openDlg = 0;
+ }
+
+ // remember which version of K3b checked the system the last time
+ KConfigGroup cfg( k3bcore->config(), "General Options" );
+ cfg.writeEntry( "Last system check version", k3bcore->version() );
+}
+
+void K3bSystemProblemDialog::slotK3bSetup()
+{
+ KProcess p;
+ p << "kdesu" << "kcmshell k3bsetup2 --lang " + KGlobal::locale()->language();
+ if( !p.start( KProcess::DontCare ) )
+ KMessageBox::error( 0, i18n("Unable to start K3bSetup2.") );
+}
+
+
+int K3bSystemProblemDialog::dmaActivated( K3bDevice::Device* dev )
+{
+ QString hdparm = K3b::findExe( "hdparm" );
+ if( hdparm.isEmpty() )
+ return -1;
+
+ K3bProcess p;
+ K3bProcessOutputCollector out( &p );
+ p << hdparm << "-d" << dev->blockDeviceName();
+ if( !p.start( KProcess::Block, KProcess::AllOutput ) )
+ return -1;
+
+ // output is something like:
+ //
+ // /dev/hda:
+ // using_dma = 1 (on)
+ //
+ // But we ignore the on/off since it might be translated
+ //
+ if( out.output().contains( "1 (" ) )
+ return 1;
+ else if( out.output().contains( "0 (" ) )
+ return 0;
+ else
+ return -1;
+}
+
+
+QPtrList<K3bDevice::Device> K3bSystemProblemDialog::checkForAutomounting()
+{
+ QPtrList<K3bDevice::Device> l;
+
+ ::setfsent();
+
+ struct fstab * mountInfo = 0;
+ while( (mountInfo = ::getfsent()) )
+ {
+ // check if the entry corresponds to a device
+ QString md = K3b::resolveLink( QFile::decodeName( mountInfo->fs_spec ) );
+ QString type = QFile::decodeName( mountInfo->fs_vfstype );
+
+ if( type == "supermount" || type == "subfs" ) {
+ // parse the device
+ QStringList opts = QStringList::split( ",", QString::fromLocal8Bit(mountInfo->fs_mntops) );
+ for( QStringList::const_iterator it = opts.begin(); it != opts.end(); ++it ) {
+ if( (*it).startsWith("dev=") ) {
+ md = (*it).mid( 4 );
+ break;
+ }
+ }
+
+ if( K3bDevice::Device* dev = k3bcore->deviceManager()->findDevice( md ) )
+ l.append( dev );
+ }
+ } // while mountInfo
+
+ ::endfsent();
+
+ return l;
+}
+
+
+bool K3bSystemProblemDialog::readCheckSystemConfig()
+{
+ KConfigGroup cfgGrp( k3bcore->config(), "General Options" );
+
+ K3bVersion configVersion( cfgGrp.readEntry( "Last system check version", "0.1" ) );
+ if( configVersion < k3bcore->version() )
+ cfgGrp.writeEntry( "check system config", true );
+
+ return cfgGrp.readBoolEntry( "check system config", true );
+}
+
+#include "k3bsystemproblemdialog.moc"
diff --git a/src/k3bsystemproblemdialog.h b/src/k3bsystemproblemdialog.h
new file mode 100644
index 0000000..ad3e1c3
--- /dev/null
+++ b/src/k3bsystemproblemdialog.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * $Id: k3bsystemproblemdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_SYSTEM_DIALOG_H_
+#define _K3B_SYSTEM_DIALOG_H_
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <kdialog.h>
+
+class QPushButton;
+class QCheckBox;
+class QCloseEvent;
+namespace K3bDevice {
+ class Device;
+}
+
+
+class K3bSystemProblem
+{
+ public:
+ K3bSystemProblem( int type = NON_CRITICAL,
+ const QString& problem = QString::null,
+ const QString& details = QString::null,
+ const QString& solution = QString::null,
+ bool k3bsetup = false );
+
+ enum {
+ CRITICAL,
+ NON_CRITICAL,
+ WARNING
+ };
+
+ int type;
+ QString problem;
+ QString details;
+ QString solution;
+ bool solvableByK3bSetup;
+};
+
+
+/**
+ * The K3bSystemProblem checks for problems with the system setup
+ * that could prevent K3b from funcioning properly. Examples are
+ * missing external appplications like cdrecord or versions of
+ * external applications that are too old.
+ *
+ * Usage:
+ * <pre>
+ * if( K3bSystemProblemDialog::readCheckSystemConfig() )
+ * K3bSystemProblemDialog::checkSystem( this );
+ * </pre>
+ */
+class K3bSystemProblemDialog : public KDialog
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Determines if the system problem dialog should be shown or not.
+ * It basicly reads a config entry. But in addition it
+ * always forces the system check if a new version has been installed
+ * or K3b is started for the first time.
+ */
+ static bool readCheckSystemConfig();
+ static void checkSystem( QWidget* parent = 0,
+ const char* name = 0 );
+
+ protected:
+ void closeEvent( QCloseEvent* );
+
+ private slots:
+ void slotK3bSetup();
+
+ private:
+ K3bSystemProblemDialog( const QValueList<K3bSystemProblem>&,
+ QWidget* parent = 0,
+ const char* name = 0 );
+ static int dmaActivated( K3bDevice::Device* );
+ static QPtrList<K3bDevice::Device> checkForAutomounting();
+
+ QPushButton* m_closeButton;
+ QPushButton* m_k3bsetupButton;
+ QCheckBox* m_checkDontShowAgain;
+};
+
+#endif
diff --git a/src/k3btempdirselectionwidget.cpp b/src/k3btempdirselectionwidget.cpp
new file mode 100644
index 0000000..ae850e1
--- /dev/null
+++ b/src/k3btempdirselectionwidget.cpp
@@ -0,0 +1,277 @@
+/*
+ *
+ * $Id: k3btempdirselectionwidget.cpp 690207 2007-07-20 10:40:19Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3btempdirselectionwidget.h"
+#include <k3bglobals.h>
+#include <k3bcore.h>
+
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qhbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qfileinfo.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kdialog.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <kurlrequester.h>
+#include <kio/global.h>
+#include <kconfig.h>
+#include <klineedit.h>
+
+
+K3bTempDirSelectionWidget::K3bTempDirSelectionWidget( QWidget *parent, const char *name )
+ : QGroupBox( 4, Qt::Vertical, parent, name ),
+ m_labelCdSize(0),
+ m_defaultImageFileName( "k3b_image.iso" )
+{
+ layout()->setSpacing( KDialog::spacingHint() );
+ layout()->setMargin( KDialog::marginHint() );
+
+ m_imageFileLabel = new QLabel( this );
+ m_editDirectory = new KURLRequester( this, "m_editDirectory" );
+
+ m_imageFileLabel->setBuddy( m_editDirectory );
+
+ QHBox* freeTempSpaceBox = new QHBox( this );
+ freeTempSpaceBox->setSpacing( KDialog::spacingHint() );
+ (void)new QLabel( i18n( "Free space in temporary directory:" ), freeTempSpaceBox, "TextLabel2" );
+ m_labelFreeSpace = new QLabel( " ",freeTempSpaceBox, "m_labelFreeSpace" );
+ m_labelFreeSpace->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+
+ connect( m_editDirectory, SIGNAL(openFileDialog(KURLRequester*)),
+ this, SLOT(slotTempDirButtonPressed(KURLRequester*)) );
+ connect( m_editDirectory, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotUpdateFreeTempSpace()) );
+ connect( m_editDirectory->lineEdit(), SIGNAL(lostFocus()),
+ this, SLOT(slotFixTempPath()) );
+
+ // choose a default
+ setSelectionMode( DIR );
+
+ m_editDirectory->setURL( K3b::defaultTempPath() );
+ slotUpdateFreeTempSpace();
+
+ // ToolTips
+ // --------------------------------------------------------------------------------
+ QToolTip::add( m_editDirectory, i18n("The directory in which to save the image files") );
+
+ // What's This info
+ // --------------------------------------------------------------------------------
+ QWhatsThis::add( m_editDirectory, i18n("<p>This is the directory in which K3b will save the <em>image files</em>."
+ "<p>Please make sure that it resides on a partition that has enough free space.") );
+}
+
+
+K3bTempDirSelectionWidget::~K3bTempDirSelectionWidget()
+{
+}
+
+
+unsigned long K3bTempDirSelectionWidget::freeTempSpace() const
+{
+ QString path = m_editDirectory->url();
+
+ if( !QFile::exists( path ) )
+ path.truncate( path.findRev('/') );
+
+ unsigned long size;
+ K3b::kbFreeOnFs( path, size, m_freeTempSpace );
+
+ return m_freeTempSpace;
+}
+
+
+void K3bTempDirSelectionWidget::slotUpdateFreeTempSpace()
+{
+ // update the temp space
+ freeTempSpace();
+
+ m_labelFreeSpace->setText( KIO::convertSizeFromKB(m_freeTempSpace) );
+
+ if( m_labelCdSize ) {
+ if( m_freeTempSpace < m_requestedSize/1024 )
+ m_labelCdSize->setPaletteForegroundColor( red );
+ else
+ m_labelCdSize->setPaletteForegroundColor( m_labelFreeSpace->paletteForegroundColor() );
+ }
+ QTimer::singleShot( 1000, this, SLOT(slotUpdateFreeTempSpace()) );
+}
+
+
+void K3bTempDirSelectionWidget::slotTempDirButtonPressed( KURLRequester* r )
+{
+ // set the correct mode for the filedialog
+ if( m_mode == DIR ) {
+ r->setCaption( i18n("Select Temporary Directory") );
+ r->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+ }
+ else {
+ r->setCaption( i18n("Select Temporary File") );
+ r->setMode( KFile::File | KFile::LocalOnly );
+ }
+}
+
+
+void K3bTempDirSelectionWidget::setTempPath( const QString& dir )
+{
+ m_editDirectory->setURL( dir );
+ slotUpdateFreeTempSpace();
+}
+
+
+QString K3bTempDirSelectionWidget::tempPath() const
+{
+ QFileInfo fi( m_editDirectory->url() );
+
+ if( fi.exists() ) {
+ if( m_mode == DIR ) {
+ if( fi.isDir() )
+ return fi.absFilePath();
+ else
+ return fi.dirPath( true );
+ }
+ else {
+ if( fi.isFile() )
+ return fi.absFilePath();
+ else
+ return fi.absFilePath() + "/k3b_image.iso";
+ }
+ }
+ else {
+ return fi.absFilePath();
+ }
+}
+
+
+QString K3bTempDirSelectionWidget::plainTempPath() const
+{
+ return m_editDirectory->url();
+}
+
+
+QString K3bTempDirSelectionWidget::tempDirectory() const
+{
+ QString td( m_editDirectory->url() );
+
+ // remove a trailing slash
+ while( !td.isEmpty() && td[td.length()-1] == '/' )
+ td.truncate( td.length()-1 );
+
+ QFileInfo fi( td );
+ if( fi.exists() && fi.isDir() )
+ return td + "/";
+
+ // now we treat the last section as a filename and return the path
+ // in front of it
+ td.truncate( td.findRev( '/' ) + 1 );
+ return td;
+}
+
+
+void K3bTempDirSelectionWidget::setSelectionMode( int mode )
+{
+ m_mode = mode;
+
+ if( m_mode == DIR ) {
+ m_imageFileLabel->setText( i18n( "Wri&te image files to:" ) );
+ setTitle( i18n("Temporary Directory") );
+ }
+ else {
+ m_imageFileLabel->setText( i18n( "Wri&te image file to:" ) );
+ setTitle( i18n("Temporary File") );
+ }
+}
+
+
+void K3bTempDirSelectionWidget::setNeededSize( KIO::filesize_t bytes )
+{
+ m_requestedSize = bytes;
+ if( !m_labelCdSize ) {
+ QHBox* cdSizeBox = new QHBox( this );
+ cdSizeBox->setSpacing( KDialog::spacingHint() );
+ (void)new QLabel( i18n( "Size of project:" ), cdSizeBox, "TextLabel4" );
+ m_labelCdSize = new QLabel( KIO::convertSize(bytes), cdSizeBox, "m_labelCdSize" );
+ m_labelCdSize->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ }
+ m_labelCdSize->setText( KIO::convertSize(bytes) );
+}
+
+
+void K3bTempDirSelectionWidget::saveConfig()
+{
+ KConfigGroup grp( k3bcore->config(), "General Options" );
+ grp.writePathEntry( "Temp Dir", tempDirectory() );
+}
+
+
+void K3bTempDirSelectionWidget::readConfig( KConfigBase* c )
+{
+ setTempPath( c->readPathEntry( "image path", K3b::defaultTempPath() ) );
+}
+
+
+void K3bTempDirSelectionWidget::saveConfig( KConfigBase* c )
+{
+ c->writePathEntry( "image path", tempPath() );
+}
+
+
+void K3bTempDirSelectionWidget::setDefaultImageFileName( const QString& name )
+{
+ if ( !name.isEmpty() ) {
+ bool changeImageName = false;
+ if ( selectionMode() == FILE ) {
+ if ( plainTempPath().section( '/', -1 ) == m_defaultImageFileName ) {
+ changeImageName = true;
+ }
+ }
+
+ m_defaultImageFileName = name;
+ if ( !m_defaultImageFileName.contains( '.' ) ) {
+ m_defaultImageFileName += ".iso";
+ }
+ fixTempPath( changeImageName );
+ }
+}
+
+
+void K3bTempDirSelectionWidget::slotFixTempPath()
+{
+ fixTempPath( false );
+}
+
+
+void K3bTempDirSelectionWidget::fixTempPath( bool forceNewImageName )
+{
+ // if in file selection mode and no image file is specified or
+ // forceNewImageName is true set the default image file name
+ if ( selectionMode() == FILE ) {
+ if ( forceNewImageName ||
+ QFileInfo( plainTempPath() ).isDir() ) {
+ setTempPath( tempDirectory() + m_defaultImageFileName );
+ }
+ }
+}
+
+#include "k3btempdirselectionwidget.moc"
diff --git a/src/k3btempdirselectionwidget.h b/src/k3btempdirselectionwidget.h
new file mode 100644
index 0000000..abad230
--- /dev/null
+++ b/src/k3btempdirselectionwidget.h
@@ -0,0 +1,100 @@
+/*
+ *
+ * $Id: k3btempdirselectionwidget.h 690207 2007-07-20 10:40:19Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BTEMPDIRSELECTIONWIDGET_H
+#define K3BTEMPDIRSELECTIONWIDGET_H
+
+#include <qgroupbox.h>
+#include <kio/global.h>
+
+class QTimer;
+class QLabel;
+class KURLRequester;
+class KConfigBase;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bTempDirSelectionWidget : public QGroupBox
+{
+ Q_OBJECT
+
+ public:
+ K3bTempDirSelectionWidget( QWidget *parent = 0, const char *name = 0 );
+ ~K3bTempDirSelectionWidget();
+
+ /** determines if the selection dialog should ask for a dir or a file */
+ enum mode { DIR, FILE };
+
+ int selectionMode() const { return m_mode; }
+
+ /**
+ * \return Free space in KB
+ * FIXME: use KIO::filesize_t and return the number of bytes
+ */
+ unsigned long freeTempSpace() const;
+ QString tempPath() const;
+ QString tempDirectory() const;
+
+ /**
+ * Use this if you don't want K3bTempDirSelectionWidget to modify the
+ * user input based on the mode.
+ */
+ QString plainTempPath() const;
+
+ public slots:
+ void setTempPath( const QString& );
+ void setSelectionMode( int mode );
+ void setNeededSize( KIO::filesize_t bytes );
+
+ /**
+ * In file selection mode if the user enters a directory name it will
+ * automatically be expended to this filename.
+ * Default is k3b_image.iso
+ */
+ void setDefaultImageFileName( const QString& name );
+
+ /**
+ * saves the current path as the global default tempd dir.
+ */
+ void saveConfig();
+
+ void readConfig( KConfigBase* );
+ void saveConfig( KConfigBase* );
+
+ private slots:
+ void slotUpdateFreeTempSpace();
+ void slotTempDirButtonPressed( KURLRequester* );
+ void slotFixTempPath();
+
+ private:
+ void fixTempPath( bool forceNewImageName );
+
+ QLabel* m_imageFileLabel;
+ QLabel* m_labelCdSize;
+ QLabel* m_labelFreeSpace;
+ KURLRequester* m_editDirectory;
+
+ mutable unsigned long m_freeTempSpace;
+ unsigned long m_requestedSize;
+
+ int m_mode;
+
+ QString m_defaultImageFileName;
+};
+
+#endif
diff --git a/src/k3bthemedheader.cpp b/src/k3bthemedheader.cpp
new file mode 100644
index 0000000..4eb1c28
--- /dev/null
+++ b/src/k3bthemedheader.cpp
@@ -0,0 +1,129 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bthemedheader.h"
+#include "k3bthememanager.h"
+#include "k3bapplication.h"
+
+#include <k3btitlelabel.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+
+K3bThemedHeader::K3bThemedHeader( QWidget* parent )
+ : QFrame( parent )
+{
+ init();
+}
+
+
+K3bThemedHeader::K3bThemedHeader( const QString& title, const QString& subtitle, QWidget* parent )
+ : QFrame( parent )
+{
+ setTitle( title );
+ setSubTitle( subtitle );
+
+ init();
+}
+
+
+K3bThemedHeader::~K3bThemedHeader()
+{
+}
+
+
+void K3bThemedHeader::setTitle( const QString& title, const QString& subtitle )
+{
+ m_titleLabel->setTitle( title, subtitle );
+}
+
+
+void K3bThemedHeader::setSubTitle( const QString& subtitle )
+{
+ m_titleLabel->setSubTitle( subtitle );
+}
+
+
+void K3bThemedHeader::setLeftPixmap( K3bTheme::PixmapType p )
+{
+ m_leftPix = p;
+ slotThemeChanged();
+}
+
+
+void K3bThemedHeader::setRightPixmap( K3bTheme::PixmapType p )
+{
+ m_rightPix = p;
+ slotThemeChanged();
+}
+
+
+void K3bThemedHeader::setAlignment( int align )
+{
+ m_titleLabel->setAlignment( align );
+}
+
+
+void K3bThemedHeader::init()
+{
+ setFrameShape( QFrame::StyledPanel );
+ setFrameShadow( QFrame::Sunken );
+ setLineWidth( 1 );
+ setMargin( 1 );
+
+ QHBoxLayout* layout = new QHBoxLayout( this );
+ layout->setMargin( 2 ); // to make sure the frame gets displayed
+ layout->setSpacing( 0 );
+
+ m_leftLabel = new QLabel( this );
+ m_leftLabel->setScaledContents( false );
+ m_titleLabel = new K3bTitleLabel( this );
+ m_rightLabel = new QLabel( this );
+ m_rightLabel->setScaledContents( false );
+
+ layout->addWidget( m_leftLabel );
+ layout->addWidget( m_titleLabel );
+ layout->setStretchFactor( m_titleLabel, 1 );
+ layout->addWidget( m_rightLabel );
+
+ m_leftPix = K3bTheme::DIALOG_LEFT;
+ m_rightPix = K3bTheme::DIALOG_RIGHT;
+
+ slotThemeChanged();
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()),
+ this, SLOT(slotThemeChanged()) );
+ connect( kapp, SIGNAL(appearanceChanged()),
+ this, SLOT(slotThemeChanged()) );
+}
+
+
+void K3bThemedHeader::slotThemeChanged()
+{
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+// setPaletteBackgroundColor( theme->backgroundColor() );
+// setPaletteForegroundColor( theme->foregroundColor() );
+
+ m_leftLabel->setPaletteBackgroundColor( theme->backgroundColor() );
+ m_leftLabel->setPixmap( theme->pixmap( m_leftPix ) );
+ m_rightLabel->setPaletteBackgroundColor( theme->backgroundColor() );
+ m_rightLabel->setPixmap( theme->pixmap( m_rightPix ) );
+ m_titleLabel->setPaletteBackgroundColor( theme->backgroundColor() );
+ m_titleLabel->setPaletteForegroundColor( theme->foregroundColor() );
+ }
+}
+
+#include "k3bthemedheader.moc"
diff --git a/src/k3bthemedheader.h b/src/k3bthemedheader.h
new file mode 100644
index 0000000..3dda877
--- /dev/null
+++ b/src/k3bthemedheader.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_THEMED_HEADER_H_
+#define _K3B_THEMED_HEADER_H_
+
+#include <qframe.h>
+
+#include "k3bthememanager.h"
+
+class K3bTitleLabel;
+class QLabel;
+
+class K3bThemedHeader : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ K3bThemedHeader( QWidget* parent = 0 );
+ K3bThemedHeader( const QString& title, const QString& subtitle, QWidget* parent = 0 );
+ ~K3bThemedHeader();
+
+ public slots:
+ void setTitle( const QString& title, const QString& subtitle = QString::null );
+ void setSubTitle( const QString& subtitle );
+ void setAlignment( int );
+ void setLeftPixmap( K3bTheme::PixmapType );
+ void setRightPixmap( K3bTheme::PixmapType );
+
+ private slots:
+ void slotThemeChanged();
+
+ private:
+ void init();
+
+ K3bTitleLabel* m_titleLabel;
+ QLabel* m_leftLabel;
+ QLabel* m_rightLabel;
+ K3bTheme::PixmapType m_leftPix;
+ K3bTheme::PixmapType m_rightPix;
+};
+
+#endif
diff --git a/src/k3bthemedlabel.cpp b/src/k3bthemedlabel.cpp
new file mode 100644
index 0000000..d2ea05b
--- /dev/null
+++ b/src/k3bthemedlabel.cpp
@@ -0,0 +1,76 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bthemedlabel.h"
+#include "k3bapplication.h"
+
+K3bThemedLabel::K3bThemedLabel( QWidget* parent )
+ : KCutLabel( parent ),
+ m_themePixmapCode( -1 )
+{
+ slotThemeChanged();
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()),
+ this, SLOT(slotThemeChanged()) );
+ connect( kapp, SIGNAL(appearanceChanged()),
+ this, SLOT(slotThemeChanged()) );
+}
+
+
+K3bThemedLabel::K3bThemedLabel( const QString& text, QWidget* parent )
+ : KCutLabel( text, parent ),
+ m_themePixmapCode( -1 )
+{
+ slotThemeChanged();
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()),
+ this, SLOT(slotThemeChanged()) );
+ connect( kapp, SIGNAL(appearanceChanged()),
+ this, SLOT(slotThemeChanged()) );
+}
+
+
+K3bThemedLabel::K3bThemedLabel( K3bTheme::PixmapType pix, QWidget* parent )
+ : KCutLabel( parent )
+{
+ setThemePixmap( pix );
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()),
+ this, SLOT(slotThemeChanged()) );
+ connect( kapp, SIGNAL(appearanceChanged()),
+ this, SLOT(slotThemeChanged()) );
+}
+
+
+void K3bThemedLabel::setThemePixmap( K3bTheme::PixmapType pix )
+{
+ m_themePixmapCode = pix;
+ slotThemeChanged();
+}
+
+
+void K3bThemedLabel::slotThemeChanged()
+{
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ setPaletteBackgroundColor( theme->backgroundColor() );
+ setPaletteForegroundColor( theme->foregroundColor() );
+ if( m_themePixmapCode > -1 ) {
+ setPixmap( theme->pixmap( (K3bTheme::PixmapType)m_themePixmapCode ) );
+ setScaledContents( false );
+ }
+ }
+}
+
+#include "k3bthemedlabel.moc"
diff --git a/src/k3bthemedlabel.h b/src/k3bthemedlabel.h
new file mode 100644
index 0000000..06d4851
--- /dev/null
+++ b/src/k3bthemedlabel.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_THEMED_LABEL_H_
+#define _K3B_THEMED_LABEL_H_
+
+#include <kcutlabel.h>
+#include <k3bthememanager.h>
+
+
+class K3bThemedLabel : public KCutLabel
+{
+ Q_OBJECT
+
+ public:
+ K3bThemedLabel( QWidget* parent = 0 );
+ K3bThemedLabel( const QString& text, QWidget* parent = 0 );
+ K3bThemedLabel( K3bTheme::PixmapType, QWidget* parent = 0 );
+
+ public slots:
+ void setThemePixmap( K3bTheme::PixmapType );
+
+ private slots:
+ void slotThemeChanged();
+
+ private:
+ int m_themePixmapCode;
+};
+
+#endif
diff --git a/src/k3bthememanager.cpp b/src/k3bthememanager.cpp
new file mode 100644
index 0000000..2d7177f
--- /dev/null
+++ b/src/k3bthememanager.cpp
@@ -0,0 +1,324 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bthememanager.h"
+
+#include <k3bversion.h>
+
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <ksimpleconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include <qpixmap.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+
+
+K3bTheme::K3bTheme()
+ : m_bgMode(BG_TILE)
+{
+}
+
+
+QColor K3bTheme::backgroundColor() const
+{
+ if( m_bgColor.isValid() )
+ return m_bgColor;
+ else
+ return KGlobalSettings::activeTitleColor();
+}
+
+
+QColor K3bTheme::foregroundColor() const
+{
+ if( m_fgColor.isValid() )
+ return m_fgColor;
+ else
+ return KGlobalSettings::activeTextColor();
+}
+
+
+const QPixmap& K3bTheme::pixmap( const QString& name ) const
+{
+ QMap<QString, QPixmap>::const_iterator it = m_pixmapMap.find( name );
+ if( it != m_pixmapMap.end() )
+ return *it;
+
+ // try loading the image
+ if( QFile::exists( m_path + name ) )
+ return *m_pixmapMap.insert( name, QPixmap( m_path + name ) );
+
+ kdDebug() << "(K3bTheme) " << m_name << ": could not load image " << name << endl;
+
+ return m_emptyPixmap;
+}
+
+
+const QPixmap& K3bTheme::pixmap( K3bTheme::PixmapType t ) const
+{
+ return pixmap( filenameForPixmapType( t ) );
+}
+
+
+QString K3bTheme::filenameForPixmapType( PixmapType t )
+{
+ QString name;
+
+ switch( t ) {
+ case MEDIA_AUDIO:
+ name = "media_audio";
+ break;
+ case MEDIA_DATA:
+ name = "media_data";
+ break;
+ case MEDIA_VIDEO:
+ name = "media_video";
+ break;
+ case MEDIA_EMPTY:
+ name = "media_empty";
+ break;
+ case MEDIA_MIXED:
+ name = "media_mixed";
+ break;
+ case MEDIA_NONE:
+ name = "media_none";
+ break;
+ case MEDIA_LEFT:
+ name = "media_left";
+ break;
+ case PROGRESS_WORKING:
+ name = "progress_working";
+ break;
+ case PROGRESS_SUCCESS:
+ name = "progress_success";
+ break;
+ case PROGRESS_FAIL:
+ name = "progress_fail";
+ break;
+ case PROGRESS_RIGHT:
+ name = "progress_right";
+ break;
+ case DIALOG_LEFT:
+ name = "dialog_left";
+ break;
+ case DIALOG_RIGHT:
+ name = "dialog_right";
+ break;
+ case SPLASH:
+ name = "splash";
+ break;
+ case PROJECT_LEFT:
+ name = "project_left";
+ break;
+ case PROJECT_RIGHT:
+ name = "project_right";
+ break;
+ case WELCOME_BG:
+ name = "welcome_bg";
+ break;
+ default:
+ break;
+ }
+
+ name.append( ".png" );
+
+ return name;
+}
+
+
+K3bTheme::BackgroundMode K3bTheme::backgroundMode() const
+{
+ return m_bgMode;
+}
+
+
+
+class K3bThemeManager::Private
+{
+public:
+ Private()
+ : currentTheme(&emptyTheme) {
+ }
+
+ QValueList<K3bTheme*> themes;
+ K3bTheme* currentTheme;
+ QString currentThemeName;
+
+ K3bTheme emptyTheme;
+};
+
+
+
+K3bThemeManager::K3bThemeManager( QObject* parent, const char* name )
+ : QObject( parent, name )
+{
+ d = new Private();
+ d->emptyTheme.m_name = "Empty Theme";
+}
+
+
+K3bThemeManager::~K3bThemeManager()
+{
+ delete d;
+}
+
+
+const QValueList<K3bTheme*>& K3bThemeManager::themes() const
+{
+ return d->themes;
+}
+
+
+K3bTheme* K3bThemeManager::currentTheme() const
+{
+ return d->currentTheme;
+}
+
+
+void K3bThemeManager::readConfig( KConfigBase* c )
+{
+ KConfigGroup generalOptions( c, "General Options" );
+
+ // allow to override the default theme by packaging a default config file
+ QString defaultTheme = generalOptions.readEntry( "default theme", "quant" );
+
+ K3bVersion configVersion( generalOptions.readEntry( "config version", "0.1" ) );
+ if( configVersion >= K3bVersion("0.98") )
+ setCurrentTheme( generalOptions.readEntry( "current theme", defaultTheme ) );
+ else
+ setCurrentTheme( defaultTheme );
+}
+
+
+void K3bThemeManager::saveConfig( KConfigBase* c )
+{
+ if( !d->currentThemeName.isEmpty() )
+ KConfigGroup( c, "General Options" ).writeEntry( "current theme", d->currentThemeName );
+}
+
+
+void K3bThemeManager::setCurrentTheme( const QString& name )
+{
+ if( name != d->currentThemeName ) {
+ if( K3bTheme* theme = findTheme( name ) )
+ setCurrentTheme( theme );
+ }
+}
+
+
+void K3bThemeManager::setCurrentTheme( K3bTheme* theme )
+{
+ if( !theme )
+ theme = d->themes.first();
+
+ if( theme ) {
+ if( theme != d->currentTheme ) {
+ d->currentTheme = theme;
+ d->currentThemeName = theme->name();
+
+ emit themeChanged();
+ emit themeChanged( theme );
+ }
+ }
+}
+
+
+K3bTheme* K3bThemeManager::findTheme( const QString& name ) const
+{
+ for( QValueList<K3bTheme*>::iterator it = d->themes.begin(); it != d->themes.end(); ++it )
+ if( (*it)->name() == name )
+ return *it;
+ return 0;
+}
+
+
+void K3bThemeManager::loadThemes()
+{
+ // first we cleanup the loaded themes
+ for( QValueList<K3bTheme*>::iterator it = d->themes.begin(); it != d->themes.end(); ++it )
+ delete *it;
+ d->themes.clear();
+
+ QStringList dirs = KGlobal::dirs()->findDirs( "data", "k3b/pics" );
+ // now search for themes. As there may be multiple themes with the same name
+ // we only use the names from this list and then use findResourceDir to make sure
+ // the local is preferred over the global stuff (like testing a theme by copying it
+ // to the .kde dir)
+ QStringList themeNames;
+ for( QStringList::const_iterator dirIt = dirs.begin(); dirIt != dirs.end(); ++dirIt ) {
+ QDir dir( *dirIt );
+ QStringList entries = dir.entryList( QDir::Dirs );
+ entries.remove( "." );
+ entries.remove( ".." );
+ // every theme dir needs to contain a k3b.theme file
+ for( QStringList::const_iterator entryIt = entries.begin(); entryIt != entries.end(); ++entryIt ) {
+ QString themeDir = *dirIt + *entryIt + "/";
+ if( !themeNames.contains( *entryIt ) && QFile::exists( themeDir + "k3b.theme" ) ) {
+ bool themeValid = true;
+
+ // check for all nessessary pixmaps (this is a little evil hacking)
+ for( int i = 0; i <= K3bTheme::WELCOME_BG; ++i ) {
+ if( !QFile::exists( themeDir + K3bTheme::filenameForPixmapType( (K3bTheme::PixmapType)i ) ) ) {
+ kdDebug() << "(K3bThemeManager) theme misses pixmap: " << K3bTheme::filenameForPixmapType( (K3bTheme::PixmapType)i ) << endl;
+ themeValid = false;
+ break;
+ }
+ }
+
+ if( themeValid )
+ themeNames.append( *entryIt );
+ }
+ }
+ }
+
+ // now load the themes
+ for( QStringList::const_iterator themeIt = themeNames.begin(); themeIt != themeNames.end(); ++themeIt )
+ loadTheme( *themeIt );
+
+ // load the current theme
+ setCurrentTheme( findTheme(d->currentThemeName) );
+}
+
+
+void K3bThemeManager::loadTheme( const QString& name )
+{
+ QString path = KGlobal::dirs()->findResource( "data", "k3b/pics/" + name + "/k3b.theme" );
+ if( !path.isEmpty() ) {
+ K3bTheme* t = new K3bTheme();
+ t->m_name = name;
+ t->m_path = path.left( path.length() - 9 );
+ QFileInfo fi( t->m_path );
+ t->m_local = fi.isWritable();
+
+ // load the stuff
+ KSimpleConfig cfg( path, true );
+ t->m_author = cfg.readEntry( "Author" );
+ t->m_comment = cfg.readEntry( "Comment" );
+ t->m_version = cfg.readEntry( "Version" );
+ t->m_bgColor = cfg.readColorEntry( "Backgroundcolor" );
+ t->m_fgColor = cfg.readColorEntry( "Foregroundcolor" );
+ t->m_bgMode = ( cfg.readEntry( "BackgroundMode" ) == "Scaled" ? K3bTheme::BG_SCALE : K3bTheme::BG_TILE );
+
+ d->themes.append( t );
+ }
+}
+
+
+#include "k3bthememanager.moc"
diff --git a/src/k3bthememanager.h b/src/k3bthememanager.h
new file mode 100644
index 0000000..f00e62f
--- /dev/null
+++ b/src/k3bthememanager.h
@@ -0,0 +1,146 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_THEME_MANAGER_H_
+#define _K3B_THEME_MANAGER_H_
+
+#include <qobject.h>
+#include <qvaluelist.h>
+#include <qstring.h>
+#include <qmap.h>
+#include <qcolor.h>
+#include <qpixmap.h>
+
+
+
+class KConfigBase;
+
+
+class K3bTheme
+{
+ public:
+ K3bTheme();
+
+ QColor backgroundColor() const;
+ QColor foregroundColor() const;
+
+ enum PixmapType {
+ MEDIA_AUDIO, /**< Media information header, right side when showing an audio CD. */
+ MEDIA_DATA, /**< Media information header, right side when showing a data media. */
+ MEDIA_VIDEO, /**< Media information header, right side when showing a video media. */
+ MEDIA_EMPTY, /**< Media information header, right side when showing an empty media. */
+ MEDIA_MIXED, /**< Media information header, right side when showing a mixed mode CD. */
+ MEDIA_NONE, /**< Media information header, right side default pixmap (no media). */
+ MEDIA_LEFT, /**< Media information header, left side. */
+ PROGRESS_WORKING, /**< Progress dialog, left top while working. */
+ PROGRESS_SUCCESS, /**< Progress dialog, left top on success. */
+ PROGRESS_FAIL, /**< Progress dialog, left top on failure. */
+ PROGRESS_RIGHT, /**< Progress dialog, right top. */
+ DIALOG_LEFT, /**< Action dialog, left top. */
+ DIALOG_RIGHT, /**< Action dialog, right top. */
+ SPLASH, /**< K3b splash screen. Size not important. */
+ PROJECT_LEFT, /**< Project header left side. */
+ PROJECT_RIGHT, /**< Project header right side. */
+ WELCOME_BG /**< Background pixmap of the welcome window. */
+ };
+
+ enum BackgroundMode {
+ BG_TILE, /**< Keep the pixmap's size and tile the welcome widget */
+ BG_SCALE /**< Scale the pixmap to fill the welcome widget. */
+ };
+
+ const QPixmap& pixmap( PixmapType ) const;
+
+ /**
+ * \deprecated use pixmap( PixmapType )
+ */
+ const QPixmap& pixmap( const QString& name ) const;
+
+ BackgroundMode backgroundMode() const;
+
+ const QString& name() const { return m_name; }
+ const QString& author() const { return m_author; }
+ const QString& comment() const { return m_comment; }
+ const QString& version() const { return m_version; }
+
+ /**
+ * Global themes are installed for all users and cannot be deleted.
+ */
+ bool global() const { return !local(); }
+
+ /**
+ * Local themes are installed in the user's home directory and can be deleted.
+ */
+ bool local() const { return m_local; }
+
+ const QString& path() const { return m_path; }
+
+ static QString filenameForPixmapType( PixmapType );
+
+ private:
+ QString m_path;
+ bool m_local;
+ QString m_name;
+ QString m_author;
+ QString m_comment;
+ QString m_version;
+ QColor m_bgColor;
+ QColor m_fgColor;
+ BackgroundMode m_bgMode;
+
+ mutable QMap<QString, QPixmap> m_pixmapMap;
+
+ QPixmap m_emptyPixmap;
+
+ friend class K3bThemeManager;
+};
+
+
+class K3bThemeManager : public QObject
+{
+ Q_OBJECT
+
+ public:
+ K3bThemeManager( QObject* parent = 0, const char* name = 0 );
+ ~K3bThemeManager();
+
+ const QValueList<K3bTheme*>& themes() const;
+
+ /**
+ * This is never null. If no theme could be found an empty dummy theme
+ * will be returnes which does not contains any pixmaps.
+ */
+ K3bTheme* currentTheme() const;
+ K3bTheme* findTheme( const QString& ) const;
+
+ signals:
+ void themeChanged();
+ void themeChanged( K3bTheme* );
+
+ public slots:
+ void readConfig( KConfigBase* );
+ void saveConfig( KConfigBase* );
+ void setCurrentTheme( const QString& );
+ void setCurrentTheme( K3bTheme* );
+ void loadThemes();
+
+ private:
+ void loadTheme( const QString& name );
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3btimeoutwidget.cpp b/src/k3btimeoutwidget.cpp
new file mode 100644
index 0000000..156963f
--- /dev/null
+++ b/src/k3btimeoutwidget.cpp
@@ -0,0 +1,149 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3btimeoutwidget.h"
+#include "k3bthememanager.h"
+#include "k3bapplication.h"
+
+#include <kiconloader.h>
+
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qbitmap.h>
+
+
+class K3bTimeoutWidget::Private
+{
+public:
+ int timeout;
+ int margin;
+
+ QTimer timer;
+ int currentTime;
+};
+
+
+K3bTimeoutWidget::K3bTimeoutWidget( QWidget* parent )
+ : QWidget( parent )
+{
+ d = new Private;
+ d->timeout = 10000;
+ d->margin = 4;
+ connect( &d->timer, SIGNAL(timeout()), this, SLOT(timeStep()) );
+}
+
+
+K3bTimeoutWidget::~K3bTimeoutWidget()
+{
+ delete d;
+}
+
+
+void K3bTimeoutWidget::start()
+{
+ d->currentTime = 0;
+ startTimer();
+}
+
+
+void K3bTimeoutWidget::stop()
+{
+ d->timer.stop();
+ d->currentTime = 0;
+}
+
+
+void K3bTimeoutWidget::pause()
+{
+ d->timer.stop();
+}
+
+
+void K3bTimeoutWidget::resume()
+{
+ startTimer();
+}
+
+
+void K3bTimeoutWidget::timeStep()
+{
+ d->currentTime += 100;
+ update();
+ if( d->currentTime >= d->timeout ) {
+ stop();
+ emit timeout();
+ }
+}
+
+
+QSize K3bTimeoutWidget::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+
+QSize K3bTimeoutWidget::minimumSizeHint() const
+{
+ int fw = fontMetrics().width( QString::number( d->timeout/1000 ) );
+ int fh = fontMetrics().height();
+
+ int diam = QMAX( fw, fh ) + 2*d->margin;
+
+ return QSize( diam, diam );
+}
+
+
+void K3bTimeoutWidget::setTimeout( int msecs )
+{
+ d->timeout = msecs;
+}
+
+
+void K3bTimeoutWidget::startTimer()
+{
+ d->timer.start( 100 );
+}
+
+
+void K3bTimeoutWidget::paintEvent( QPaintEvent* )
+{
+ if( d->timer.isActive() ) {
+ QPainter p(this);
+
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ p.setBrush( theme->backgroundColor() );
+ p.setPen( theme->backgroundColor() );
+ }
+
+ QRect r;
+ r.setSize( minimumSizeHint() );
+ r.moveCenter( rect().center() );
+
+ p.drawArc( r, 0, 360*16 );
+ p.drawPie( r, 90*16, 360*16*d->currentTime/d->timeout );
+
+ p.setPen( Qt::black );
+ p.drawText( rect(), Qt::AlignCenter, QString::number( (d->timeout - d->currentTime + 500)/1000 ) );
+ }
+}
+
+
+void K3bTimeoutWidget::resizeEvent( QResizeEvent* e )
+{
+ QWidget::resizeEvent( e );
+}
+
+
+#include "k3btimeoutwidget.moc"
diff --git a/src/k3btimeoutwidget.h b/src/k3btimeoutwidget.h
new file mode 100644
index 0000000..6f47deb
--- /dev/null
+++ b/src/k3btimeoutwidget.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_TIMEOUT_WIDGET_H_
+#define _K3B_TIMEOUT_WIDGET_H_
+
+#include <qwidget.h>
+
+class QPaintEvent;
+class QResizeEvent;
+
+
+class K3bTimeoutWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bTimeoutWidget( QWidget* parent );
+ ~K3bTimeoutWidget();
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ public slots:
+ void setTimeout( int msecs );
+ void start();
+ void stop();
+ void pause();
+ void resume();
+
+ signals:
+ void timeout();
+
+ protected:
+ void paintEvent( QPaintEvent* );
+ void resizeEvent( QResizeEvent* );
+
+ private slots:
+ void timeStep();
+ void startTimer();
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3btooltip.cpp b/src/k3btooltip.cpp
new file mode 100644
index 0000000..570c23b
--- /dev/null
+++ b/src/k3btooltip.cpp
@@ -0,0 +1,195 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3btooltip.h"
+#include "k3bwidgetshoweffect.h"
+
+#include <k3bthememanager.h>
+#include <k3bapplication.h>
+
+#include <qtimer.h>
+#include <qapplication.h>
+#include <qlabel.h>
+
+#include <kdebug.h>
+#include <fixx11h.h>
+
+
+K3bToolTip::K3bToolTip( QWidget* widget )
+ : QObject( widget ),
+ m_parentWidget( widget ),
+ m_currentTip( 0 ),
+ m_tipTimer( new QTimer( this ) ),
+ m_tipTimeout( 700 )
+{
+ m_parentWidget->installEventFilter( this );
+ connect( m_tipTimer, SIGNAL(timeout()),
+ this, SLOT(slotCheckShowTip()) );
+}
+
+
+K3bToolTip::~K3bToolTip()
+{
+}
+
+
+void K3bToolTip::tip( const QRect& rect, const QString& text, int effect )
+{
+ QLabel* label = new QLabel( text, parentWidget() );
+ label->setMargin( 6 );
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ label->setPaletteBackgroundColor( theme->backgroundColor() );
+ label->setPaletteForegroundColor( theme->foregroundColor() );
+ }
+ tip( rect, label, (K3bWidgetShowEffect::Effect)effect );
+}
+
+
+void K3bToolTip::tip( const QRect& rect, const QPixmap& pix, int effect )
+{
+ QLabel* label = new QLabel( parentWidget() );
+ label->setMargin( 6 );
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ label->setPaletteBackgroundColor( theme->backgroundColor() );
+ label->setPaletteForegroundColor( theme->foregroundColor() );
+ }
+ label->setPixmap( pix );
+ tip( rect, label, (K3bWidgetShowEffect::Effect)effect );
+}
+
+
+void K3bToolTip::tip( const QRect& rect, QWidget* w, int effect )
+{
+ // stop the timer
+ m_tipTimer->stop();
+
+ // hide any previous tip
+ hideTip();
+
+ // which screen are we on?
+ int scr;
+ if( QApplication::desktop()->isVirtualDesktop() )
+ scr = QApplication::desktop()->screenNumber( m_parentWidget->mapToGlobal( m_lastMousePos ) );
+ else
+ scr = QApplication::desktop()->screenNumber( m_parentWidget );
+
+ // make sure the widget is displayed correcly
+ w->reparent( QApplication::desktop()->screen( scr ),
+ WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM,
+ QPoint( 0, 0 ), false );
+ w->polish();
+ w->adjustSize();
+
+ // positioning code from qtooltip.cpp
+ QRect screen = QApplication::desktop()->screenGeometry( scr );
+
+ // FIXME: why (2,16) and (4,24) below? Why not use the cursors' size?
+
+ QPoint p = m_parentWidget->mapToGlobal( m_lastMousePos ) + QPoint( 2, 16 );
+
+ if( p.x() + w->width() > screen.x() + screen.width() )
+ p.rx() -= 4 + w->width();
+ if( p.y() + w->height() > screen.y() + screen.height() )
+ p.ry() -= 24 + w->height();
+
+ if( p.y() < screen.y() )
+ p.setY( screen.y() );
+ if( p.x() + w->width() > screen.x() + screen.width() )
+ p.setX( screen.x() + screen.width() - w->width() );
+ if( p.x() < screen.x() )
+ p.setX( screen.x() );
+ if( p.y() + w->height() > screen.y() + screen.height() )
+ p.setY( screen.y() + screen.height() - w->height() );
+
+ m_currentTip = w;
+ m_currentTipRect = rect;
+ w->move( p );
+ if( effect )
+ K3bWidgetShowEffect::showWidget( w, (K3bWidgetShowEffect::Effect)effect );
+ else
+ w->show();
+ w->raise();
+}
+
+
+void K3bToolTip::hideTip()
+{
+ // just remove the tip
+ delete m_currentTip;
+ m_currentTip = 0;
+}
+
+
+bool K3bToolTip::eventFilter( QObject* o, QEvent* e )
+{
+ if( o == parentWidget() ) {
+ switch( e->type() ) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ // input - turn off tool tip mode
+ hideTip();
+ m_tipTimer->stop();
+ break;
+
+ case QEvent::MouseMove: {
+ QMouseEvent* m = (QMouseEvent*)e;
+ m_lastMousePos = m_parentWidget->mapFromGlobal( m->globalPos() );
+
+ m_tipTimer->stop();
+ if( m_currentTip ) {
+ // see if we have to hide it
+ if( !m_currentTipRect.contains( m_lastMousePos ) ) {
+ hideTip();
+
+ // in case we moved the mouse from one tip area to the next without leaving
+ // the widget just popup the new tip immedeately
+ m_tipTimer->start( 0, true );
+ }
+ }
+
+ // if we are not showing a tip currently start the tip timer
+ else
+ m_tipTimer->start( m_tipTimeout, true );
+
+ break;
+ }
+
+ case QEvent::Leave:
+ case QEvent::Hide:
+ case QEvent::Destroy:
+ case QEvent::FocusOut:
+ hideTip();
+ m_tipTimer->stop();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+
+void K3bToolTip::slotCheckShowTip()
+{
+ maybeTip( m_lastMousePos );
+}
+
+
+#include "k3btooltip.moc"
diff --git a/src/k3btooltip.h b/src/k3btooltip.h
new file mode 100644
index 0000000..878f512
--- /dev/null
+++ b/src/k3btooltip.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_TOOLTIP_H_
+#define _K3B_TOOLTIP_H_
+
+#include <qobject.h>
+#include <qpixmap.h>
+
+#include "k3bwidgetshoweffect.h"
+
+class QTimer;
+
+/**
+ * More beautiful tooltip
+ */
+class K3bToolTip : public QObject
+{
+ Q_OBJECT
+
+ public:
+ K3bToolTip( QWidget* widget );
+ ~K3bToolTip();
+
+ QWidget* parentWidget() const { return m_parentWidget; }
+
+ public slots:
+ /**
+ * default is 700 mseconds (same as QToolTip)
+ */
+ void setTipTimeout( int msec ) { m_tipTimeout = msec; }
+
+ protected:
+ /**
+ * \see QToolTip::maybeTip
+ */
+ virtual void maybeTip( const QPoint& ) = 0;
+
+ /**
+ * Show a tooltip.
+ */
+ void tip( const QRect&, const QString&, int effect = K3bWidgetShowEffect::Dissolve );
+ void tip( const QRect& rect, const QPixmap& pix, int effect = K3bWidgetShowEffect::Dissolve );
+
+ /**
+ * Use some arbitrary widget as the tooltip
+ * \param effect Use 0 for no effect
+ */
+ void tip( const QRect&, QWidget* w, int effect = K3bWidgetShowEffect::Dissolve );
+
+ bool eventFilter( QObject* o, QEvent* e );
+
+ private slots:
+ void slotCheckShowTip();
+
+ private:
+ void hideTip();
+
+ QWidget* m_parentWidget;
+ QWidget* m_currentTip;
+ QRect m_currentTipRect;
+
+ QTimer* m_tipTimer;
+ QPoint m_lastMousePos;
+
+ int m_tipTimeout;
+};
+
+#endif
diff --git a/src/k3btrm.cpp b/src/k3btrm.cpp
new file mode 100644
index 0000000..9d4f24d
--- /dev/null
+++ b/src/k3btrm.cpp
@@ -0,0 +1,93 @@
+/*
+ *
+ * $Id: k3btrm.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_MUSICBRAINZ
+
+#include "k3btrm.h"
+#include "musicbrainz/mb_c.h"
+
+#include <kdebug.h>
+#include <kprotocolmanager.h>
+#include <kurl.h>
+
+
+class K3bTRM::Private
+{
+public:
+ trm_t trm;
+ QCString sig;
+ QCString rawSig;
+};
+
+
+K3bTRM::K3bTRM()
+{
+ d = new Private;
+ d->trm = trm_New();
+ d->rawSig.resize( 17 );
+ d->sig.resize( 37 );
+}
+
+
+K3bTRM::~K3bTRM()
+{
+ trm_Delete( d->trm );
+ delete d;
+}
+
+
+void K3bTRM::start( const K3b::Msf& length )
+{
+ if( KProtocolManager::useProxy() ) {
+ KURL proxy = KProtocolManager::proxyFor("http");
+ trm_SetProxy( d->trm, const_cast<char*>(proxy.host().latin1()), short(proxy.port()) );
+ }
+
+ trm_SetPCMDataInfo( d->trm, 44100, 2, 16 );
+ trm_SetSongLength( d->trm, length.totalFrames()/75 );
+}
+
+
+bool K3bTRM::generate( char* data, int len )
+{
+ return ( trm_GenerateSignature( d->trm, data, len ) == 1 );
+}
+
+
+bool K3bTRM::finalize()
+{
+ if( trm_FinalizeSignature( d->trm, d->rawSig.data(), 0 ) == 0 ) {
+ trm_ConvertSigToASCII( d->trm, d->rawSig.data(), d->sig.data() );
+ return true;
+ }
+ else
+ return false;
+}
+
+
+const QCString& K3bTRM::rawSignature() const
+{
+ return d->rawSig;
+}
+
+
+const QCString& K3bTRM::signature() const
+{
+ return d->sig;
+}
+
+#endif
diff --git a/src/k3btrm.h b/src/k3btrm.h
new file mode 100644
index 0000000..722a769
--- /dev/null
+++ b/src/k3btrm.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * $Id: k3btrm.h 630384 2007-02-05 09:33:17Z mlaurent $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_TRM_H_
+#define _K3B_TRM_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_MUSICBRAINZ
+
+#include <k3bmsf.h>
+
+/**
+ * This class is a wrapper around the trm part of libmusicbrainz.
+ * It handles proxy settings automatically through KDE.
+ *
+ * K3bTRM always treats audio data as 44100, 2 channel, 16 bit data.
+ */
+class K3bTRM
+{
+ public:
+ K3bTRM();
+ ~K3bTRM();
+
+ void start( const K3b::Msf& length );
+
+ /**
+ * \return true if no more data is needed
+ */
+ bool generate( char* data, int len );
+
+ /**
+ * \return true on success, false on error.
+ */
+ bool finalize();
+
+ const QCString& rawSignature() const;
+ const QCString& signature() const;
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
+#endif
diff --git a/src/k3bui.rc b/src/k3bui.rc
new file mode 100644
index 0000000..24a8af8
--- /dev/null
+++ b/src/k3bui.rc
@@ -0,0 +1,78 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="k3b" version="8">
+<MenuBar>
+ <Menu name="project"><text>&amp;Project</text>
+ <Action name="project_add_files" />
+ <Action name="project_clear_project" />
+ </Menu>
+
+ <Menu name="tools"><text>&amp;Tools</text>
+ <Action name="tools_copy_cd" />
+ <Action name="tools_copy_dvd" />
+ <Separator />
+ <Action name="tools_blank_cdrw" />
+ <Action name="tools_format_dvd" />
+ <Separator />
+ <Action name="tools_write_cd_image" />
+ <Action name="tools_write_dvd_iso" />
+ <Separator />
+ <Action name="tools_cdda_rip" />
+ <Action name="tools_videodvd_rip" />
+ <Action name="tools_videocd_rip" />
+ </Menu>
+
+ <Menu name="device"><text>&amp;Device</text>
+ <Action name ="device_diskinfo" />
+ <Separator />
+ <Action name ="device_unmount" />
+ <Action name ="device_mount" />
+ <Separator />
+ <Action name ="device_eject" />
+ <Action name ="device_load" />
+ <Separator />
+ <Action name ="device_set_read_speed" />
+ </Menu>
+
+ <Menu name="settings">
+ <Action name="view_show_project_view" append="show_merge" />
+ <Action name="view_dir_tree" append="show_merge" />
+ <Action name="view_contents" append="show_merge" />
+ <Action name="view_audio_player" append="show_merge" />
+ <Action name="view_document_header" append="show_merge" />
+ <Action name="settings_k3bsetup" append="configure_merge" />
+ </Menu>
+
+ <Menu name="help"><text>&amp;Help</text>
+ <Action name="help_check_system" />
+ </Menu>
+</MenuBar>
+
+<ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text>
+ <Action name="file_new" />
+ <Action name="file_open" />
+ <Action name="file_save" />
+</ToolBar>
+
+<ToolBar name="toolsToolBar"><text>Tools</text>
+ <Action name="tools_copy_cd" />
+ <Action name="tools_copy_dvd" />
+ <Action name="tools_blank_cdrw" />
+ <Action name="tools_format_dvd" />
+</ToolBar>
+
+<ToolBar name="quickDirSelector" fullWidth="true"><text>Quick Dir Selector</text>
+ <Action name="quick_dir_selector" />
+ <Action name="go_url" />
+</ToolBar>
+
+<State name="state_project_active">
+ <enable>
+ <Action name="file_save" />
+ <Action name="file_save_as" />
+ <Action name="file_close" />
+ <Action name="file_close_all" />
+ <Action name="project_add_files" />
+ <Action name="project_clear_project" />
+ </enable>
+</State>
+</kpartgui>
diff --git a/src/k3bwelcomewidget.cpp b/src/k3bwelcomewidget.cpp
new file mode 100644
index 0000000..a3915d5
--- /dev/null
+++ b/src/k3bwelcomewidget.cpp
@@ -0,0 +1,489 @@
+/*
+ *
+ * $Id: k3bwelcomewidget.cpp 676186 2007-06-16 08:53:46Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bwelcomewidget.h"
+#include "k3b.h"
+#include "k3bflatbutton.h"
+#include <k3bstdguiitems.h>
+#include "k3bapplication.h"
+#include <k3bversion.h>
+#include "k3bthememanager.h"
+
+#include <qpixmap.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qpainter.h>
+#include <qsimplerichtext.h>
+#include <qptrlist.h>
+#include <qmap.h>
+#include <qtooltip.h>
+#include <qcursor.h>
+#include <qimage.h>
+
+#include <kurl.h>
+#include <kurldrag.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <kaboutdata.h>
+#include <kactionclasses.h>
+
+
+static const char* s_allActions[] = {
+ "file_new_data",
+ "file_new_dvd",
+ "file_continue_multisession",
+ "_sep_",
+ "file_new_audio",
+ "_sep_",
+ "file_new_mixed",
+ "_sep_",
+ "file_new_vcd",
+ "file_new_video_dvd",
+ "_sep_",
+ "file_new_movix",
+ "file_new_movix_dvd",
+ "_sep_",
+ "tools_copy_cd",
+ "tools_copy_dvd",
+ "_sep_",
+ "tools_blank_cdrw",
+ "tools_format_dvd",
+ "_sep_",
+ "tools_write_cd_image",
+ "tools_write_dvd_iso",
+ "_sep_",
+ "tools_cdda_rip",
+ "tools_videodvd_rip",
+ "tools_videocd_rip",
+ 0
+};
+
+K3bWelcomeWidget::Display::Display( K3bWelcomeWidget* parent )
+ : QWidget( parent->viewport() )
+{
+ setWFlags( Qt::WNoAutoErase );
+
+ QFont fnt(font());
+ fnt.setBold(true);
+ fnt.setPointSize( 16 );
+ m_header = new QSimpleRichText( i18n("Welcome to K3b - The CD and DVD Kreator"), fnt );
+ m_infoText = new QSimpleRichText( QString::fromUtf8("<qt align=\"center\">K3b %1 (c) 1999 - 2007 Sebastian Trüg")
+ .arg(kapp->aboutData()->version()), font() );
+
+ // set a large width just to be sure no linebreak occurs
+ m_header->setWidth( 800 );
+
+ setAcceptDrops( true );
+ setBackgroundMode( PaletteBase );
+ m_rows = m_cols = 1;
+
+ m_buttonMore = new K3bFlatButton( i18n("Further actions..."), this );
+ connect( m_buttonMore, SIGNAL(pressed()), parent, SLOT(slotMoreActions()) );
+
+ connect( k3bappcore->themeManager(), SIGNAL(themeChanged()), this, SLOT(slotThemeChanged()) );
+
+ slotThemeChanged();
+}
+
+
+K3bWelcomeWidget::Display::~Display()
+{
+ delete m_header;
+ delete m_infoText;
+}
+
+
+void K3bWelcomeWidget::Display::addAction( KAction* action )
+{
+ if( action ) {
+ m_actions.append(action);
+ rebuildGui();
+ }
+}
+
+
+void K3bWelcomeWidget::Display::removeAction( KAction* action )
+{
+ if( action ) {
+ m_actions.removeRef( action );
+ rebuildGui();
+ }
+}
+
+
+void K3bWelcomeWidget::Display::removeButton( K3bFlatButton* b )
+{
+ removeAction( m_buttonMap[b] );
+}
+
+
+void K3bWelcomeWidget::Display::rebuildGui( const QPtrList<KAction>& actions )
+{
+ m_actions = actions;
+ rebuildGui();
+}
+
+
+static void calculateButtons( int width, int numActions, int buttonWidth, int& cols, int& rows )
+{
+ // always try to avoid horizontal scrollbars
+ int wa = width - 40;
+ cols = QMAX( 1, QMIN( wa / (buttonWidth+4), numActions ) );
+ rows = numActions/cols;
+ int over = numActions%cols;
+ if( over ) {
+ rows++;
+ // try to avoid useless cols
+ while( over && cols - over - 1 >= rows-1 ) {
+ --cols;
+ over = numActions%cols;
+ }
+ }
+}
+
+
+void K3bWelcomeWidget::Display::rebuildGui()
+{
+ // step 1: delete all old buttons in the buttons QPtrList<K3bFlatButton>
+ m_buttonMap.clear();
+ m_buttons.setAutoDelete(true);
+ m_buttons.clear();
+
+ int numActions = m_actions.count();
+ if( numActions > 0 ) {
+
+ // create buttons
+ for( QPtrListIterator<KAction> it( m_actions ); it.current(); ++it ) {
+ KAction* a = it.current();
+
+ K3bFlatButton* b = new K3bFlatButton( a, this );
+
+ m_buttons.append( b );
+ m_buttonMap.insert( b, a );
+ }
+
+ // determine the needed button size (since all buttons should be equal in size
+ // we use the max of all sizes)
+ m_buttonSize = m_buttons.first()->sizeHint();
+ for( QPtrListIterator<K3bFlatButton> it( m_buttons ); it.current(); ++it ) {
+ m_buttonSize = m_buttonSize.expandedTo( it.current()->sizeHint() );
+ }
+
+ repositionButtons();
+ }
+}
+
+
+void K3bWelcomeWidget::Display::repositionButtons()
+{
+ // calculate rows and columns
+ calculateButtons( width(), m_actions.count(), m_buttonSize.width(), m_cols, m_rows );
+
+ int availHor = width() - 40;
+ int availVert = height() - 20 - 10 - m_header->height() - 10;
+ availVert -= m_infoText->height() - 10;
+ int leftMargin = 20 + (availHor - (m_buttonSize.width()+4)*m_cols)/2;
+ int topOffset = m_header->height() + 20 + ( availVert - (m_buttonSize.height()+4)*m_rows - m_buttonMore->height() )/2;
+
+ int row = 0;
+ int col = 0;
+
+ for( QPtrListIterator<K3bFlatButton> it( m_buttons ); it.current(); ++it ) {
+ K3bFlatButton* b = it.current();
+
+ b->setGeometry( QRect( QPoint( leftMargin + (col*(m_buttonSize.width()+4) + 2 ),
+ topOffset + (row*(m_buttonSize.height()+4)) + 2 ),
+ m_buttonSize ) );
+ b->show();
+
+ col++;
+ if( col == m_cols ) {
+ col = 0;
+ row++;
+ }
+ }
+ if( col > 0 )
+ ++row;
+
+ m_buttonMore->setGeometry( QRect( QPoint( leftMargin + 2,
+ topOffset + (row*(m_buttonSize.height()+4)) + 2 ),
+ QSize( m_cols*(m_buttonSize.width()+4) - 4, m_buttonMore->height() ) ) );
+}
+
+
+QSizePolicy K3bWelcomeWidget::Display::sizePolicy () const
+{
+ return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum, true );
+}
+
+
+int K3bWelcomeWidget::Display::heightForWidth( int w ) const
+{
+ int ow = m_infoText->width();
+ m_infoText->setWidth( w );
+ int h = m_infoText->height();
+ m_infoText->setWidth( ow );
+
+ int cols, rows;
+ calculateButtons( w, m_actions.count(), m_buttonSize.width(), cols, rows );
+
+ return (20 + m_header->height() + 20 + 10 + ((m_buttonSize.height()+4)*rows) + 4 + m_buttonMore->height() + 10 + h + 20);
+}
+
+
+QSize K3bWelcomeWidget::Display::minimumSizeHint() const
+{
+ QSize size( QMAX(40+m_header->widthUsed(), 40+m_buttonSize.width()),
+ 20 + m_header->height() + 20 + 10 + m_buttonSize.height() + 10 + m_infoText->height() + 20 );
+
+ return size;
+}
+
+
+void K3bWelcomeWidget::Display::resizeEvent( QResizeEvent* e )
+{
+ m_infoText->setWidth( width() - 20 );
+ QWidget::resizeEvent(e);
+ repositionButtons();
+ if( e->size() != m_bgPixmap.size() )
+ updateBgPix();
+}
+
+
+void K3bWelcomeWidget::Display::slotThemeChanged()
+{
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() )
+ if( theme->backgroundMode() == K3bTheme::BG_SCALE )
+ m_bgImage = theme->pixmap( K3bTheme::WELCOME_BG ).convertToImage();
+
+ updateBgPix();
+ update();
+}
+
+#include "fastscale/scale.h"
+void K3bWelcomeWidget::Display::updateBgPix()
+{
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ if( theme->backgroundMode() == K3bTheme::BG_SCALE )
+ m_bgPixmap.convertFromImage( ImageUtils::scale( m_bgImage, rect().width(), rect().height(), ImageUtils::SMOOTH_FAST ) );
+ else
+ m_bgPixmap = theme->pixmap( K3bTheme::WELCOME_BG );
+ }
+}
+
+
+void K3bWelcomeWidget::Display::paintEvent( QPaintEvent* )
+{
+ if( K3bTheme* theme = k3bappcore->themeManager()->currentTheme() ) {
+ QPainter p( this );
+ p.setPen( theme->foregroundColor() );
+
+ // draw the background including first filling with the bg color for transparent images
+ p.fillRect( rect(), theme->backgroundColor() );
+ p.drawTiledPixmap( rect(), m_bgPixmap );
+
+ // rect around the header
+ QRect rect( 10, 10, QMAX( m_header->widthUsed() + 20, width() - 20 ), m_header->height() + 20 );
+ p.fillRect( rect, theme->backgroundColor() );
+ p.drawRect( rect );
+
+ // big rect around the whole thing
+ p.drawRect( 10, 10, width()-20, height()-20 );
+
+ // draw the header text
+ QColorGroup grp( colorGroup() );
+ grp.setColor( QColorGroup::Text, theme->foregroundColor() );
+ int pos = 20;
+ pos += QMAX( (width()-40-m_header->widthUsed())/2, 0 );
+ m_header->draw( &p, pos, 20, QRect(), grp );
+
+ // draw the info box
+ // int boxWidth = 20 + m_infoText->widthUsed();
+ int boxHeight = 10 + m_infoText->height();
+ QRect infoBoxRect( 10/*QMAX( (width()-20-m_infoText->widthUsed())/2, 10 )*/,
+ height()-10-boxHeight,
+ width()-20/*boxWidth*/,
+ boxHeight );
+ p.fillRect( infoBoxRect, theme->backgroundColor() );
+ p.drawRect( infoBoxRect );
+ m_infoText->draw( &p, infoBoxRect.left()+5, infoBoxRect.top()+5, QRect(), grp );
+ }
+}
+
+
+void K3bWelcomeWidget::Display::dragEnterEvent( QDragEnterEvent* event )
+{
+ event->accept( KURLDrag::canDecode(event) );
+}
+
+
+void K3bWelcomeWidget::Display::dropEvent( QDropEvent* e )
+{
+ KURL::List urls;
+ KURLDrag::decode( e, urls );
+ emit dropped( urls );
+}
+
+
+
+K3bWelcomeWidget::K3bWelcomeWidget( K3bMainWindow* mw, QWidget* parent, const char* name )
+ : QScrollView( parent, name ),
+ m_mainWindow( mw )
+{
+ main = new Display( this );
+ addChild( main );
+
+ connect( main, SIGNAL(dropped(const KURL::List&)), m_mainWindow, SLOT(addUrls(const KURL::List&)) );
+
+ connect( kapp, SIGNAL(appearanceChanged()), main, SLOT(update()) );
+}
+
+
+K3bWelcomeWidget::~K3bWelcomeWidget()
+{
+}
+
+
+void K3bWelcomeWidget::loadConfig( KConfigBase* c )
+{
+ QStringList sl = KConfigGroup( c, "Welcome Widget" ).readListEntry( "welcome_actions" );
+
+ if( sl.isEmpty() ) {
+ sl.append( "file_new_audio" );
+ sl.append( "file_new_data" );
+ sl.append( "file_new_dvd" );
+ sl.append( "tools_copy_cd" );
+ sl.append( "tools_write_cd_image" );
+ sl.append( "tools_write_dvd_iso" );
+ }
+
+ QPtrList<KAction> actions;
+ for( QStringList::const_iterator it = sl.begin(); it != sl.end(); ++it )
+ if( KAction* a = m_mainWindow->actionCollection()->action( (*it).latin1() ) )
+ actions.append(a);
+
+ main->rebuildGui( actions );
+
+ fixSize();
+}
+
+
+void K3bWelcomeWidget::saveConfig( KConfigBase* c )
+{
+ KConfigGroup grp( c, "Welcome Widget" );
+
+ QStringList sl;
+ for( QPtrListIterator<KAction> it( main->m_actions ); it.current(); ++it )
+ sl.append( it.current()->name() );
+
+ grp.writeEntry( "welcome_actions", sl );
+}
+
+
+void K3bWelcomeWidget::resizeEvent( QResizeEvent* e )
+{
+ QScrollView::resizeEvent( e );
+ fixSize();
+}
+
+
+void K3bWelcomeWidget::showEvent( QShowEvent* e )
+{
+ QScrollView::showEvent( e );
+ fixSize();
+}
+
+
+void K3bWelcomeWidget::fixSize()
+{
+ QSize s = contentsRect().size();
+ s.setWidth( QMAX( main->minimumSizeHint().width(), s.width() ) );
+ s.setHeight( QMAX( main->heightForWidth(s.width()), s.height() ) );
+
+ main->resize( s );
+ viewport()->resize( s );
+}
+
+
+void K3bWelcomeWidget::contentsMousePressEvent( QMouseEvent* e )
+{
+ if( e->button() == QMouseEvent::RightButton ) {
+ QMap<int, KAction*> map;
+ KPopupMenu addPop;
+
+ for ( int i = 0; s_allActions[i]; ++i ) {
+ if ( s_allActions[i][0] != '_' ) {
+ KAction* a = m_mainWindow->actionCollection()->action( s_allActions[i] );
+ if ( a && !main->m_actions.containsRef(a) ) {
+ map.insert( addPop.insertItem( a->iconSet(), a->text() ), a );
+ }
+ }
+ }
+
+ // menu identifiers in QT are always < 0 (when automatically generated)
+ // and unique throughout the entire application!
+ int r = 0;
+ int removeAction = 0;
+
+ QWidget* widgetAtPos = viewport()->childAt(e->pos());
+ if( widgetAtPos && widgetAtPos->inherits( "K3bFlatButton" ) ) {
+ KPopupMenu pop;
+ removeAction = pop.insertItem( SmallIcon("remove"), i18n("Remove Button") );
+ if ( addPop.count() > 0 )
+ pop.insertItem( i18n("Add Button"), &addPop );
+ pop.insertSeparator();
+ r = pop.exec( e->globalPos() );
+ }
+ else {
+ addPop.insertTitle( i18n("Add Button"), -1, 0 );
+ addPop.insertSeparator();
+ r = addPop.exec( e->globalPos() );
+ }
+
+ if( r != 0 ) {
+ if( r == removeAction )
+ main->removeButton( static_cast<K3bFlatButton*>(widgetAtPos) );
+ else
+ main->addAction( map[r] );
+ }
+
+ fixSize();
+ }
+}
+
+
+void K3bWelcomeWidget::slotMoreActions()
+{
+ KPopupMenu popup;
+
+ for ( int i = 0; s_allActions[i]; ++i ) {
+ if ( s_allActions[i][0] == '_' ) {
+ (new KActionSeparator( &popup ))->plug( &popup );
+ }
+ else {
+ m_mainWindow->actionCollection()->action( s_allActions[i] )->plug( &popup );
+ }
+ }
+
+ popup.exec( QCursor::pos() );
+}
+
+#include "k3bwelcomewidget.moc"
diff --git a/src/k3bwelcomewidget.h b/src/k3bwelcomewidget.h
new file mode 100644
index 0000000..df1945f
--- /dev/null
+++ b/src/k3bwelcomewidget.h
@@ -0,0 +1,124 @@
+/*
+ *
+ * $Id: k3bwelcomewidget.h 642063 2007-03-13 09:40:13Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_WELCOME_WIDGET_H_
+#define _K3B_WELCOME_WIDGET_H_
+
+#include <qscrollview.h>
+#include <qptrlist.h>
+#include <qmap.h>
+#include <qimage.h>
+
+#include <kurl.h>
+#include <kaction.h>
+
+class K3bMainWindow;
+class QDropEvent;
+class QDragEnterEvent;
+class K3bFlatButton;
+class QPaintEvent;
+class QResizeEvent;
+class QSimpleRichText;
+class KConfigBase;
+class QMouseEvent;
+class QShowEvent;
+
+
+class K3bWelcomeWidget : public QScrollView
+{
+ Q_OBJECT
+
+ public:
+ K3bWelcomeWidget( K3bMainWindow*, QWidget* parent = 0, const char* name = 0 );
+ ~K3bWelcomeWidget();
+
+ void loadConfig( KConfigBase* c );
+ void saveConfig( KConfigBase* c );
+
+ class Display;
+
+ public slots:
+ void slotMoreActions();
+
+ protected:
+ void resizeEvent( QResizeEvent* );
+ void showEvent( QShowEvent* );
+ void contentsMousePressEvent( QMouseEvent* e );
+
+ private:
+ void fixSize();
+
+ K3bMainWindow* m_mainWindow;
+ Display* main;
+};
+
+
+class K3bWelcomeWidget::Display : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ Display( K3bWelcomeWidget* parent );
+ ~Display();
+
+ QSize minimumSizeHint() const;
+ QSizePolicy sizePolicy () const;
+ int heightForWidth ( int w ) const;
+
+ void addAction( KAction* );
+ void removeAction( KAction* );
+ void removeButton( K3bFlatButton* );
+ void rebuildGui();
+ void rebuildGui( const QPtrList<KAction>& );
+
+ signals:
+ void dropped( const KURL::List& );
+
+ protected:
+ void resizeEvent( QResizeEvent* );
+ void paintEvent( QPaintEvent* );
+ void dropEvent( QDropEvent* event );
+ void dragEnterEvent( QDragEnterEvent* event );
+
+ private slots:
+ void slotThemeChanged();
+
+ private:
+ void repositionButtons();
+ void updateBgPix();
+
+ QSimpleRichText* m_header;
+ QSimpleRichText* m_infoText;
+
+ QSize m_buttonSize;
+ int m_cols;
+ int m_rows;
+
+ QPtrList<KAction> m_actions;
+ QPtrList<K3bFlatButton> m_buttons;
+ QMap<K3bFlatButton*, KAction*> m_buttonMap;
+
+ K3bFlatButton* m_buttonMore;
+
+ bool m_infoTextVisible;
+
+ QPixmap m_bgPixmap;
+ QImage m_bgImage;
+
+ friend class K3bWelcomeWidget;
+};
+
+#endif
diff --git a/src/k3bwidgetshoweffect.cpp b/src/k3bwidgetshoweffect.cpp
new file mode 100644
index 0000000..1caa971
--- /dev/null
+++ b/src/k3bwidgetshoweffect.cpp
@@ -0,0 +1,203 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * Based on the effects in popupMessage.cpp
+ * Copyright (C) 2005 by Max Howell <max.howell@methylblue.com>
+ * 2005 by Seb Ruiz <me@sebruiz.net>
+ *
+ * Dissolve Mask (c) Kicker Authors kickertip.cpp, 2005/08/17
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bwidgetshoweffect.h"
+
+#include <qpainter.h>
+#include <qwidget.h>
+
+
+K3bWidgetShowEffect::K3bWidgetShowEffect( QWidget* widget, Effect e )
+ : QObject( widget ),
+ m_effect( e ),
+ m_widget( widget ),
+ m_dissolveSize( 0 ),
+ m_dissolveDelta( -1 ),
+ m_offset( 0 ),
+ m_deleteSelf( false ),
+ m_bEffectOnly( false )
+{
+}
+
+
+K3bWidgetShowEffect::~K3bWidgetShowEffect()
+{
+}
+
+
+void K3bWidgetShowEffect::hide( bool effectOnly )
+{
+ m_bEffectOnly = effectOnly;
+ m_bShow = false;
+ m_offset = m_widget->height();
+ killTimer( m_timerId );
+ m_timerId = startTimer( 6 );
+}
+
+
+void K3bWidgetShowEffect::show( bool effectOnly )
+{
+ m_bShow = true;
+ m_offset = 0;
+ m_dissolveSize = 24;
+ m_dissolveDelta = -1;
+
+ m_widget->polish();
+
+ if( m_effect == Dissolve ) {
+ // necessary to create the mask
+ m_mask.resize( m_widget->width(), m_widget->height() );
+ // make the mask empty and hence will not show widget with show() called below
+ dissolveMask();
+ m_timerId = startTimer( 1000 / 30 );
+ }
+ else {
+ m_widget->move( 0, m_widget->parentWidget()->height() );
+ m_timerId = startTimer( 6 );
+ }
+
+ if( !effectOnly )
+ m_widget->show();
+}
+
+
+void K3bWidgetShowEffect::timerEvent( QTimerEvent* )
+{
+ switch( m_effect ) {
+ case Slide:
+ slideMask();
+ break;
+
+ case Dissolve:
+ dissolveMask();
+ break;
+ }
+}
+
+
+void K3bWidgetShowEffect::dissolveMask()
+{
+ if( m_bShow ) {
+ m_widget->repaint( false );
+ QPainter maskPainter(&m_mask);
+
+ m_mask.fill(Qt::black);
+
+ maskPainter.setBrush(Qt::white);
+ maskPainter.setPen(Qt::white);
+ maskPainter.drawRect( m_mask.rect() );
+
+ m_dissolveSize += m_dissolveDelta;
+
+ if( m_dissolveSize > 0 ) {
+ maskPainter.setRasterOp( Qt::EraseROP );
+
+ int x, y, s;
+ const int size = 16;
+
+ for( y = 0; y < m_widget->height() + size; y += size ) {
+ x = m_widget->width();
+ s = m_dissolveSize * x / 128;
+
+ for( ; x > size; x -= size, s -= 2 ) {
+ if( s < 0 )
+ break;
+
+ maskPainter.drawEllipse(x - s / 2, y - s / 2, s, s);
+ }
+ }
+ }
+ else if( m_dissolveSize < 0 ) {
+ m_dissolveDelta = 1;
+ killTimer( m_timerId );
+
+ emit widgetShown( m_widget );
+
+ if( m_deleteSelf )
+ deleteLater();
+ }
+
+ m_widget->setMask( m_mask );
+ }
+
+ else {
+ // just hide it for now
+ emit widgetHidden( m_widget );
+ if( !m_bEffectOnly )
+ m_widget->hide();
+
+ if( m_deleteSelf )
+ deleteLater();
+ }
+}
+
+
+void K3bWidgetShowEffect::slideMask()
+{
+ if( m_bShow ) {
+ m_widget->move( 0, m_widget->parentWidget()->height() - m_offset );
+
+ m_offset++;
+ if( m_offset > m_widget->height() ) {
+ killTimer( m_timerId );
+
+ emit widgetShown( m_widget );
+
+ if( m_deleteSelf )
+ deleteLater();
+ }
+ }
+ else {
+ m_offset--;
+ m_widget->move( 0, m_widget->parentWidget()->height() - m_offset );
+
+ if( m_offset < 0 ) {
+ // finally hide the widget
+ emit widgetHidden( m_widget );
+ if( !m_bEffectOnly )
+ m_widget->hide();
+
+ if( m_deleteSelf )
+ deleteLater();
+ }
+ }
+}
+
+
+
+K3bWidgetShowEffect* K3bWidgetShowEffect::showWidget( QWidget* w, Effect m )
+{
+ K3bWidgetShowEffect* e = new K3bWidgetShowEffect( w, m );
+ e->m_deleteSelf = true;
+ e->show();
+ return e;
+}
+
+
+K3bWidgetShowEffect* K3bWidgetShowEffect::hideWidget( QWidget* w, Effect m )
+{
+ K3bWidgetShowEffect* e = new K3bWidgetShowEffect( w, m );
+ e->m_deleteSelf = true;
+ e->hide();
+ return e;
+}
+
+#include "k3bwidgetshoweffect.moc"
diff --git a/src/k3bwidgetshoweffect.h b/src/k3bwidgetshoweffect.h
new file mode 100644
index 0000000..9e0de9b
--- /dev/null
+++ b/src/k3bwidgetshoweffect.h
@@ -0,0 +1,115 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * Based on the effects in popupMessage.cpp
+ * Copyright (C) 2005 by Max Howell <max.howell@methylblue.com>
+ * 2005 by Seb Ruiz <me@sebruiz.net>
+ *
+ * Dissolve Mask (c) Kicker Authors kickertip.cpp, 2005/08/17
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_WIDGET_SHOW_EFFECT_H_
+#define _K3B_WIDGET_SHOW_EFFECT_H_
+
+#include <qobject.h>
+#include <qbitmap.h>
+
+
+/**
+ * Helper class to show and hide a widget in a fancy way.
+ */
+class K3bWidgetShowEffect : public QObject
+{
+ Q_OBJECT
+
+ public:
+ // FIXME: add an effect direction
+ enum Effect {
+ Dissolve = 1,
+ Slide
+ };
+
+ K3bWidgetShowEffect( QWidget* widget, Effect e = Slide );
+ ~K3bWidgetShowEffect();
+
+ void setEffect( Effect e ) { m_effect = e; }
+
+ /**
+ * Using the widget effects the easy way.
+ * \returns the K3bWidgetShowEffect instance used to show the widget.
+ * Can be used to connect to signals.
+ */
+ static K3bWidgetShowEffect* showWidget( QWidget* w, Effect );
+
+ /**
+ * Using the widget effects the easy way.
+ * \returns the K3bWidgetShowEffect instance used to hide the widget.
+ * Can be used to connect to signals.
+ */
+ static K3bWidgetShowEffect* hideWidget( QWidget* w, Effect );
+
+ signals:
+ void widgetShown( QWidget* );
+ void widgetHidden( QWidget* );
+
+ public slots:
+ /**
+ * \param effectOnly If true K3bWidgetShowEffect will not call QWidget::show().
+ * This is only useful in case onw uses K3bWidgetShowEffect
+ * to reimplement QWidget::show(). In that case the caller
+ * has to take care of showing the widget.
+ */
+ void show( bool effectOnly = false );
+
+ /**
+ * \param effectOnly If true K3bWidgetShowEffect will not call QWidget::hide().
+ * This is only useful in case onw uses K3bWidgetShowEffect
+ * to reimplement QWidget::hide(). In that case the caller
+ * has to take care of hiding the widget by connecting to
+ * K3bWidgetShowEffect::widgetHidden()
+ */
+ void hide( bool effectOnly = false );
+
+ private:
+ void timerEvent( QTimerEvent* );
+
+ /**
+ * @short Gradually show widget by dissolving from background
+ */
+ void dissolveMask();
+
+ /**
+ * @short animation to slide the widget into view
+ */
+ void slideMask();
+
+ Effect m_effect;
+ QWidget* m_widget;
+
+ QBitmap m_mask;
+
+ int m_dissolveSize;
+ int m_dissolveDelta;
+
+ int m_offset;
+ int m_timerId;
+
+ // if true we show, otherwise we hide the widget
+ bool m_bShow;
+
+ bool m_deleteSelf;
+ bool m_bEffectOnly;
+};
+
+#endif
diff --git a/src/k3bwriterselectionwidget.cpp b/src/k3bwriterselectionwidget.cpp
new file mode 100644
index 0000000..29a11f9
--- /dev/null
+++ b/src/k3bwriterselectionwidget.cpp
@@ -0,0 +1,607 @@
+/*
+ *
+ * $Id: k3bwriterselectionwidget.cpp 690635 2007-07-21 16:47:29Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bwriterselectionwidget.h"
+#include "k3bapplication.h"
+#include "k3bmediacache.h"
+
+#include <k3bmediaselectioncombobox.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <kconfig.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <kinputdialog.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qtooltip.h>
+#include <qtoolbutton.h>
+#include <qwhatsthis.h>
+#include <qmap.h>
+#include <qptrvector.h>
+#include <qcursor.h>
+#include <qapplication.h>
+
+
+class K3bWriterSelectionWidget::MediaSelectionComboBox : public K3bMediaSelectionComboBox
+{
+public:
+ MediaSelectionComboBox( QWidget* parent )
+ : K3bMediaSelectionComboBox( parent ),
+ m_overrideDevice( 0 ) {
+ }
+
+ void setOverrideDevice( K3bDevice::Device* dev, const QString& s, const QString& t ) {
+ m_overrideDevice = dev;
+ m_overrideString = s;
+ m_overrideToolTip = t;
+ updateMedia();
+ }
+
+ K3bDevice::Device* overrideDevice() const {
+ return m_overrideDevice;
+ }
+
+ protected:
+ bool showMedium( const K3bMedium& m ) const {
+ return ( m.device() == m_overrideDevice ||
+ K3bMediaSelectionComboBox::showMedium( m ) );
+ }
+
+ QString mediumString( const K3bMedium& m ) const {
+ if( m.device() == m_overrideDevice )
+ return m_overrideString;
+ else
+ return K3bMediaSelectionComboBox::mediumString( m );
+ }
+
+ QString mediumToolTip( const K3bMedium& m ) const {
+ if( m.device() == m_overrideDevice )
+ return m_overrideToolTip;
+ else {
+ QString s = K3bMediaSelectionComboBox::mediumToolTip( m );
+ if( !m.diskInfo().empty() && !(wantedMediumState() & m.diskInfo().diskState()) )
+ s.append( "<p><i>" + i18n("Medium will be overwritten.") + "</i>" );
+ return s;
+ }
+ }
+
+private:
+ K3bDevice::Device* m_overrideDevice;
+ QString m_overrideString;
+ QString m_overrideToolTip;
+};
+
+
+class K3bWriterSelectionWidget::Private
+{
+public:
+ bool forceAutoSpeed;
+ bool haveIgnoreSpeed;
+ bool haveManualSpeed;
+
+ int supportedWritingApps;
+
+ int lastSetSpeed;
+
+ QMap<int, int> indexSpeedMap;
+ QMap<int, int> speedIndexMap;
+};
+
+
+K3bWriterSelectionWidget::K3bWriterSelectionWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ d = new Private;
+ d->forceAutoSpeed = false;
+ d->supportedWritingApps = K3b::CDRECORD|K3b::CDRDAO|K3b::GROWISOFS;
+ d->lastSetSpeed = -1;
+
+ QGroupBox* groupWriter = new QGroupBox( this );
+ groupWriter->setTitle( i18n( "Burn Medium" ) );
+ groupWriter->setColumnLayout(0, Qt::Vertical );
+ groupWriter->layout()->setSpacing( 0 );
+ groupWriter->layout()->setMargin( 0 );
+
+ QGridLayout* groupWriterLayout = new QGridLayout( groupWriter->layout() );
+ groupWriterLayout->setAlignment( Qt::AlignTop );
+ groupWriterLayout->setSpacing( KDialog::spacingHint() );
+ groupWriterLayout->setMargin( KDialog::marginHint() );
+
+ QLabel* labelSpeed = new QLabel( groupWriter, "TextLabel1" );
+ labelSpeed->setText( i18n( "Speed:" ) );
+
+ m_comboSpeed = new KComboBox( false, groupWriter, "m_comboSpeed" );
+ m_comboSpeed->setAutoMask( false );
+ m_comboSpeed->setDuplicatesEnabled( false );
+
+ m_comboMedium = new MediaSelectionComboBox( groupWriter );
+
+ m_writingAppLabel = new QLabel( i18n("Writing app:"), groupWriter );
+ m_comboWritingApp = new KComboBox( groupWriter );
+
+ groupWriterLayout->addWidget( m_comboMedium, 0, 0 );
+ groupWriterLayout->addWidget( labelSpeed, 0, 1 );
+ groupWriterLayout->addWidget( m_comboSpeed, 0, 2 );
+ groupWriterLayout->addWidget( m_writingAppLabel, 0, 3 );
+ groupWriterLayout->addWidget( m_comboWritingApp, 0, 4 );
+ groupWriterLayout->setColStretch( 0, 1 );
+
+
+ QGridLayout* mainLayout = new QGridLayout( this );
+ mainLayout->setAlignment( Qt::AlignTop );
+ mainLayout->setSpacing( KDialog::spacingHint() );
+ mainLayout->setMargin( 0 );
+
+ mainLayout->addWidget( groupWriter, 0, 0 );
+
+ // tab order
+ setTabOrder( m_comboMedium, m_comboSpeed );
+ setTabOrder( m_comboSpeed, m_comboWritingApp );
+
+ connect( m_comboMedium, SIGNAL(selectionChanged(K3bDevice::Device*)), this, SIGNAL(writerChanged()) );
+ connect( m_comboMedium, SIGNAL(selectionChanged(K3bDevice::Device*)),
+ this, SIGNAL(writerChanged(K3bDevice::Device*)) );
+ connect( m_comboMedium, SIGNAL(newMedia()), this, SIGNAL(newMedia()) );
+ connect( m_comboMedium, SIGNAL(newMedium(K3bDevice::Device*)), this, SIGNAL(newMedium(K3bDevice::Device*)) );
+ connect( m_comboMedium, SIGNAL(newMedium(K3bDevice::Device*)), this, SLOT(slotNewBurnMedium(K3bDevice::Device*)) );
+ connect( m_comboWritingApp, SIGNAL(activated(int)), this, SLOT(slotWritingAppSelected(int)) );
+ connect( this, SIGNAL(writerChanged()), SLOT(slotWriterChanged()) );
+ connect( m_comboSpeed, SIGNAL(activated(int)), this, SLOT(slotSpeedChanged(int)) );
+
+
+ QToolTip::add( m_comboMedium, i18n("The medium that will be used for burning") );
+ QToolTip::add( m_comboSpeed, i18n("The speed at which to burn the medium") );
+ QToolTip::add( m_comboWritingApp, i18n("The external application to actually burn the medium") );
+
+ QWhatsThis::add( m_comboMedium, i18n("<p>Select the medium that you want to use for burning."
+ "<p>In most cases there will only be one medium available which "
+ "does not leave much choice.") );
+ QWhatsThis::add( m_comboSpeed, i18n("<p>Select the speed with which you want to burn."
+ "<p><b>Auto</b><br>"
+ "This will choose the maximum writing speed possible with the used "
+ "medium. "
+ "This is the recommended selection for most media.</p>"
+ "<p><b>Ignore</b> (DVD only)<br>"
+ "This will leave the speed selection to the writer device. "
+ "Use this if K3b is unable to set the writing speed."
+ "<p>1x refers to 1385 KB/s for DVD and 175 KB/s for CD.</p>"
+ "<p><b>Caution:</b> Make sure your system is able to send the data "
+ "fast enough to prevent buffer underruns.") );
+ QWhatsThis::add( m_comboWritingApp, i18n("<p>K3b uses the command line tools cdrecord, growisofs, and cdrdao "
+ "to actually write a CD or DVD."
+ "<p>Normally K3b chooses the best "
+ "suited application for every task automatically but in some cases it "
+ "may be possible that one of the applications does not work as intended "
+ "with a certain writer. In this case one may select the "
+ "application manually.") );
+
+ clearSpeedCombo();
+
+ slotConfigChanged(k3bcore->config());
+ slotWriterChanged();
+}
+
+
+K3bWriterSelectionWidget::~K3bWriterSelectionWidget()
+{
+ delete d;
+}
+
+
+void K3bWriterSelectionWidget::setWantedMediumType( int type )
+{
+ m_comboMedium->setWantedMediumType( type );
+}
+
+
+void K3bWriterSelectionWidget::setWantedMediumState( int state )
+{
+ m_comboMedium->setWantedMediumState( state );
+}
+
+
+int K3bWriterSelectionWidget::wantedMediumType() const
+{
+ return m_comboMedium->wantedMediumType();
+}
+
+
+int K3bWriterSelectionWidget::wantedMediumState() const
+{
+ return m_comboMedium->wantedMediumState();
+}
+
+
+void K3bWriterSelectionWidget::slotConfigChanged( KConfigBase* c )
+{
+ KConfigGroup g( c, "General Options" );
+ if( g.readBoolEntry( "Manual writing app selection", false ) ) {
+ m_comboWritingApp->show();
+ m_writingAppLabel->show();
+ }
+ else {
+ m_comboWritingApp->hide();
+ m_writingAppLabel->hide();
+ }
+}
+
+
+void K3bWriterSelectionWidget::slotRefreshWriterSpeeds()
+{
+ if( writerDevice() ) {
+ QValueList<int> speeds = k3bappcore->mediaCache()->writingSpeeds( writerDevice() );
+
+ int lastSpeed = writerSpeed();
+
+ clearSpeedCombo();
+
+ m_comboSpeed->insertItem( i18n("Auto") );
+ if( k3bappcore->mediaCache()->diskInfo( writerDevice() ).isDvdMedia() ) {
+ m_comboSpeed->insertItem( i18n("Ignore") );
+ d->haveIgnoreSpeed = true;
+ }
+ else
+ d->haveIgnoreSpeed = false;
+
+ if( !d->forceAutoSpeed ) {
+ if( speeds.isEmpty() || writerDevice() == m_comboMedium->overrideDevice() ) {
+ //
+ // In case of the override device we do not know which medium will actually be used
+ // So this is the only case in which we need to use the device's max writing speed
+ //
+ // But we need to know if it will be a CD or DVD medium. Since the override device
+ // is only used for CD/DVD copy anyway we simply reply on the inserted medium's type.
+ //
+ int i = 1;
+ int speed = ( k3bappcore->mediaCache()->diskInfo( writerDevice() ).isDvdMedia() ? 1385 : 175 );
+ int max = writerDevice()->maxWriteSpeed();
+ while( i*speed <= max ) {
+ insertSpeedItem( i*speed );
+ // a little hack to handle the stupid 2.4x DVD speed
+ if( i == 2 && speed == 1385 )
+ insertSpeedItem( (int)(2.4*1385.0) );
+ i = ( i == 1 ? 2 : i+2 );
+ }
+
+ //
+ // Since we do not know the exact max writing speed if an override device is set (we can't becasue
+ // the writer always returns the speed relative to the inserted medium) we allow the user to specify
+ // the speed manually
+ //
+ m_comboSpeed->insertItem( i18n("More...") );
+ d->haveManualSpeed = true;
+ }
+ else {
+ for( QValueList<int>::iterator it = speeds.begin(); it != speeds.end(); ++it )
+ insertSpeedItem( *it );
+ }
+ }
+
+ // try to reload last set speed
+ if( d->lastSetSpeed == -1 )
+ setSpeed( lastSpeed );
+ else
+ setSpeed( d->lastSetSpeed );
+ }
+
+ m_comboSpeed->setEnabled( writerDevice() != 0 );
+}
+
+
+void K3bWriterSelectionWidget::clearSpeedCombo()
+{
+ m_comboSpeed->clear();
+ d->indexSpeedMap.clear();
+ d->speedIndexMap.clear();
+ d->haveManualSpeed = false;
+ d->haveIgnoreSpeed = false;
+}
+
+
+void K3bWriterSelectionWidget::insertSpeedItem( int speed )
+{
+ if( !d->speedIndexMap.contains( speed ) ) {
+ d->indexSpeedMap[m_comboSpeed->count()] = speed;
+ d->speedIndexMap[speed] = m_comboSpeed->count();
+
+ if( k3bappcore->mediaCache()->diskInfo( writerDevice() ).isDvdMedia() )
+ m_comboSpeed->insertItem( ( speed%1385 > 0
+ ? QString::number( (float)speed/1385.0, 'f', 1 ) // example: DVD+R(W): 2.4x
+ : QString::number( speed/1385 ) )
+ + "x" );
+ else
+ m_comboSpeed->insertItem( QString("%1x").arg(speed/175) );
+ }
+}
+
+
+void K3bWriterSelectionWidget::slotWritingAppSelected( int )
+{
+ emit writingAppChanged( selectedWritingApp() );
+}
+
+
+K3bDevice::Device* K3bWriterSelectionWidget::writerDevice() const
+{
+ return m_comboMedium->selectedDevice();
+}
+
+
+QValueList<K3bDevice::Device*> K3bWriterSelectionWidget::allDevices() const
+{
+ return m_comboMedium->allDevices();
+}
+
+
+void K3bWriterSelectionWidget::setWriterDevice( K3bDevice::Device* dev )
+{
+ m_comboMedium->setSelectedDevice( dev );
+}
+
+
+void K3bWriterSelectionWidget::setSpeed( int s )
+{
+ d->lastSetSpeed = -1;
+
+ if( d->haveIgnoreSpeed && s < 0 )
+ m_comboSpeed->setCurrentItem( 1 ); // Ignore
+ else if( d->speedIndexMap.contains( s ) )
+ m_comboSpeed->setCurrentItem( d->speedIndexMap[s] );
+ else {
+ m_comboSpeed->setCurrentItem( 0 ); // Auto
+ d->lastSetSpeed = s; // remember last set speed
+ }
+}
+
+
+void K3bWriterSelectionWidget::setWritingApp( int app )
+{
+ switch( app ) {
+ case K3b::CDRECORD:
+ m_comboWritingApp->setCurrentItem( "cdrecord" );
+ break;
+ case K3b::CDRDAO:
+ m_comboWritingApp->setCurrentItem( "cdrdao" );
+ break;
+ case K3b::DVDRECORD:
+ m_comboWritingApp->setCurrentItem( "dvdrecord" );
+ break;
+ case K3b::GROWISOFS:
+ m_comboWritingApp->setCurrentItem( "growisofs" );
+ break;
+ case K3b::DVD_RW_FORMAT:
+ m_comboWritingApp->setCurrentItem( "dvd+rw-format" );
+ break;
+ default:
+ m_comboWritingApp->setCurrentItem( 0 ); // Auto
+ break;
+ }
+}
+
+
+int K3bWriterSelectionWidget::writerSpeed() const
+{
+ if( m_comboSpeed->currentItem() == 0 )
+ return 0; // Auto
+ else if( d->haveIgnoreSpeed && m_comboSpeed->currentItem() == 1 )
+ return -1; // Ignore
+ else
+ return d->indexSpeedMap[m_comboSpeed->currentItem()];
+}
+
+
+int K3bWriterSelectionWidget::writingApp() const
+{
+ KConfigGroup g( k3bcore->config(), "General Options" );
+ if( g.readBoolEntry( "Manual writing app selection", false ) ) {
+ return selectedWritingApp();
+ }
+ else
+ return K3b::DEFAULT;
+}
+
+
+int K3bWriterSelectionWidget::selectedWritingApp() const
+{
+ return K3b::writingAppFromString( m_comboWritingApp->currentText() );
+}
+
+
+void K3bWriterSelectionWidget::slotSpeedChanged( int s )
+{
+ // the last item is the manual speed selection item
+ if( d->haveManualSpeed && s == m_comboSpeed->count() - 1 ) {
+ slotManualSpeed();
+ }
+ else {
+ d->lastSetSpeed = d->indexSpeedMap[s];
+
+ if( K3bDevice::Device* dev = writerDevice() )
+ dev->setCurrentWriteSpeed( writerSpeed() );
+ }
+}
+
+
+void K3bWriterSelectionWidget::slotWriterChanged()
+{
+ slotRefreshWriterSpeeds();
+ slotRefreshWritingApps();
+
+ // save last selected writer
+ if( K3bDevice::Device* dev = writerDevice() ) {
+ KConfigGroup g( k3bcore->config(), "General Options" );
+ g.writeEntry( "current_writer", dev->devicename() );
+ }
+}
+
+
+void K3bWriterSelectionWidget::setSupportedWritingApps( int i )
+{
+ int oldApp = writingApp();
+
+ d->supportedWritingApps = i;
+
+ slotRefreshWritingApps();
+
+ setWritingApp( oldApp );
+}
+
+
+void K3bWriterSelectionWidget::slotRefreshWritingApps()
+{
+ int i = 0;
+
+ // select the ones that make sense
+ if( k3bappcore->mediaCache()->diskInfo( writerDevice() ).isDvdMedia() )
+ i = K3b::GROWISOFS|K3b::DVD_RW_FORMAT|K3b::DVDRECORD;
+ else
+ i = K3b::CDRDAO|K3b::CDRECORD;
+
+ // now strip it down to the ones we support
+ i &= d->supportedWritingApps;
+
+ m_comboWritingApp->clear();
+ m_comboWritingApp->insertItem( i18n("Auto") );
+
+ if( i & K3b::CDRDAO )
+ m_comboWritingApp->insertItem( "cdrdao" );
+ if( i & K3b::CDRECORD )
+ m_comboWritingApp->insertItem( "cdrecord" );
+ if( i & K3b::DVDRECORD )
+ m_comboWritingApp->insertItem( "dvdrecord" );
+ if( i & K3b::GROWISOFS )
+ m_comboWritingApp->insertItem( "growisofs" );
+ if( i & K3b::DVD_RW_FORMAT )
+ m_comboWritingApp->insertItem( "dvd+rw-format" );
+
+ m_comboWritingApp->setEnabled( writerDevice() != 0 );
+}
+
+
+void K3bWriterSelectionWidget::loadConfig( KConfigBase* c )
+{
+ setWriterDevice( k3bcore->deviceManager()->findDevice( c->readEntry( "writer_device" ) ) );
+ setSpeed( c->readNumEntry( "writing_speed", 0 ) );
+ setWritingApp( K3b::writingAppFromString( c->readEntry( "writing_app" ) ) );
+}
+
+
+void K3bWriterSelectionWidget::saveConfig( KConfigBase* c )
+{
+ c->writeEntry( "writing_speed", writerSpeed() );
+ c->writeEntry( "writer_device", writerDevice() ? writerDevice()->devicename() : QString::null );
+ c->writeEntry( "writing_app", m_comboWritingApp->currentText() );
+}
+
+void K3bWriterSelectionWidget::loadDefaults()
+{
+ // ignore the writer
+ m_comboSpeed->setCurrentItem( 0 ); // Auto
+ setWritingApp( K3b::DEFAULT );
+}
+
+
+void K3bWriterSelectionWidget::setForceAutoSpeed( bool b )
+{
+ d->forceAutoSpeed = b;
+ slotRefreshWriterSpeeds();
+}
+
+
+void K3bWriterSelectionWidget::setOverrideDevice( K3bDevice::Device* dev, const QString& overrideString, const QString& tooltip )
+{
+ m_comboMedium->setOverrideDevice( dev, overrideString, tooltip );
+}
+
+
+void K3bWriterSelectionWidget::slotNewBurnMedium( K3bDevice::Device* dev )
+{
+ //
+ // Try to select a medium that is better suited than the current one
+ //
+ if( dev && dev != writerDevice() ) {
+ K3bMedium medium = k3bappcore->mediaCache()->medium( dev );
+
+ //
+ // Always prefer newly inserted media over the override device
+ //
+ if( writerDevice() == m_comboMedium->overrideDevice() ) {
+ setWriterDevice( dev );
+ }
+
+ //
+ // Prefer an empty medium over one that has to be erased
+ //
+ else if( wantedMediumState() & K3bDevice::STATE_EMPTY &&
+ !k3bappcore->mediaCache()->diskInfo( writerDevice() ).empty() &&
+ medium.diskInfo().empty() ) {
+ setWriterDevice( dev );
+ }
+ }
+}
+
+
+void K3bWriterSelectionWidget::slotManualSpeed()
+{
+ //
+ // We need to know if it will be a CD or DVD medium. Since the override device
+ // is only used for CD/DVD copy anyway we simply reply on the inserted medium's type.
+ //
+ int speedFactor = ( k3bappcore->mediaCache()->diskInfo( writerDevice() ).isDvdMedia() ? 1385 : 175 );
+
+ bool ok = true;
+ int newSpeed = KInputDialog::getInteger( i18n("Set writing speed manually"),
+ i18n("<p>K3b is not able to perfectly determine the maximum "
+ "writing speed of an optical writer. Writing speed is always "
+ "reported subject to the inserted medium."
+ "<p>Please enter the writing speed here and K3b will remember it "
+ "for future sessions (Example: 16x)."),
+ writerDevice()->maxWriteSpeed()/speedFactor,
+ 1,
+ 10000,
+ 1,
+ 10,
+ &ok,
+ this ) * speedFactor;
+ if( ok ) {
+ writerDevice()->setMaxWriteSpeed( QMAX( newSpeed, writerDevice()->maxWriteSpeed() ) );
+ slotRefreshWriterSpeeds();
+ setSpeed( newSpeed );
+ }
+ else {
+ if( d->lastSetSpeed == -1 )
+ m_comboSpeed->setCurrentItem( 0 ); // Auto
+ else
+ setSpeed( d->lastSetSpeed );
+ }
+}
+
+
+void K3bWriterSelectionWidget::setIgnoreDevice( K3bDevice::Device* dev )
+{
+ m_comboMedium->setIgnoreDevice( dev );
+}
+
+#include "k3bwriterselectionwidget.moc"
diff --git a/src/k3bwriterselectionwidget.h b/src/k3bwriterselectionwidget.h
new file mode 100644
index 0000000..8174637
--- /dev/null
+++ b/src/k3bwriterselectionwidget.h
@@ -0,0 +1,146 @@
+/*
+ *
+ * $Id: k3bwriterselectionwidget.h 690635 2007-07-21 16:47:29Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BWRITERSELECTIONWIDGET_H
+#define K3BWRITERSELECTIONWIDGET_H
+
+#include <qwidget.h>
+
+class KComboBox;
+class KConfigBase;
+class QLabel;
+class K3bMediaSelectionComboBox;
+namespace K3bDevice {
+ class Device;
+ class DeviceManager;
+}
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bWriterSelectionWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Creates a writerselectionwidget
+ */
+ K3bWriterSelectionWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bWriterSelectionWidget();
+
+ int writerSpeed() const;
+ K3bDevice::Device* writerDevice() const;
+
+ QValueList<K3bDevice::Device*> allDevices() const;
+
+ /**
+ * returns K3b::WritingApp
+ */
+ int writingApp() const;
+
+ int wantedMediumType() const;
+ int wantedMediumState() const;
+
+ void loadDefaults();
+ void loadConfig( KConfigBase* );
+ void saveConfig( KConfigBase* );
+
+ public slots:
+ void setWriterDevice( K3bDevice::Device* );
+ void setSpeed( int );
+ void setWritingApp( int );
+
+ /**
+ * K3b::WritingApp or'ed together
+ *
+ * Defaults to cdrecord and cdrdao for CD and growisofs for DVD
+ */
+ void setSupportedWritingApps( int );
+
+ /**
+ * A simple hack to disable the speed selection for DVD formatting
+ */
+ void setForceAutoSpeed( bool );
+
+ /**
+ * Set the wanted medium type. Defaults to writable CD.
+ *
+ * \param type a bitwise combination of the K3bDevice::MediaType enum
+ */
+ void setWantedMediumType( int type );
+
+ /**
+ * Set the wanted medium state. Defaults to empty media.
+ *
+ * \param state a bitwise combination of the K3bDevice::State enum
+ */
+ void setWantedMediumState( int state );
+
+ /**
+ * This is a hack to allow the copy dialogs to use the same device for reading
+ * and writing without having the user to choose the same medium.
+ *
+ * \param overrideString A string which will be shown in place of the medium string.
+ * For example: "Burn to the same device". Set it to 0 in order
+ * to disable the feature.
+ */
+ void setOverrideDevice( K3bDevice::Device* dev, const QString& overrideString = QString::null, const QString& tooltip = QString::null );
+
+ /**
+ * Compare K3bMediaSelectionComboBox::setIgnoreDevice
+ */
+ void setIgnoreDevice( K3bDevice::Device* dev );
+
+ signals:
+ void writerChanged();
+ void writerChanged( K3bDevice::Device* );
+ void writingAppChanged( int app );
+
+ /**
+ * \see K3bMediaSelectionComboBox
+ */
+ void newMedia();
+ void newMedium( K3bDevice::Device* dev );
+
+ private slots:
+ void slotRefreshWriterSpeeds();
+ void slotRefreshWritingApps();
+ void slotWritingAppSelected( int id );
+ void slotConfigChanged( KConfigBase* c );
+ void slotSpeedChanged( int index );
+ void slotWriterChanged();
+ void slotNewBurnMedium( K3bDevice::Device* dev );
+ void slotManualSpeed();
+
+ private:
+ void clearSpeedCombo();
+ void insertSpeedItem( int );
+ int selectedWritingApp() const;
+
+ class MediaSelectionComboBox;
+
+ KComboBox* m_comboSpeed;
+ MediaSelectionComboBox* m_comboMedium;
+ KComboBox* m_comboWritingApp;
+ QLabel* m_writingAppLabel;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/k3bwritingmodewidget.cpp b/src/k3bwritingmodewidget.cpp
new file mode 100644
index 0000000..a2bd696
--- /dev/null
+++ b/src/k3bwritingmodewidget.cpp
@@ -0,0 +1,247 @@
+/*
+ *
+ * $Id: k3bwritingmodewidget.cpp 621084 2007-01-08 09:17:21Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bwritingmodewidget.h"
+#include "k3bmediacache.h"
+#include "k3bapplication.h"
+
+#include <k3bglobals.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+static const QString s_autoHelp = i18n("Let K3b select the best-suited mode. This is the recommended selection.");
+static const QString s_daoHelp = i18n("<em>Disk At Once</em> or more properly <em>Session At Once</em>. "
+ "The laser is never turned off while writing the CD or DVD. "
+ "This is the preferred mode to write audio CDs since it allows "
+ "pregaps other than 2 seconds. Not all writers support DAO.<br>"
+ "DVD-R(W)s written in DAO provide the best DVD-Video compatibility.");
+static const QString s_taoHelp = i18n("<em>Track At Once</em> should be supported by every CD writer. "
+ "The laser will be turned off after every track.<br>"
+ "Most CD writers need this mode for writing multisession CDs.");
+// TODO: add something like: "No CD-TEXT writing in TAO mode."
+
+static const QString s_rawHelp = i18n("RAW writing mode. The error correction data is created by the "
+ "software instead of the writer device.<br>"
+ "Try this if your CD writer fails to write in DAO and TAO.");
+static const QString s_seqHelp = i18n("Incremental sequential is the default writing mode for DVD-R(W). "
+ "It allows multisession DVD-R(W)s. It only applies to DVD-R(W).");
+static const QString s_ovwHelp = i18n("Restricted Overwrite allows to use a DVD-RW just like a DVD-RAM "
+ "or a DVD+RW. The media may just be overwritten. It is not possible "
+ "to write multisession DVD-RWs in this mode but K3b uses growisofs "
+ "to grow an ISO9660 filesystem within the first session, thus allowing "
+ "new files to be added to an already burned disk.");
+
+
+class K3bWritingModeWidget::Private
+{
+public:
+ // modes set via setSupportedModes
+ int supportedModes;
+
+ // filtered modes
+ int selectedModes;
+
+ K3bDevice::Device* device;
+};
+
+
+K3bWritingModeWidget::K3bWritingModeWidget( int modes, QWidget* parent, const char* name )
+ : K3bIntMapComboBox( parent, name )
+{
+ init();
+ setSupportedModes( modes );
+}
+
+
+K3bWritingModeWidget::K3bWritingModeWidget( QWidget* parent, const char* name )
+ : K3bIntMapComboBox( parent, name )
+{
+ init();
+ setSupportedModes( K3b::DAO | K3b::TAO | K3b::RAW ); // default: support all CD-R(W) modes
+}
+
+
+K3bWritingModeWidget::~K3bWritingModeWidget()
+{
+ delete d;
+}
+
+
+void K3bWritingModeWidget::init()
+{
+ d = new Private();
+ d->device = 0;
+
+ connect( this, SIGNAL(valueChanged(int)), this, SIGNAL(writingModeChanged(int)) );
+
+ QToolTip::add( this, i18n("Select the writing mode to use") );
+
+ initWhatsThisHelp();
+}
+
+
+void K3bWritingModeWidget::initWhatsThisHelp()
+{
+ addGlobalWhatsThisText( "<p><b>" + i18n("Writing mode") + "</b></p>",
+ i18n("Be aware that the writing mode is ignored when writing DVD+R(W) since "
+ "there is only one way to write them.")
+ + "<p><i>"
+ + i18n("The selection of writing modes depends on the inserted burning medium.")
+ + "</i>" );
+}
+
+
+int K3bWritingModeWidget::writingMode() const
+{
+ return selectedValue();
+}
+
+
+void K3bWritingModeWidget::setWritingMode( int m )
+{
+ if( m & d->selectedModes ) {
+ setSelectedValue( m );
+ }
+ else {
+ setCurrentItem( 0 ); // WRITING_MODE_AUTO
+ }
+}
+
+
+void K3bWritingModeWidget::setSupportedModes( int m )
+{
+ d->supportedModes = m|K3b::WRITING_MODE_AUTO; // we always support the Auto mode
+ updateModes();
+}
+
+
+void K3bWritingModeWidget::setDevice( K3bDevice::Device* dev )
+{
+ d->device = dev;
+ updateModes();
+}
+
+
+void K3bWritingModeWidget::updateModes()
+{
+ // save current mode
+ int currentMode = writingMode();
+
+ clear();
+
+ if( d->device )
+ d->selectedModes = d->supportedModes & d->device->writingModes();
+ else
+ d->selectedModes = d->supportedModes;
+
+ insertItem( 0, i18n("Auto"), s_autoHelp );
+ if( d->selectedModes & K3b::DAO )
+ insertItem( K3b::DAO, i18n("DAO"), s_daoHelp );
+ if( d->selectedModes & K3b::TAO )
+ insertItem( K3b::TAO, i18n("TAO"), s_taoHelp );
+ if( d->selectedModes & K3b::RAW )
+ insertItem( K3b::RAW, i18n("RAW"), s_rawHelp );
+ if( d->selectedModes & K3b::WRITING_MODE_RES_OVWR )
+ insertItem( K3b::WRITING_MODE_RES_OVWR, i18n("Restricted Overwrite"), s_ovwHelp );
+ if( d->selectedModes & K3b::WRITING_MODE_INCR_SEQ )
+ insertItem( K3b::WRITING_MODE_INCR_SEQ, i18n("Incremental"), s_seqHelp );
+
+ setWritingMode( currentMode );
+}
+
+
+void K3bWritingModeWidget::saveConfig( KConfigBase* c )
+{
+ switch( writingMode() ) {
+ case K3b::DAO:
+ c->writeEntry( "writing_mode", "dao" );
+ break;
+ case K3b::TAO:
+ c->writeEntry( "writing_mode", "tao" );
+ break;
+ case K3b::RAW:
+ c->writeEntry( "writing_mode", "raw" );
+ break;
+ case K3b::WRITING_MODE_INCR_SEQ:
+ c->writeEntry( "writing_mode", "incremental" );
+ break;
+ case K3b::WRITING_MODE_RES_OVWR:
+ c->writeEntry( "writing_mode", "overwrite" );
+ break;
+ default:
+ c->writeEntry( "writing_mode", "auto" );
+ break;
+ }
+}
+
+void K3bWritingModeWidget::loadConfig( KConfigBase* c )
+{
+ QString mode = c->readEntry( "writing_mode" );
+ if ( mode == "dao" )
+ setWritingMode( K3b::DAO );
+ else if( mode == "tao" )
+ setWritingMode( K3b::TAO );
+ else if( mode == "raw" )
+ setWritingMode( K3b::RAW );
+ else if( mode == "incremental" )
+ setWritingMode( K3b::WRITING_MODE_INCR_SEQ );
+ else if( mode == "overwrite" )
+ setWritingMode( K3b::WRITING_MODE_RES_OVWR );
+ else
+ setWritingMode( K3b::WRITING_MODE_AUTO );
+}
+
+
+void K3bWritingModeWidget::determineSupportedModesFromMedium( const K3bMedium& m )
+{
+ int modes = 0;
+
+ if( m.diskInfo().mediaType() & (K3bDevice::MEDIA_CD_R|K3bDevice::MEDIA_CD_RW) ) {
+ modes |= K3b::TAO;
+ if( m.device()->supportsWritingMode( K3bDevice::WRITINGMODE_SAO ) )
+ modes |= K3b::DAO;
+ if( m.device()->supportsWritingMode( K3bDevice::WRITINGMODE_RAW ) )
+ modes |= K3b::RAW;
+ }
+
+ if( m.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_MINUS_ALL ) {
+ modes |= K3b::DAO;
+ if( m.device()->featureCurrent( K3bDevice::FEATURE_INCREMENTAL_STREAMING_WRITABLE ) != 0 )
+ modes |= K3b::WRITING_MODE_INCR_SEQ;
+ }
+
+ if( m.diskInfo().mediaType() & (K3bDevice::MEDIA_DVD_RW|
+ K3bDevice::MEDIA_DVD_RW_SEQ|
+ K3bDevice::MEDIA_DVD_RW_OVWR) )
+ modes |= K3b::WRITING_MODE_RES_OVWR;
+
+ setSupportedModes( modes );
+ setDevice( m.device() );
+}
+
+
+void K3bWritingModeWidget::determineSupportedModesFromMedium( K3bDevice::Device* dev )
+{
+ if( dev )
+ determineSupportedModesFromMedium( k3bappcore->mediaCache()->medium( dev ) );
+ else
+ determineSupportedModesFromMedium( K3bMedium() ); // no medium
+}
+
+#include "k3bwritingmodewidget.moc"
diff --git a/src/k3bwritingmodewidget.h b/src/k3bwritingmodewidget.h
new file mode 100644
index 0000000..f399f14
--- /dev/null
+++ b/src/k3bwritingmodewidget.h
@@ -0,0 +1,91 @@
+/*
+ *
+ * $Id: k3bwritingmodewidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_WRITING_MODE_WIDGET_H_
+#define _K3B_WRITING_MODE_WIDGET_H_
+
+#include <k3bintmapcombobox.h>
+
+#include <k3bmedium.h>
+
+class KConfigBase;
+
+
+/**
+ * Allows selection of K3b::WritingMode
+ */
+class K3bWritingModeWidget : public K3bIntMapComboBox
+{
+ Q_OBJECT
+
+ public:
+ K3bWritingModeWidget( QWidget* parent = 0, const char* name = 0 );
+ K3bWritingModeWidget( int modes, QWidget* parent = 0, const char* name = 0 );
+ ~K3bWritingModeWidget();
+
+ int writingMode() const;
+
+ void saveConfig( KConfigBase* );
+ /**
+ * This will not emit the writingModeChanged signal
+ */
+ void loadConfig( KConfigBase* );
+
+ public slots:
+ /**
+ * This will not emit the writingModeChanged signal
+ */
+ void setWritingMode( int m );
+ void setSupportedModes( int );
+
+ /**
+ * If the device is set the supported writing modes
+ * will be filtered by the ones supported by the drive.
+ */
+ void setDevice( K3bDevice::Device* );
+
+ /**
+ * Set the writing modes which make sense with the provided medium.
+ * This will also reset the device from the medium.
+ *
+ * \param m The medium. May even be non-writable or no medium at all
+ * in which case only the auto mode will be selected.
+ *
+ * \sa setDevice
+ */
+ void determineSupportedModesFromMedium( const K3bMedium& m );
+
+ /**
+ * Convinience method. Does the same as the one above.
+ *
+ * \param dev The device which contains the medium. May even be 0 in
+ * which case only the auto mode will be selected.
+ */
+ void determineSupportedModesFromMedium( K3bDevice::Device* dev );
+
+ signals:
+ void writingModeChanged( int );
+
+ private:
+ void init();
+ void updateModes();
+ void initWhatsThisHelp();
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/konqi/Makefile.am b/src/konqi/Makefile.am
new file mode 100644
index 0000000..e13f9d2
--- /dev/null
+++ b/src/konqi/Makefile.am
@@ -0,0 +1,16 @@
+k3bservice_DATA = k3b_create_data_cd.desktop \
+ k3b_create_data_dvd.desktop \
+ k3b_create_audio_cd.desktop \
+ k3b_create_video_cd.desktop \
+ k3b_write_bin_image.desktop \
+ k3b_write_iso_image.desktop
+
+konqservice_DATA = k3b_audiocd_rip.desktop \
+ k3b_videodvd_rip.desktop \
+ k3b_cd_copy.desktop \
+ k3b_dvd_copy.desktop \
+ k3b_handle_empty_dvd.desktop \
+ k3b_handle_empty_cd.desktop
+
+k3bservicedir = $(kde_datadir)/k3b/servicemenus
+konqservicedir = $(kde_datadir)/konqueror/servicemenus
diff --git a/src/konqi/k3b_audiocd_rip.desktop b/src/konqi/k3b_audiocd_rip.desktop
new file mode 100644
index 0000000..c118cd4
--- /dev/null
+++ b/src/konqi/k3b_audiocd_rip.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+ServiceTypes=media/audiocd,media/mixedcd
+Actions=K3bRip;
+X-KDE-Priority=TopLevel
+
+[Desktop Action K3bRip]
+Name=Extract Digital Audio with K3b
+Name[af]=Onttrek digitale oudio m.b.v. K3b
+Name[ar]= استعمل K3b لاستخراج الصوتي الرقمي.
+Name[bg]=Извличане на цифров звук с K3b
+Name[br]=Eztennañ klevet niverel gant K3b
+Name[ca]=Extreu àudio digital amb el K3b
+Name[cs]=Extrahovat digitální zvuk pomocí K3b
+Name[da]=Rip digitallyd med K3b
+Name[de]=Digital-Audio mit K3b auslesen
+Name[el]=Εξαγωγή ψηφιακού ήχου με το K3b
+Name[eo]=Ekstraktu ciferecan sonon per K3b
+Name[es]=Extraer audio digital con K3b
+Name[et]=Ekstrakti digitaalne audio K3b abil
+Name[fa]=استخراج صوتی رقمی با K3b
+Name[fi]=Pura sisältö digitaalisesti K3b:llä
+Name[fr]=Extraction Audio avec K3b
+Name[gl]=Extrair Áudio Dixital con K3b
+Name[hu]=Digitális hanganyag kimásolása a K3b-vel
+Name[is]=Afrita stafrænt hljóð með K3b
+Name[it]=Estrai audio digitale con K3b
+Name[ja]=K3b でデジタルオーディオを吸い出し
+Name[km]=ស្រង់​ចេញ​អូឌីយ៉ូ​ឌីជីថល​ដោយ​ប្រើ K3b
+Name[lt]=Nurašyti skaitmeninį audio su K3b
+Name[ms]=Ekstrak Audio Digital dengan K3b
+Name[nds]=Digitaal Audiodaten mit K3b ruttrecken
+Name[nl]=Digitale audio rippen met K3b
+Name[nn]=Hent ut digitallyd med K3b
+Name[pa]=K3b ਨਾਲ ਡਿਜ਼ੀਟਲ ਆਡੀਓ ਖੋਲ੍ਹੋ
+Name[pl]=Zgraj utwory za pomocą K3b
+Name[pt]=Extrair o Áudio Digital com o K3b
+Name[pt_BR]=Extrair Áudio Digital com o K3b
+Name[sk]=Extrahovať digitálne audio pomocou K3b
+Name[sr]=Издвој дигитални звук помоћу K3b-а
+Name[sr@Latn]=Izdvoj digitalni zvuk pomoću K3b-a
+Name[sv]=Lagra digitalljud med K3b
+Name[tr]=K3b ile Sayısal Ses Aktar
+Name[uk]=Витягування цифрового аудіо за допомогою K3b
+Name[uz]=K3b yordamida qoʻshiqlarni audio-faylga aylantirish
+Name[uz@cyrillic]=K3b ёрдамида қўшиқларни аудио-файлга айлантириш
+Name[zh_CN]=用 K3b 提取数字音频
+Name[zh_TW]=使用 K3b 以數位方式提取音樂
+Exec=k3b --cddarip %u
+Icon=k3b
diff --git a/src/konqi/k3b_cd_copy.desktop b/src/konqi/k3b_cd_copy.desktop
new file mode 100644
index 0000000..51f0ab0
--- /dev/null
+++ b/src/konqi/k3b_cd_copy.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+ServiceTypes=media/cdrom_unmounted,media/cdwriter_unmounted,media/audiocd
+Actions=K3bCDCopy;
+X-KDE-Priority=TopLevel
+
+[Desktop Action K3bCDCopy]
+Name=Copy CD with K3b
+Name[af]=Kopiëer CD m.b.v. K3b...
+Name[ar]= انقل القرص المدمج بواسطة K3b .
+Name[bg]=Копиране на CD с K3b
+Name[br]=Eilañ ur CD gant K3b
+Name[ca]=Copia CD amb el K3b
+Name[cs]=Kopírovat CD pomocí K3b
+Name[da]=Kopiér cd med K3b
+Name[de]=CD mit K3b kopieren
+Name[el]=Αντιγραφή CD με το K3b
+Name[eo]=Kopiu KD per K3b
+Name[es]=Copiar CD con K3b
+Name[et]=Kopeeri CD K3b abil
+Name[fa]=رونوشت دیسک فشرده با K3b
+Name[fi]=Kopioi cd K3b:llä
+Name[fr]=Copier le CD avec K3b
+Name[gl]=Copiar CD con K3b
+Name[hu]=CD-másolás a K3b-vel
+Name[is]=Afrita geisladisk með K3b
+Name[it]=Copia CD con K3b
+Name[ja]=K3b で CD をコピー
+Name[ka]=CD-ს ასლი K3b-ით
+Name[km]=ចម្លង​ស៊ីឌី​ដោយ​ប្រើ K3b
+Name[lt]=Kopijuoti CD su K3b
+Name[mk]=Копирајте CD со K3b
+Name[ms]=Salin CD dengan K3b
+Name[nds]=CD mit K3b koperen
+Name[nl]=CD kopiëren met K3b
+Name[nn]=Kopier CD med K3b
+Name[pa]=K3b ਨਾਲ CD ਨਕਲ
+Name[pl]=Skopiuj płytę CD za pomocą K3b
+Name[pt]=Copiar o CD com o K3b
+Name[pt_BR]=Copiar CD com o K3b
+Name[ru]=Записать компакт-диск, используя K3b...
+Name[sk]=Kopírovať CD pomocou K3b
+Name[sr]=Копирај CD помоћу K3b-а
+Name[sr@Latn]=Kopiraj CD pomoću K3b-a
+Name[sv]=Kopiera cd med K3b
+Name[tr]=K3b ile CD Kopyala
+Name[uk]=Копіювати КД за допомогою K3b
+Name[uz]=K3b yordamida CD'dan nusxa olish
+Name[uz@cyrillic]=K3b ёрдамида CD'дан нусха олиш
+Name[zh_CN]=用 K3b 复制 CD
+Name[zh_TW]=使用 K3b 複製 CD
+Exec=k3b --copycd %u
+Icon=k3b
diff --git a/src/konqi/k3b_create_audio_cd.desktop b/src/konqi/k3b_create_audio_cd.desktop
new file mode 100644
index 0000000..e4ecad9
--- /dev/null
+++ b/src/konqi/k3b_create_audio_cd.desktop
@@ -0,0 +1,62 @@
+[Desktop Entry]
+Actions=CreateK3bAudioProject;
+Encoding=UTF-8
+ServiceTypes=audio/x-mp3,audio/x-vorbis,application/x-ogg,audio/x-mp2,audio/x-mpegurl,audio/x-wav
+
+[Desktop Action CreateK3bAudioProject]
+Exec=k3b --audiocd %F
+Name=Create Audio CD with K3b...
+Name[af]=Skep oudio CD met K3b...
+Name[ar]= انشيء القرص المدمج السمعي بواسطة K3b ...
+Name[bg]=Създаване на аудио CD с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে অডিও সিডি তৈরি করো...
+Name[br]=Krouiñ ur CD klevet gant K3b ...
+Name[bs]=Napravio audio CD koristeći K3b...
+Name[ca]=Crea un CD d'àudio amb el K3b...
+Name[cs]=Vytvořit zvukové CD...
+Name[da]=Lav lyd-cd med K3b...
+Name[de]=Audio-CD mit K3b erstellen ...
+Name[el]=Δημιουργία CD ήχου με το K3b...
+Name[eo]=Kreu sonan KD per K3b...
+Name[es]=Crear CD de audio con K3b...
+Name[et]=Kirjuta audio-CD K3b abil...
+Name[fa]=ایجاد دیسک فشردۀ صوتی با K3b...
+Name[fi]=Luo musiikki-cd K3b:llä...
+Name[fr]=Créer un CD audio avec K3b...
+Name[gl]=Criar un CD de Áudio con K3b...
+Name[he]=צור תקליטור שמע בעזרת K3b...
+Name[hi]=के3बी के साथ ऑडियो सीडी बनाए...
+Name[hu]=Hang-CD létrehozása a K3b-vel...
+Name[is]=Búa til hljóðdisk með K3b...
+Name[it]=Crea CD audio con K3b...
+Name[ja]=K3b でオーディオ CD を作成...
+Name[ka]=K3b-ით Audio CD-ის ჩაწერა...
+Name[km]=បង្កើត​ស៊ីឌី​អូឌីយ៉ូ​ជាមួយ​នឹង K3b...
+Name[lt]=Kurti audio CD su K3b...
+Name[mk]=Креирајте аудио-CD со K3b...
+Name[ms]= Cipta Audio CD dengan K3b...
+Name[nb]=Lag lyd-CD med K3b . . .
+Name[nds]=Audio-CD mit K3b opstellen...
+Name[ne]=K3b सँग अडियो सीडी सिर्जना गर्नुहोस्...
+Name[nl]=Audio-cd aanmaken met K3b...
+Name[nn]=Lag lyd-CD med K3b …
+Name[pa]=K2b ਨਾਲ ਆਡੀਓ CD ਬਣਾਓ...
+Name[pl]=Stwórz płytę CD Audio za pomocą K3b...
+Name[pt]=Criar um CD de Áudio com o K3b...
+Name[pt_BR]=Criar CD de Áudio com o K3b...
+Name[ru]=Записать аудио компакт-диск, используя K3b...
+Name[sk]=Vytvoriť audio CD pomocou K3b...
+Name[sl]=Ustvari avdio CD s K3b ...
+Name[sr]=Направи аудио CD помоћу K3b-а...
+Name[sr@Latn]=Napravi audio CD pomoću K3b-a...
+Name[sv]=Skapa ljud-cd med K3b...
+Name[ta]=ஒலிக் குறுந்தகட்டோடு K3bயை உருவாக்குக...
+Name[tg]=Сабт кардани аудио компакт-диск бо истифодаи K3b...
+Name[tr]=K3b ile Ses CD'si oluştur...
+Name[uk]=Створити аудіо-КД за допомогою K3b...
+Name[uz]=K3b yordamida audio CD yaratish
+Name[uz@cyrillic]=K3b ёрдамида аудио CD яратиш
+Name[xh]=Yenza i CD Yokuvakalayo nge K3b...
+Name[zh_CN]=用 K3b 创建音频 CD...
+Name[zh_TW]=使用 K3b 建立音樂 CD...
+Icon=k3b
diff --git a/src/konqi/k3b_create_data_cd.desktop b/src/konqi/k3b_create_data_cd.desktop
new file mode 100644
index 0000000..af6bcaa
--- /dev/null
+++ b/src/konqi/k3b_create_data_cd.desktop
@@ -0,0 +1,63 @@
+[Desktop Entry]
+Actions=CreateK3bDataCDProject;
+Encoding=UTF-8
+ServiceTypes=all/allfiles,inode/directory
+ExcludeServiceTypes=application/x-iso,kdedevice/*
+
+[Desktop Action CreateK3bDataCDProject]
+Exec=k3b --datacd %F
+Name=Create Data CD with K3b...
+Name[af]=Skep data CD met K3b...
+Name[ar]= انشيء القرص المدمج لحفظ البيانات (Data) بواسطة K3b ...
+Name[bg]=Създаване на CD с данни с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে ডেটা-সিডি তৈরি করো...
+Name[br]=Krouiñ ur CD roadoù gant K3b ...
+Name[bs]=Napravi podatkovni CD koristeći K3b...
+Name[ca]=Crea un CD de dades amb el K3b...
+Name[cs]=Vytvořit datové CD...
+Name[da]=Lav data-cd med K3b...
+Name[de]=Daten-CD mit K3b erstellen ...
+Name[el]=Δημιουργία CD δεδομένων με το K3b...
+Name[eo]=Kreu datuman KD per K3b...
+Name[es]=Crear CD de datos con K3b...
+Name[et]=Kirjuta andme-CD K3b abil...
+Name[fa]=ایجاد دیسک فشردۀ داده با K3b...
+Name[fi]=Luo data-cd K3b:llä...
+Name[fr]=Créer un CD de données avec K3b...
+Name[gl]=Criar un CD de Dados con K3b...
+Name[he]=צור תקליטורי מידע CD בעזרת K3b...
+Name[hi]=के3बी के साथ डाटा सीडी बनाए...
+Name[hu]=Adat-CD létrehozása a K3b-vel...
+Name[is]=Búa til gagnadisk með K3b...
+Name[it]=Crea CD dati con K3b...
+Name[ja]=K3b でデータ CD を作成...
+Name[ka]=K3b-ით მონაცემთა CD-ის ჩაწერა...
+Name[km]=បង្កើត​ស៊ីឌី​ទិន្ន័យ​ជាមួយនឹង K3b...
+Name[lt]=Kurti duomenų CD su K3b...
+Name[mk]=Креирајте податочно CD со K3b...
+Name[ms]= Cipta CD Data dengan K3b...
+Name[nb]=Lag data-CD med K3b . . .
+Name[nds]=Daten-CD mit K3b opstellen...
+Name[ne]=K3b...
+Name[nl]=Gegevens-cd aanmaken met K3b...
+Name[nn]=Lag data-CD med K3b …
+Name[pa]=K2b ਨਾਲ ਡਾਟਾ CD ਬਣਾਓ...
+Name[pl]=Stwórz płytę CD z danymi za pomocą K3b...
+Name[pt]=Criar um CD de Dados com o K3b...
+Name[pt_BR]=Criar CD de Dados com o K3b...
+Name[ru]=Записать компакт-диск с данными, используя K3b...
+Name[sk]=Vytvoriť dátové CD pomocou K3b...
+Name[sl]=Ustvari podatkovni CD s K3b ...
+Name[sr]=Направи CD са подацима помоћу K3b-а...
+Name[sr@Latn]=Napravi CD sa podacima pomoću K3b-a...
+Name[sv]=Skapa data-cd med K3b...
+Name[ta]=தகவல் குறுந்தகட்டோடு K3b ஐ உருவாக்குக...
+Name[tg]=Сабт кардани CD бо маълумотҳо,бо истифодабарии K3b...
+Name[tr]=K3b ile Veri CD'si oluştur...
+Name[uk]=Створити КД з даними за допомогою K3b...
+Name[uz]=K3b yordamida maʼlumot CD yaratish
+Name[uz@cyrillic]=K3b ёрдамида маълумот CD яратиш
+Name[xh]=Yenza i CD yolwazi nge K3b...
+Name[zh_CN]=用 K3b 创建数据 CD...
+Name[zh_TW]=使用 K3b 建立資料 CD...
+Icon=k3b
diff --git a/src/konqi/k3b_create_data_dvd.desktop b/src/konqi/k3b_create_data_dvd.desktop
new file mode 100644
index 0000000..d03e5b5
--- /dev/null
+++ b/src/konqi/k3b_create_data_dvd.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Actions=CreateK3bDataDVDProject
+Encoding=UTF-8
+ServiceTypes=all/allfiles,inode/directory
+ExcludeServiceTypes=application/x-iso
+
+[Desktop Action CreateK3bDataDVDProject]
+Exec=k3b --datadvd %F
+Name=Create Data DVD with K3b...
+Name[af]=Skep 'n Data DVD m.b.v. K3b...
+Name[ar]= انشيء القرص المرئي الرقمي (DVD) لحفظ البيانات (Data) بواسطة K3b ...
+Name[bg]=Създаване на DVD с данни с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে ডেটা-ডিভিডি তৈরি করো...
+Name[br]=Krouiñ un DVD roadoù gant K3b ...
+Name[ca]=Crea un DVD de dades amb el K3b...
+Name[cs]=Vytvořit datové DVD...
+Name[da]=Lav data-cd med K3b...
+Name[de]=Daten-DVD mit K3b erstellen ...
+Name[el]=Δημιουργία DVD δεδομένων με το K3b...
+Name[eo]=Kreu datuman DVD per K3b...
+Name[es]=Crear DVD de datos con K3b...
+Name[et]=Kirjuta andme-DVD K3b abil...
+Name[fa]=ایجاد دی وی دی داده با K3b...
+Name[fi]=Luo data-dvd K3b:llä...
+Name[fr]=Créer un DVD de données avec K3b...
+Name[gl]=Criar un DVD de Dados con K3b...
+Name[he]=צור תקליטורי מידע DVD בעזרת K3b...
+Name[hu]=Adat-DVD létrehozása a K3b-vel...
+Name[is]=Búa til DVD gagnadisk með K3b...
+Name[it]=Crea DVD dati con K3b...
+Name[ja]=K3b でデータ DVD を作成...
+Name[ka]=K3b-ით მონაცემთა DVD-ის ჩაწერა...
+Name[km]=បង្កើត​ឌីវីឌី​ទិន្នន័យ​ដោយ​ប្រើ K3b...
+Name[lt]=Kurti duomenų DVD su K3b...
+Name[mk]=Креирајте податочно DVD со K3b...
+Name[ms]=Cipta DVD Data dengan K3b...
+Name[nb]=Lag data-DVD med K3b . . .
+Name[nds]=Daten-DVD mit K3b opstellen...
+Name[nl]=Gegevens-dvd aanmaken met K3b...
+Name[nn]=Lag data-DVD med K3b …
+Name[pa]=K3b ਨਾਲ ਡਾਟਾ DVD ਬਣਾਓ...
+Name[pl]=Stwórz płytę DVD z danymi za pomocą K3b...
+Name[pt]=Criar um DVD de Dados com o K3b...
+Name[pt_BR]=Criar DVD de Dados com o K3b...
+Name[ru]=Записать DVD с данными, используя K3b...
+Name[sk]=Vytvoriť dátové DVD pomocou K3b...
+Name[sr]=Направи DVD са подацима помоћу K3b-а...
+Name[sr@Latn]=Napravi DVD sa podacima pomoću K3b-a...
+Name[sv]=Skapa data-dvd med K3b...
+Name[tg]=Сабт кардани Маълумотҳои CD бо истифодабарии K3b...
+Name[tr]=K3b ile Veri DVD'si oluştur...
+Name[uk]=Створити DVD з даними у K3b...
+Name[uz]=K3b yordamida maʼlumot DVD yaratish
+Name[uz@cyrillic]=K3b ёрдамида маълумот DVD яратиш
+Name[zh_CN]=用 K3b 创建数据 DVD...
+Name[zh_TW]=使用 K3b 建立資料 DVD...
+Icon=k3b
diff --git a/src/konqi/k3b_create_video_cd.desktop b/src/konqi/k3b_create_video_cd.desktop
new file mode 100644
index 0000000..bb5ca3a
--- /dev/null
+++ b/src/konqi/k3b_create_video_cd.desktop
@@ -0,0 +1,61 @@
+[Desktop Entry]
+Actions=CreateK3bVcdProject;
+Encoding=UTF-8
+ServiceTypes=video/mpeg
+
+[Desktop Action CreateK3bVcdProject]
+Exec=k3b --videocd %F
+Name=Create Video CD with K3b...
+Name[af]=Skep video CD met K3b...
+Name[ar]= انشيء القرص المدمج المرئي (CD) بواسطة K3b .
+Name[bg]=Създаване на видео CD с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে ভিডিও সিডি তৈরি করো...
+Name[br]=Krouiñ ur CD video gant K3b ...
+Name[bs]=Napravi video CD koristeći K3b...
+Name[ca]=Crea un CD de vídeo amb el K3b...
+Name[cs]=Vytvořit video CD...
+Name[da]=Lav video-cd med K3b...
+Name[de]=Video-CD mit K3b erstellen ...
+Name[el]=Δημιουργία Video CD με το K3b...
+Name[eo]=Kreu videan KD per K3b...
+Name[es]=Crear CD de vídeo con K3b...
+Name[et]=Kirjuta video-CD K3b abil...
+Name[fa]=ایجاد دیسک فشردۀ ویدیویی با K3b...
+Name[fi]=Luo videocd K3b:llä...
+Name[fr]=Créer un CD vidéo avec K3b...
+Name[gl]=Criar un Video CD con K3b...
+Name[he]=צור תקליטורי וידאו VCD בעזרת K3b...
+Name[hi]=के3बी के साथ वीडियो सीडी बनाए...
+Name[hu]=Video CD létrehozása a K3b-vel...
+Name[is]=Búa til vídeódisk með K3b...
+Name[it]=Crea Video CD con K3b...
+Name[ja]=K3b でビデオ CD を作成...
+Name[ka]=K3b-ით Video CD-ის ჩაწერა...
+Name[km]=បង្កើត​ស៊ីឌី​វីដេអូ​ជាមួយ​នឹង K3b...
+Name[lt]=Kurti video CD su K3b...
+Name[mk]=Креирајте видео-CD со K3b...
+Name[ms]= Cipta CD Video dengan K3b...
+Name[nb]=Lag video-CD med K3b . . .
+Name[nds]=Video-CD mit K3b opstellen...
+Name[ne]=K3b सँग भिडियो सीडी सिर्जना गर्नुहोस्...
+Name[nl]=Video-cd aanmaken K3b...
+Name[nn]=Lag film-CD med K3b …
+Name[pa]=K2b ਨਾਲ ਵੀਡਿਓ CD ਬਣਾਓ...
+Name[pl]=Stwórz płytę Video CD za pomocą K3b...
+Name[pt]=Criar um CD de Vídeo com o K3b...
+Name[pt_BR]=Criar CD de Vídeo com o K3b...
+Name[ru]=Записать видео компакт-диск, используя K3b...
+Name[sk]=Vytvoriť video CD pomocou K3b...
+Name[sl]=Ustvari video CD s K3b ...
+Name[sr]=Направи видео CD помоћу K3b-а...
+Name[sr@Latn]=Napravi video CD pomoću K3b-a...
+Name[sv]=Skapa video-cd med K3b...
+Name[ta]=ஒளிக் குறுந்தகட்டோடு K3bஐ உருவாக்குக...
+Name[tg]=Сабт кардани видео компакт-диск бо истифодаи K3b...
+Name[tr]=K3b ile Görüntü CD'si oluştur...
+Name[uk]=Створити відео-КД за допомогою K3b...
+Name[uz]=K3b yordamida video CD yaratish
+Name[uz@cyrillic]=K3b ёрдамида видео CD яратиш
+Name[zh_CN]=用 K3b 创建视频 CD...
+Name[zh_TW]=使用 K3b 建立 VCD...
+Icon=k3b
diff --git a/src/konqi/k3b_dvd_copy.desktop b/src/konqi/k3b_dvd_copy.desktop
new file mode 100644
index 0000000..88ce0bd
--- /dev/null
+++ b/src/konqi/k3b_dvd_copy.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+ServiceTypes=media/dvdrom_unmounted,media/dvdwriter_unmounted,media/dvdvideo
+Actions=K3bDVDCopy;
+X-KDE-Priority=TopLevel
+
+[Desktop Action K3bDVDCopy]
+Name=Copy DVD with K3b
+Name[af]=Kopiëer DVD m.b.v. K3b
+Name[ar]= انسخ القرص الرقمي المرئي (DVD) بواسطة K3b .
+Name[bg]=Копиране на DVD с K3b
+Name[br]=Eilañ un DVD gant K3b
+Name[ca]=Copia un DVD amb el K3b
+Name[cs]=Kopírovat DVD pomocí K3b
+Name[da]=Kopiér dvd med K3b
+Name[de]=DVD mit K3b kopieren
+Name[el]=Αντιγραφή DVD με το K3b
+Name[eo]=Kopiu DVD per K3b
+Name[es]=Copiar DVD con K3b
+Name[et]=Kopeeri DVD K3b abil
+Name[fa]=رونوشت دی وی دی با K3b
+Name[fi]=Kopioi dvd K3b:llä
+Name[fr]=Copier le DVD avec K3b
+Name[gl]=Copiar DVD con K3b
+Name[hu]=DVD-másolás a K3b-vel
+Name[is]=Afrita DVD með K3b
+Name[it]=Copia DVD con K3b
+Name[ja]=K3b で DVD をコピー...
+Name[ka]=DVD-ს ასლი K3b-ით
+Name[km]=ចម្លង​ឌីវីឌី​ដោយ​ប្រើ K3b
+Name[lt]=Kopijuoti DVD su K3b
+Name[mk]=Копирајте DVD со K3b...
+Name[ms]=Salin DVD dengan K3b
+Name[nds]=DVD mit K3b koperen
+Name[nl]=DVD kopiëren met K3b
+Name[nn]=Kopier DVD med K3b
+Name[pa]=K3b ਨਾਲ DVD ਨਕਲ
+Name[pl]=Skopiuj DVD za pomocą K3b
+Name[pt]=Copiar o DVD com o K3b
+Name[pt_BR]=Copiar DVD com o K3b
+Name[ru]=Копировать DVD, используя K3b...
+Name[sk]=Vytvoriť DVD pomocou K3b
+Name[sr]=Копирај DVD помоћу K3b-а
+Name[sr@Latn]=Kopiraj DVD pomoću K3b-a
+Name[sv]=Kopiera dvd med K3b
+Name[tr]=K3b ile Veri DVD'si Kopyala
+Name[uk]=Копіювати DVD за допомогою K3b
+Name[uz]=K3b yordamida DVD'dan nusxa olish
+Name[uz@cyrillic]=K3b ёрдамида DVD'дан нусха олиш
+Name[zh_CN]=用 K3b 复制 DVD
+Name[zh_TW]=使用 K3b 複製 DVD
+Exec=k3b --copydvd %u
+Icon=k3b
diff --git a/src/konqi/k3b_handle_empty_cd.desktop b/src/konqi/k3b_handle_empty_cd.desktop
new file mode 100644
index 0000000..33287bd
--- /dev/null
+++ b/src/konqi/k3b_handle_empty_cd.desktop
@@ -0,0 +1,120 @@
+[Desktop Entry]
+ServiceTypes=media/blankcd
+Actions=K3bDataProject;K3bAudioCDProject;
+X-KDE-Priority=TopLevel
+
+[Desktop Action K3bDataProject]
+Exec=k3b --device %u --datacd
+Name=Create Data CD with K3b...
+Name[af]=Skep data CD met K3b...
+Name[ar]= انشيء القرص المدمج لحفظ البيانات (Data) بواسطة K3b ...
+Name[bg]=Създаване на CD с данни с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে ডেটা-সিডি তৈরি করো...
+Name[br]=Krouiñ ur CD roadoù gant K3b ...
+Name[bs]=Napravi podatkovni CD koristeći K3b...
+Name[ca]=Crea un CD de dades amb el K3b...
+Name[cs]=Vytvořit datové CD...
+Name[da]=Lav data-cd med K3b...
+Name[de]=Daten-CD mit K3b erstellen ...
+Name[el]=Δημιουργία CD δεδομένων με το K3b...
+Name[eo]=Kreu datuman KD per K3b...
+Name[es]=Crear CD de datos con K3b...
+Name[et]=Kirjuta andme-CD K3b abil...
+Name[fa]=ایجاد دیسک فشردۀ داده با K3b...
+Name[fi]=Luo data-cd K3b:llä...
+Name[fr]=Créer un CD de données avec K3b...
+Name[gl]=Criar un CD de Dados con K3b...
+Name[he]=צור תקליטורי מידע CD בעזרת K3b...
+Name[hi]=के3बी के साथ डाटा सीडी बनाए...
+Name[hu]=Adat-CD létrehozása a K3b-vel...
+Name[is]=Búa til gagnadisk með K3b...
+Name[it]=Crea CD dati con K3b...
+Name[ja]=K3b でデータ CD を作成...
+Name[ka]=K3b-ით მონაცემთა CD-ის ჩაწერა...
+Name[km]=បង្កើត​ស៊ីឌី​ទិន្ន័យ​ជាមួយនឹង K3b...
+Name[lt]=Kurti duomenų CD su K3b...
+Name[mk]=Креирајте податочно CD со K3b...
+Name[ms]= Cipta CD Data dengan K3b...
+Name[nb]=Lag data-CD med K3b . . .
+Name[nds]=Daten-CD mit K3b opstellen...
+Name[ne]=K3b...
+Name[nl]=Gegevens-cd aanmaken met K3b...
+Name[nn]=Lag data-CD med K3b …
+Name[pa]=K2b ਨਾਲ ਡਾਟਾ CD ਬਣਾਓ...
+Name[pl]=Stwórz płytę CD z danymi za pomocą K3b...
+Name[pt]=Criar um CD de Dados com o K3b...
+Name[pt_BR]=Criar CD de Dados com o K3b...
+Name[ru]=Записать компакт-диск с данными, используя K3b...
+Name[sk]=Vytvoriť dátové CD pomocou K3b...
+Name[sl]=Ustvari podatkovni CD s K3b ...
+Name[sr]=Направи CD са подацима помоћу K3b-а...
+Name[sr@Latn]=Napravi CD sa podacima pomoću K3b-a...
+Name[sv]=Skapa data-cd med K3b...
+Name[ta]=தகவல் குறுந்தகட்டோடு K3b ஐ உருவாக்குக...
+Name[tg]=Сабт кардани CD бо маълумотҳо,бо истифодабарии K3b...
+Name[tr]=K3b ile Veri CD'si oluştur...
+Name[uk]=Створити КД з даними за допомогою K3b...
+Name[uz]=K3b yordamida maʼlumot CD yaratish
+Name[uz@cyrillic]=K3b ёрдамида маълумот CD яратиш
+Name[xh]=Yenza i CD yolwazi nge K3b...
+Name[zh_CN]=用 K3b 创建数据 CD...
+Name[zh_TW]=使用 K3b 建立資料 CD...
+Icon=k3b
+
+[Desktop Action K3bAudioCDProject]
+Exec=k3b --device %u --audiocd
+Name=Create Audio CD with K3b...
+Name[af]=Skep oudio CD met K3b...
+Name[ar]= انشيء القرص المدمج السمعي بواسطة K3b ...
+Name[bg]=Създаване на аудио CD с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে অডিও সিডি তৈরি করো...
+Name[br]=Krouiñ ur CD klevet gant K3b ...
+Name[bs]=Napravio audio CD koristeći K3b...
+Name[ca]=Crea un CD d'àudio amb el K3b...
+Name[cs]=Vytvořit zvukové CD...
+Name[da]=Lav lyd-cd med K3b...
+Name[de]=Audio-CD mit K3b erstellen ...
+Name[el]=Δημιουργία CD ήχου με το K3b...
+Name[eo]=Kreu sonan KD per K3b...
+Name[es]=Crear CD de audio con K3b...
+Name[et]=Kirjuta audio-CD K3b abil...
+Name[fa]=ایجاد دیسک فشردۀ صوتی با K3b...
+Name[fi]=Luo musiikki-cd K3b:llä...
+Name[fr]=Créer un CD audio avec K3b...
+Name[gl]=Criar un CD de Áudio con K3b...
+Name[he]=צור תקליטור שמע בעזרת K3b...
+Name[hi]=के3बी के साथ ऑडियो सीडी बनाए...
+Name[hu]=Hang-CD létrehozása a K3b-vel...
+Name[is]=Búa til hljóðdisk með K3b...
+Name[it]=Crea CD audio con K3b...
+Name[ja]=K3b でオーディオ CD を作成...
+Name[ka]=K3b-ით Audio CD-ის ჩაწერა...
+Name[km]=បង្កើត​ស៊ីឌី​អូឌីយ៉ូ​ជាមួយ​នឹង K3b...
+Name[lt]=Kurti audio CD su K3b...
+Name[mk]=Креирајте аудио-CD со K3b...
+Name[ms]= Cipta Audio CD dengan K3b...
+Name[nb]=Lag lyd-CD med K3b . . .
+Name[nds]=Audio-CD mit K3b opstellen...
+Name[ne]=K3b सँग अडियो सीडी सिर्जना गर्नुहोस्...
+Name[nl]=Audio-cd aanmaken met K3b...
+Name[nn]=Lag lyd-CD med K3b …
+Name[pa]=K2b ਨਾਲ ਆਡੀਓ CD ਬਣਾਓ...
+Name[pl]=Stwórz płytę CD Audio za pomocą K3b...
+Name[pt]=Criar um CD de Áudio com o K3b...
+Name[pt_BR]=Criar CD de Áudio com o K3b...
+Name[ru]=Записать аудио компакт-диск, используя K3b...
+Name[sk]=Vytvoriť audio CD pomocou K3b...
+Name[sl]=Ustvari avdio CD s K3b ...
+Name[sr]=Направи аудио CD помоћу K3b-а...
+Name[sr@Latn]=Napravi audio CD pomoću K3b-a...
+Name[sv]=Skapa ljud-cd med K3b...
+Name[ta]=ஒலிக் குறுந்தகட்டோடு K3bயை உருவாக்குக...
+Name[tg]=Сабт кардани аудио компакт-диск бо истифодаи K3b...
+Name[tr]=K3b ile Ses CD'si oluştur...
+Name[uk]=Створити аудіо-КД за допомогою K3b...
+Name[uz]=K3b yordamida audio CD yaratish
+Name[uz@cyrillic]=K3b ёрдамида аудио CD яратиш
+Name[xh]=Yenza i CD Yokuvakalayo nge K3b...
+Name[zh_CN]=用 K3b 创建音频 CD...
+Name[zh_TW]=使用 K3b 建立音樂 CD...
+Icon=k3b
diff --git a/src/konqi/k3b_handle_empty_dvd.desktop b/src/konqi/k3b_handle_empty_dvd.desktop
new file mode 100644
index 0000000..a4e5de1
--- /dev/null
+++ b/src/konqi/k3b_handle_empty_dvd.desktop
@@ -0,0 +1,110 @@
+[Desktop Entry]
+ServiceTypes=media/blankdvd
+Actions=K3bDataProject;
+X-KDE-Priority=TopLevel
+
+[Desktop Action K3bDataProject]
+Exec=k3b --device %u --datadvd
+Name=Create Data CD with K3b...
+Name[af]=Skep data CD met K3b...
+Name[ar]= انشيء القرص المدمج لحفظ البيانات (Data) بواسطة K3b ...
+Name[bg]=Създаване на CD с данни с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে ডেটা-সিডি তৈরি করো...
+Name[br]=Krouiñ ur CD roadoù gant K3b ...
+Name[bs]=Napravi podatkovni CD koristeći K3b...
+Name[ca]=Crea un CD de dades amb el K3b...
+Name[cs]=Vytvořit datové CD...
+Name[da]=Lav data-cd med K3b...
+Name[de]=Daten-CD mit K3b erstellen ...
+Name[el]=Δημιουργία CD δεδομένων με το K3b...
+Name[eo]=Kreu datuman KD per K3b...
+Name[es]=Crear CD de datos con K3b...
+Name[et]=Kirjuta andme-CD K3b abil...
+Name[fa]=ایجاد دیسک فشردۀ داده با K3b...
+Name[fi]=Luo data-cd K3b:llä...
+Name[fr]=Créer un CD de données avec K3b...
+Name[gl]=Criar un CD de Dados con K3b...
+Name[he]=צור תקליטורי מידע CD בעזרת K3b...
+Name[hi]=के3बी के साथ डाटा सीडी बनाए...
+Name[hu]=Adat-CD létrehozása a K3b-vel...
+Name[is]=Búa til gagnadisk með K3b...
+Name[it]=Crea CD dati con K3b...
+Name[ja]=K3b でデータ CD を作成...
+Name[ka]=K3b-ით მონაცემთა CD-ის ჩაწერა...
+Name[km]=បង្កើត​ស៊ីឌី​ទិន្ន័យ​ជាមួយនឹង K3b...
+Name[lt]=Kurti duomenų CD su K3b...
+Name[mk]=Креирајте податочно CD со K3b...
+Name[ms]= Cipta CD Data dengan K3b...
+Name[nb]=Lag data-CD med K3b . . .
+Name[nds]=Daten-CD mit K3b opstellen...
+Name[ne]=K3b...
+Name[nl]=Gegevens-cd aanmaken met K3b...
+Name[nn]=Lag data-CD med K3b …
+Name[pa]=K2b ਨਾਲ ਡਾਟਾ CD ਬਣਾਓ...
+Name[pl]=Stwórz płytę CD z danymi za pomocą K3b...
+Name[pt]=Criar um CD de Dados com o K3b...
+Name[pt_BR]=Criar CD de Dados com o K3b...
+Name[ru]=Записать компакт-диск с данными, используя K3b...
+Name[sk]=Vytvoriť dátové CD pomocou K3b...
+Name[sl]=Ustvari podatkovni CD s K3b ...
+Name[sr]=Направи CD са подацима помоћу K3b-а...
+Name[sr@Latn]=Napravi CD sa podacima pomoću K3b-a...
+Name[sv]=Skapa data-cd med K3b...
+Name[ta]=தகவல் குறுந்தகட்டோடு K3b ஐ உருவாக்குக...
+Name[tg]=Сабт кардани CD бо маълумотҳо,бо истифодабарии K3b...
+Name[tr]=K3b ile Veri CD'si oluştur...
+Name[uk]=Створити КД з даними за допомогою K3b...
+Name[uz]=K3b yordamida maʼlumot CD yaratish
+Name[uz@cyrillic]=K3b ёрдамида маълумот CD яратиш
+Name[xh]=Yenza i CD yolwazi nge K3b...
+Name[zh_CN]=用 K3b 创建数据 CD...
+Name[zh_TW]=使用 K3b 建立資料 CD...
+Name=Create Data DVD with K3b...
+Name[af]=Skep 'n Data DVD m.b.v. K3b...
+Name[ar]= انشيء القرص المرئي الرقمي (DVD) لحفظ البيانات (Data) بواسطة K3b ...
+Name[bg]=Създаване на DVD с данни с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে ডেটা-ডিভিডি তৈরি করো...
+Name[br]=Krouiñ un DVD roadoù gant K3b ...
+Name[ca]=Crea un DVD de dades amb el K3b...
+Name[cs]=Vytvořit datové DVD...
+Name[da]=Lav data-cd med K3b...
+Name[de]=Daten-DVD mit K3b erstellen ...
+Name[el]=Δημιουργία DVD δεδομένων με το K3b...
+Name[eo]=Kreu datuman DVD per K3b...
+Name[es]=Crear DVD de datos con K3b...
+Name[et]=Kirjuta andme-DVD K3b abil...
+Name[fa]=ایجاد دی وی دی داده با K3b...
+Name[fi]=Luo data-dvd K3b:llä...
+Name[fr]=Créer un DVD de données avec K3b...
+Name[gl]=Criar un DVD de Dados con K3b...
+Name[he]=צור תקליטורי מידע DVD בעזרת K3b...
+Name[hu]=Adat-DVD létrehozása a K3b-vel...
+Name[is]=Búa til DVD gagnadisk með K3b...
+Name[it]=Crea DVD dati con K3b...
+Name[ja]=K3b でデータ DVD を作成...
+Name[ka]=K3b-ით მონაცემთა DVD-ის ჩაწერა...
+Name[km]=បង្កើត​ឌីវីឌី​ទិន្នន័យ​ដោយ​ប្រើ K3b...
+Name[lt]=Kurti duomenų DVD su K3b...
+Name[mk]=Креирајте податочно DVD со K3b...
+Name[ms]=Cipta DVD Data dengan K3b...
+Name[nb]=Lag data-DVD med K3b . . .
+Name[nds]=Daten-DVD mit K3b opstellen...
+Name[nl]=Gegevens-dvd aanmaken met K3b...
+Name[nn]=Lag data-DVD med K3b …
+Name[pa]=K3b ਨਾਲ ਡਾਟਾ DVD ਬਣਾਓ...
+Name[pl]=Stwórz płytę DVD z danymi za pomocą K3b...
+Name[pt]=Criar um DVD de Dados com o K3b...
+Name[pt_BR]=Criar DVD de Dados com o K3b...
+Name[ru]=Записать DVD с данными, используя K3b...
+Name[sk]=Vytvoriť dátové DVD pomocou K3b...
+Name[sr]=Направи DVD са подацима помоћу K3b-а...
+Name[sr@Latn]=Napravi DVD sa podacima pomoću K3b-a...
+Name[sv]=Skapa data-dvd med K3b...
+Name[tg]=Сабт кардани Маълумотҳои CD бо истифодабарии K3b...
+Name[tr]=K3b ile Veri DVD'si oluştur...
+Name[uk]=Створити DVD з даними у K3b...
+Name[uz]=K3b yordamida maʼlumot DVD yaratish
+Name[uz@cyrillic]=K3b ёрдамида маълумот DVD яратиш
+Name[zh_CN]=用 K3b 创建数据 DVD...
+Name[zh_TW]=使用 K3b 建立資料 DVD...
+Icon=k3b
diff --git a/src/konqi/k3b_videodvd_rip.desktop b/src/konqi/k3b_videodvd_rip.desktop
new file mode 100644
index 0000000..1c7a8d5
--- /dev/null
+++ b/src/konqi/k3b_videodvd_rip.desktop
@@ -0,0 +1,48 @@
+[Desktop Entry]
+ServiceTypes=media/dvdvideo
+Actions=K3bRip;
+X-KDE-Priority=TopLevel
+
+[Desktop Action K3bRip]
+Name=Rip Video DVD Titles with K3b
+Name[af]=Kopiëer Video DVD titels m.b.v. K3b
+Name[ar]= استخرج عناوين مرئيات من القرص المرئي الرقمي (DVD) بواسطة K3b
+Name[bg]=Извличане на DVD заглавия с K3b
+Name[ca]=Extreure pistes de DVD amb el K3b
+Name[cs]=Ripovat titulky video DVD pomocí K3b
+Name[da]=Rip dvd-titler med K3b
+Name[de]=DVD-Titel mit K3b auslesen
+Name[el]=Εξαγωγή τίτλων DVD με το K3b
+Name[eo]=Ekstraktu videan DVD titolojn per K3b
+Name[es]=Extraer títulos de DVD de vídeo con K3b
+Name[et]=Ripi video-DVD tiitlid K3b abil
+Name[fa]=تبدیل عناوین دی وی دی ویدئویی با K3b
+Name[fi]=Pura dvd K3b:llä
+Name[fr]=Extraire les titres du DVD avec K3b
+Name[gl]=Gravar título de Vídeo DVD con K3b
+Name[hu]=Video DVD-címek beolvasása a K3b-vel
+Name[is]=Afrita DVD titla með K3b
+Name[it]=Estrai titoli DVD video con K3b
+Name[ja]=K3b で DVD タイトルを吸い出し...
+Name[km]=ច្រៀក​ចំណង​ជើង​ឌីវីឌី​វីដេអូ​ដោយ​ប្រើ K3b
+Name[lt]=Nurašyti video DVD su K3b
+Name[ms]=Keluarkan Tajuk Video DVD dengan K3b
+Name[nds]=Video-DVD-Stücken mit K3b utlesen
+Name[nl]=Video-dvd-titels rippen met K3b
+Name[nn]=Hent ut film-DVD-titlar med K3b
+Name[pa]=K3b ਨਾਲ ਵੀਡਿਓ DVD ਟਾਇਟਲ ਰਿਪ
+Name[pl]=Zgraj filmy z płyty DVD Video za pomocą K3b
+Name[pt]=Extrair os Títulos do DVD de Vídeo com o K3b
+Name[pt_BR]=Ripar DVD de Vídeo com o K3b
+Name[sk]=Ripovať video DVD titulky pomocou K3b
+Name[sr]=Исчупај титлове са видео DVD-а помоћу K3b-а
+Name[sr@Latn]=Isčupaj titlove sa video DVD-a pomoću K3b-a
+Name[sv]=Lagra dvd-titlar med K3b
+Name[tr]=K3b ile Görüntü DVD'si Başlıklarını Aktar
+Name[uk]=Видерти заголовки з відео-DVD за допомогою K3b
+Name[uz]=K3b yordamida filmlarni video-faylga aylantirish
+Name[uz@cyrillic]=K3b ёрдамида филмларни видео-файлга айлантириш
+Name[zh_CN]=用 K3b 提取视频 DVD
+Name[zh_TW]=使用 K3b 提取視像 DVD Titles
+Exec=k3b --videodvdrip %u
+Icon=k3b
diff --git a/src/konqi/k3b_write_bin_image.desktop b/src/konqi/k3b_write_bin_image.desktop
new file mode 100644
index 0000000..40a021c
--- /dev/null
+++ b/src/konqi/k3b_write_bin_image.desktop
@@ -0,0 +1,62 @@
+[Desktop Entry]
+Actions=WriteCdImage;
+Encoding=UTF-8
+ServiceTypes=application/x-cue
+
+[Desktop Action WriteCdImage]
+Exec=k3b --cdimage %F
+Name=Write CD Image with K3b...
+Name[af]=Skryf CD beeld met K3b...
+Name[ar]= اكتب صورة (Image DATA) على القرص المدمج (CD) بواسطة K3b .
+Name[bg]=Запис на CD образ с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে সিডি ইমেজ লেখো...
+Name[br]=srivañ ar skeudenn CD gant K3b ...
+Name[bs]=Zapiši CD image koristeći K3b...
+Name[ca]=Escriu imatge de CD amb el K3b...
+Name[cs]=Vypálit obraz CD...
+Name[da]=Skriv cd-billede med K3b...
+Name[de]=CD-Abbild mit K3b brennen ...
+Name[el]=Εγγραφή εικόνας CD με το K3b...
+Name[eo]=Skribu KD imagon per K3b...
+Name[es]=Grabar imagen de CD con K3b...
+Name[et]=Kirjuta CD-tõmmis K3b abil plaadile...
+Name[fa]=نوشتن تصویر دیسک فشرده با K3b...
+Name[fi]=Polta levykuva cd-levylle K3b:llä...
+Name[fr]=Graver une image CD avec K3b...
+Name[gl]=Escrever unha Imaxe de CD con K3b...
+Name[he]=כתוב תבנית CD בעזרת K3b...
+Name[hi]=के3बी के साथ सीडी इमेज लिखें...
+Name[hu]=CD-képmásfájl írása a K3b-vel...
+Name[is]=Skrifa diskmynd með K3b...
+Name[it]=Scrivi immagine CD con K3b...
+Name[ja]=K3b で CD イメージを書き込み...
+Name[ka]=K3b-ით CD-ის გამოსახულების ჩაწერა...
+Name[km]=សរសេរ​រូបភាព​ស៊ីឌី​ជាមួយ​នឹង K3b...
+Name[lt]=Įrašyti CD atvaizdą su K3b...
+Name[mk]=Запишете CD-слика со K3b...
+Name[ms]= Tulis Imej CD dengan K3b...
+Name[nb]=Skriv CD-bilde med K3b . . .
+Name[nds]=CD-Afbild mit K3b schrieven...
+Name[ne]=K3b सँग सीडी छवि सिर्जना गर्नुहोस्...
+Name[nl]=CD-image schrijven met K3b...
+Name[nn]=Brenn CD-bilete med K3b …
+Name[pa]=K3b ਨਾਲ CD ਪ੍ਰਤੀਬਿੰਬ ਲਿਖੋ...
+Name[pl]=Stwórz obraz płyty CD za pomocą K3b...
+Name[pt]=Gravar uma Imagem de CD com o K3b...
+Name[pt_BR]=Gravar Imagem de CD com o K3b...
+Name[ru]=Записать образ CD, используя K3b...
+Name[sk]=Zapísať obraz CD pomocou K3b...
+Name[sl]=Zapiši sliko CD-ja s K3b ...
+Name[sr]=Упиши одраз CD-а помоћу K3b-а...
+Name[sr@Latn]=Upiši odraz CD-a pomoću K3b-a...
+Name[sv]=Skriv cd-avbild med K3b...
+Name[ta]=குறுந்தகட்டு நிழலுடன் K3bஐ உருவாக்குக...
+Name[tg]=Сабт кардани намуди CD бо истифодабарии K3b...
+Name[tr]=K3b ile CD Kalıbı Yazdır...
+Name[uk]=Записати штамп КД за допомогою K3b...
+Name[uz]=K3b yordamida CD tasvirini yozish
+Name[uz@cyrillic]=K3b ёрдамида CD тасвирини ёзиш
+Name[xh]=Bhala Umfanekiso we CD nge K3b...
+Name[zh_CN]=用 K3b 刻录 CD 映像...
+Name[zh_TW]=使用 K3b 燒錄 CD 影像...
+Icon=k3b
diff --git a/src/konqi/k3b_write_iso_image.desktop b/src/konqi/k3b_write_iso_image.desktop
new file mode 100644
index 0000000..4e3e91e
--- /dev/null
+++ b/src/konqi/k3b_write_iso_image.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Actions=WriteCdImage;
+Encoding=UTF-8
+ServiceTypes=application/x-iso,inode/ISO-image
+
+[Desktop Action WriteCdImage]
+Exec=k3b --image %F
+Name=Write CD or DVD Image with K3b...
+Name[af]=Skryf CD of DVD beeld lêer m.b.v. K3b...
+Name[ar]= اكتب صورة على القرص المدمج (CD) او على القرص المرئي الرقمي (DVD) بواسطة K3b .
+Name[bg]=Запис на CD или DVD образ с K3b...
+Name[bn]=কে-থ্রি-বি দিয়ে সিডি অথবা ডিভিডি ইমেজ লেখো...
+Name[br]=srivañ ur skeudenn CD pe DVD gant K3b ...
+Name[ca]=Escriu imatge de CD o DVD amb el K3b...
+Name[cs]=Vypálit obraz CD nebo DVD pomocí K3b...
+Name[da]=Skriv cd- eller dvd-billede med K3b...
+Name[de]=CD/DVD-Abbild mit K3b brennen ...
+Name[el]=Εγγραφή εικόνας CD ή DVD με το K3b...
+Name[eo]=Skribu KD aŭ DVD imagon per K3b...
+Name[es]=Grabar imagen de CD o DVD con K3b...
+Name[et]=Kirjuta CD- või DVD-tõmmis K3b abil plaadile...
+Name[fa]=نوشتن تصویر دیسک فشرده یا دی وی دی با K3b...
+Name[fi]=Polta levykuva cd- tai dvd-levylle K3b:llä...
+Name[fr]=Graver une image CD ou DVD avec K3b...
+Name[gl]=Escrever unha Imaxe de CD ou DVD con K3b...
+Name[hu]=CD- vagy DVD-képmásfájl írása a K3b-vel...
+Name[is]=Skrifa CD eða DVD mynd með K3b...
+Name[it]=Scrivi immagine CD o DVD con K3b...
+Name[ja]=K3b で CD/DVD イメージを書き込み...
+Name[ka]=K3b-ით CD ან DVD გამოსახულების ჩაწერა...
+Name[km]=សរសេរ​​រូបភាព​ស៊ីឌី ឬ​ឌីវីឌី​ដោយ​ប្រើ K3b...
+Name[lt]=Įrašyti CD ar DVD atvaizdą su K3b...
+Name[mk]=Запишете CD или DVD-слика со K3b...
+Name[ms]=Tulis Imej CD atau DVD dengan K3b...
+Name[nb]=Skriv CD- eller DVD-bilde med K3b . . .
+Name[nds]=CD- oder DVD-Afbild mit K3b schrieven...
+Name[nl]=CD of DVD-image schrijven met K3b...
+Name[nn]=Brenn CD- eller DVD-bilete med K3b …
+Name[pa]=K3b ਨਾਲ CD ਜਾਂ DVD ਪ੍ਰਤੀਬਿੰਬ ਲਿਖੋ...
+Name[pl]=Nagraj obraz płyty CD lub DVD na płytę za pomocą K3b...
+Name[pt]=Escrever uma Imagem de CD ou DVD com o K3b...
+Name[pt_BR]=Gravar Imagem de CD ou DVD com o K3b...
+Name[ru]=Записать образ CD или DVD, используя K3b...
+Name[sk]=Zapísať obraz CD alebo DVD pomocou K3b...
+Name[sr]=Упиши CD или DVD одраз помоћу K3b-а...
+Name[sr@Latn]=Upiši CD ili DVD odraz pomoću K3b-a...
+Name[sv]=Skriv cd- eller dvd-avbild med K3b...
+Name[tg]=Сабт кардани тасвири CD ё DVD бо истифодабарии K3b...
+Name[tr]=K3b ile CD ya da DVD görüntüsü Yazdır...
+Name[uk]=Записати штамп КД або DVD у K3b...
+Name[uz]=K3b yordamida CD yoki DVD tasvirini yozish
+Name[uz@cyrillic]=K3b ёрдамида CD ёки DVD тасвирини ёзиш
+Name[zh_CN]=用 K3b 刻录 CD 或 DVD 映像...
+Name[zh_TW]=使用 K3b 燒錄 CD 或 DVD 影像...
+Icon=k3b
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..d595281
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,152 @@
+
+/*
+ *
+ * $Id: main.cpp 689578 2007-07-18 15:56:58Z trueg $
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ksimpleconfig.h>
+#include <kstdguiitem.h>
+#include <kdebug.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <kurl.h>
+
+#include <qfile.h>
+#include <qcstring.h>
+#include <qdatastream.h>
+#include <qtimer.h>
+
+#include <stdlib.h>
+
+#include "k3bapplication.h"
+#include <k3bglobals.h>
+#include <k3bcore.h>
+
+
+#include <config.h>
+
+static const char* description = I18N_NOOP("A CD and DVD burning application");
+
+
+static KCmdLineOptions options[] =
+ {
+ { "+[URL(s)]", I18N_NOOP("file(s) to open"), 0 },
+ { "datacd", I18N_NOOP("Create a new data CD project and add all given files"), 0 },
+ { "audiocd", I18N_NOOP("Create a new audio CD project and add all given files"), 0 },
+ { "videocd", I18N_NOOP("Create a new video CD project and add all given files"), 0 },
+ { "mixedcd", I18N_NOOP("Create a new mixed mode CD project and add all given files"), 0 },
+ { "emovixcd", I18N_NOOP("Create a new eMovix CD project and add all given files"), 0 },
+ { "datadvd", I18N_NOOP("Create a new data DVD project and add all given files"), 0 },
+ { "emovixdvd", I18N_NOOP("Create a new eMovix DVD project and add all given files"), 0 },
+ { "videodvd", I18N_NOOP("Create a new Video DVD project and add all given files"), 0 },
+ { "burn", I18N_NOOP("Open the project burn dialog for the current project"), 0 },
+ { "copycd <device>", I18N_NOOP("Open the CD copy dialog, optionally specify the source device"), 0 },
+ { "copydvd <device>", I18N_NOOP("Open the DVD copy dialog"), 0 },
+ { "cdimage <url>", I18N_NOOP("Write a CD image to a CD-R(W)"), 0 },
+ { "dvdimage <url>", I18N_NOOP("Write a DVD ISO9660 image to a DVD"), 0 },
+ { "image <url>", I18N_NOOP("Write a CD or DVD image to a CD-R(W) or DVD depending on the size"), 0 },
+ { "erasecd <device>", I18N_NOOP("Erase a CDRW"), 0 },
+ { "formatdvd <device>", I18N_NOOP("Format a DVD-RW or DVD+RW"), 0 },
+ { "cddarip <device>", I18N_NOOP("Extract Audio tracks digitally (+encoding)"), 0 },
+ { "videodvdrip <device>", I18N_NOOP("Rip Video DVD Titles (+transcoding)"), 0 },
+ { "videocdrip <device>", I18N_NOOP("Rip Video CD Tracks"), 0 },
+ { "lang <language>", I18N_NOOP("Set the GUI language"), 0 },
+ { "nosplash", I18N_NOOP("Disable the splash screen"), 0 },
+ { "ao <method>", I18N_NOOP("Set the audio output method (like arts or alsa depending on the installed plugins)"), 0 },
+ { "device <device>", I18N_NOOP( "Set the device to be used for new projects (This option has no effect. "
+ "Its main purpose is to enable handling of empty media from the KDE Media Manager)." ), 0 },
+ KCmdLineLastOption
+ };
+
+int main( int argc, char* argv[] )
+{
+ KAboutData aboutData( "k3b", "K3b",
+ LIBK3B_VERSION, description, KAboutData::License_GPL,
+ "(c) 1999 - 2007, Sebastian Trüg", 0, "http://www.k3b.org" );
+ aboutData.addAuthor("Sebastian Trüg",I18N_NOOP("Maintainer and Lead Developer"), "trueg@k3b.org");
+ aboutData.addAuthor("Christian Kvasny",I18N_NOOP("VideoCD Project and VideoCD ripping"), "chris@k3b.org");
+ aboutData.addCredit("Klaus-Dieter Krannich", I18N_NOOP("Advanced Cdrdao integration"), "kd@k3b.org" );
+
+ aboutData.addCredit("Thomas Froescher",
+ I18N_NOOP("VideoDVD ripping and video encoding in pre-1.0 versions."),
+ "tfroescher@k3b.org");
+ aboutData.addCredit("Alexis Younes aka Ayo",
+ I18N_NOOP("For his bombastic artwork."),
+ "73lab@free.fr" );
+ aboutData.addCredit("Christoph Thielecke",
+ I18N_NOOP("For extensive testing and the first German translation."),
+ "crissi99@gmx.de");
+ aboutData.addCredit("Andy Polyakov",
+ I18N_NOOP("For the great dvd+rw-tools and the nice cooperation."),
+ "appro@fy.chalmers.se" );
+ aboutData.addCredit("Roberto De Leo",
+ I18N_NOOP("For the very cool eMovix package and his accommodating work."),
+ "peggish@users.sf.net" );
+ aboutData.addCredit("John Steele Scott",
+ I18N_NOOP("For the flac decoding plugin."),
+ "toojays@toojays.net" );
+ aboutData.addCredit("György Szombathelyi",
+ I18N_NOOP("For the very useful isofslib."),
+ "gyurco@users.sourceforge.net" );
+ aboutData.addCredit("Erik de Castro Lopo",
+ I18N_NOOP("For libsamplerate which is used for generic resampling in the audio decoder framework."),
+ "erikd@mega-nerd.com" );
+ aboutData.addCredit("Jakob Petsovits",
+ I18N_NOOP("For the very cool conditional audio ripping pattern."),
+ "jpetso@gmx.at" );
+ aboutData.addCredit("Heiner Eichmann",
+ I18N_NOOP("For his work on the BSD port and some great patches."),
+ "h.eichmann@gmx.de" );
+ aboutData.addCredit("Adriaan De Groot",
+ I18N_NOOP("For his work on the BSD port."),
+ "" );
+ aboutData.addCredit("Thiago Macieira",
+ I18N_NOOP("For his help with the many invalid k3b entries on bugs.kde.org."),
+ "thiago@kde.org" );
+ aboutData.addCredit("Marcel Dierkes",
+ I18N_NOOP("For the great K3b icon eyecandy."),
+ "marcel.dierkes@gmx.de" );
+ aboutData.addCredit("Christoph Burger-Scheidlin",
+ I18N_NOOP("For his neverending help cleaning out the K3b bug database."),
+ "andersin@freenet.de" );
+ aboutData.addCredit( "Robert Wadley",
+ I18N_NOOP( "Rob created a great theme and came up with the idea for transparent themes." ),
+ "rob@robntina.fastmail.us" );
+ aboutData.addCredit( "Dmitry Novikov",
+ I18N_NOOP( "For the amazing K3b 1.0 theme." ),
+ "quant@trktvs.ru" );
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ if( K3bApplication::start() ) {
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+ if( args->isSet("lang") )
+ if( !KGlobal::locale()->setLanguage(args->getOption("lang")) )
+ kdDebug() << "Unable to set to language " << args->getOption("lang")
+ << " current is: " << KGlobal::locale()->language() << endl;
+
+ K3bApplication app;
+
+ // we need a running app for the init method
+ QTimer::singleShot( 0, &app, SLOT(init()) );
+
+ return app.exec();
+ }
+}
diff --git a/src/mimetypes/Makefile.am b/src/mimetypes/Makefile.am
new file mode 100644
index 0000000..8f0fb98
--- /dev/null
+++ b/src/mimetypes/Makefile.am
@@ -0,0 +1,3 @@
+kdemime_DATA = x-k3b.desktop
+kdemimedir = $(kde_mimedir)/application
+
diff --git a/src/mimetypes/x-k3b.desktop b/src/mimetypes/x-k3b.desktop
new file mode 100644
index 0000000..49c7c34
--- /dev/null
+++ b/src/mimetypes/x-k3b.desktop
@@ -0,0 +1,65 @@
+# KDE Config File
+[Desktop Entry]
+Encoding=UTF-8
+MimeType=application/x-k3b
+Comment=K3b Project
+Comment[af]=K3b Projek
+Comment[ar]= مشروع K3b
+Comment[bg]=K3b проект
+Comment[bn]=কে-থ্রি-বি প্রকল্প
+Comment[br]=Raktres K3b
+Comment[bs]=K3b projekat
+Comment[ca]=Projecte de K3b
+Comment[cs]=K3b projekt
+Comment[da]=K3b-projekt
+Comment[de]=K3b-Projekt
+Comment[el]=Έργο K3b
+Comment[eo]=K3b projekto
+Comment[es]=Proyecto de K3b
+Comment[et]=K3b Projekt
+Comment[fa]=پروژۀ K3b
+Comment[fi]=K3b-projekti
+Comment[fr]=Projet K3b
+Comment[gl]=Proxecto de K3b
+Comment[he]=פרוייקט K3b
+Comment[hi]=के3बी परियोजना
+Comment[hu]=K3b-projekt
+Comment[is]=K3b verkefni
+Comment[it]=Progetto K3b
+Comment[ja]=K3b プロジェクト
+Comment[ka]=K3b-ის პროექტი
+Comment[km]=គម្រោង K3b
+Comment[lt]=K3b projektas
+Comment[mk]=Проект за K3b
+Comment[ms]=Projek K3b
+Comment[nb]=K3b-prosjekt
+Comment[nds]=K3b-Projekt
+Comment[ne]=K3b परियोजना
+Comment[nl]=K3b-project
+Comment[nn]=K3b-prosjekt
+Comment[pa]=K3b ਪ੍ਰੋਜੈੱਕਟ
+Comment[pl]=Projekt K3b
+Comment[pt]=Projecto do K3b
+Comment[pt_BR]=Projeto do K3b
+Comment[ru]=Проект K3b
+Comment[sk]=K3b Projekt
+Comment[sl]=Projekt K3b
+Comment[sr]=K3b-ов пројекат
+Comment[sr@Latn]=K3b-ov projekat
+Comment[sv]=K3b-projekt
+Comment[ta]=K3bதிட்டம்
+Comment[tg]=Лоиҳаи K3b
+Comment[tr]=K3b Projesi
+Comment[uk]=Проект K3b
+Comment[uz]=K3b loyihasi
+Comment[uz@cyrillic]=K3b лойиҳаси
+Comment[xh]=Iprojekti ye K3b
+Comment[zh_CN]=K3b 方案
+Comment[zh_TW]=K3b 專案
+Icon=k3b
+Type=MimeType
+Patterns=*.k3b;
+X-KDE-AutoEmbed=false
+[Property::X-KDE-NativeExtension]
+Type=QString
+Value=.k3b
diff --git a/src/misc/Makefile.am b/src/misc/Makefile.am
new file mode 100644
index 0000000..ea1809b
--- /dev/null
+++ b/src/misc/Makefile.am
@@ -0,0 +1,14 @@
+AM_CPPFLAGS = -I$(srcdir)/../../libk3b/core \
+ -I$(srcdir)/../../libk3bdevice \
+ -I$(srcdir)/../../libk3b/tools \
+ -I$(srcdir)/../../libk3b/jobs \
+ -I$(srcdir)/../../libk3b/projects \
+ -I$(srcdir)/.. \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libmisc.la
+
+libmisc_la_SOURCES = k3bdvdformattingdialog.cpp k3bcdcopydialog.cpp k3bdvdcopydialog.cpp \
+ k3bcdimagewritingdialog.cpp k3bisoimagewritingdialog.cpp k3bblankingdialog.cpp
diff --git a/src/misc/k3bblankingdialog.cpp b/src/misc/k3bblankingdialog.cpp
new file mode 100644
index 0000000..5f4b531
--- /dev/null
+++ b/src/misc/k3bblankingdialog.cpp
@@ -0,0 +1,343 @@
+/*
+ *
+ * $Id: k3bblankingdialog.cpp 689551 2007-07-18 14:53:32Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bblankingdialog.h"
+#include "k3bdebuggingoutputdialog.h"
+#include "k3bdebuggingoutputfile.h"
+
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include "k3bblankingjob.h"
+#include "k3bwriterselectionwidget.h"
+#include <k3bprogressdialog.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+#include <k3bemptydiscwaiter.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <kguiitem.h>
+#include <kstdguiitem.h>
+#include <kconfig.h>
+
+#include <qgroupbox.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qtextview.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qheader.h>
+#include <qmap.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+
+
+class K3bBlankingDialog::Private
+{
+public:
+ Private()
+ : job(0),
+ erasingDlg(0) {
+ }
+
+ K3bBlankingJob* job;
+ K3bProgressDialog* erasingDlg;
+ K3bDebuggingOutputDialog* debugDialog;
+ K3bDebuggingOutputFile debugFile;
+ QMap<int, int> comboTypeMap;
+ QMap<int, int> typeComboMap;
+
+ bool jobRunning;
+};
+
+
+K3bBlankingDialog::K3bBlankingDialog( QWidget* parent, const char* name )
+ : K3bInteractionDialog( parent, name,
+ i18n("Erase CD-RW"),
+ QString::null,
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "CDRW Erasing" )
+{
+ d = new Private();
+ d->debugDialog = new K3bDebuggingOutputDialog( this );
+
+ setupGui();
+
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged()), this, SLOT(slotWriterChanged()) );
+ connect( m_writerSelectionWidget, SIGNAL(writingAppChanged(int)), this, SLOT(slotWritingAppChanged(int)) );
+ slotWriterChanged();
+ slotWritingAppChanged( m_writerSelectionWidget->writingApp() );
+}
+
+
+K3bBlankingDialog::~K3bBlankingDialog()
+{
+ delete d;
+}
+
+
+void K3bBlankingDialog::setDevice( K3bDevice::Device* dev )
+{
+ m_writerSelectionWidget->setWriterDevice( dev );
+}
+
+
+void K3bBlankingDialog::setupGui()
+{
+ QWidget* frame = mainWidget();
+
+ m_writerSelectionWidget = new K3bWriterSelectionWidget( frame );
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_CD_RW );
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE );
+
+ // --- setup the blanking type button group -----------------------------
+ QGroupBox* groupBlankType = new QGroupBox( 1, Qt::Vertical, i18n("&Erase Type"), frame );
+ groupBlankType->layout()->setSpacing( spacingHint() );
+ groupBlankType->layout()->setMargin( marginHint() );
+
+ m_comboEraseMode = new QComboBox( groupBlankType );
+ // ----------------------------------------------------------------------
+
+ QGridLayout* grid = new QGridLayout( frame );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( 0 );
+ grid->addWidget( m_writerSelectionWidget, 0, 0 );
+ grid->addWidget( groupBlankType, 1, 0 );
+}
+
+
+void K3bBlankingDialog::slotStartClicked()
+{
+ // start the blankingjob and connect to the info-signal
+ // disable the user1 button and enable the cancel button
+ d->debugDialog->clear();
+ d->debugFile.open();
+
+ if( d->job == 0 ) {
+ d->job = new K3bBlankingJob( this, this );
+ connect( d->job, SIGNAL(debuggingOutput(const QString&, const QString&)),
+ d->debugDialog, SLOT(addOutput(const QString&, const QString&)) );
+ connect( d->job, SIGNAL(debuggingOutput(const QString&, const QString&)),
+ &d->debugFile, SLOT(addOutput(const QString&, const QString&)) );
+ connect( d->job, SIGNAL(finished(bool)),
+ this, SLOT(slotJobFinished(bool)) );
+ }
+
+ d->job->setDevice( m_writerSelectionWidget->writerDevice() );
+ d->job->setSpeed( m_writerSelectionWidget->writerSpeed() );
+ // why should one ever not want to force?
+ d->job->setForce( true );
+ d->job->setWritingApp(m_writerSelectionWidget->writingApp());
+ d->job->setMode( d->comboTypeMap[m_comboEraseMode->currentItem()] );
+
+ if( !d->erasingDlg )
+ d->erasingDlg = new K3bProgressDialog( i18n("Erasing CD-RW"), this );
+
+ connect( d->erasingDlg, SIGNAL(cancelClicked()), d->job, SLOT(cancel()) );
+
+ if( !exitLoopOnHide() )
+ hide();
+
+ d->jobRunning = true;
+ d->job->start();
+ if( d->jobRunning ) // in case the job already finished in the start slot
+ d->erasingDlg->exec(false);
+
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "keep action dialogs open", false ) &&
+ !exitLoopOnHide() )
+ show();
+ else
+ close();
+}
+
+
+void K3bBlankingDialog::slotJobFinished( bool success )
+{
+ d->jobRunning = false;
+ d->erasingDlg->hide();
+ d->debugFile.close();
+
+ if( success )
+ KMessageBox::information( this,
+ i18n("Successfully erased CD-RW."),
+ i18n("Success") );
+ else if( d->job->hasBeenCanceled() )
+ KMessageBox::information( this,
+ i18n("Erasing CD-RW canceled."),
+ i18n("Canceled") );
+ else if( KMessageBox::warningYesNo( this,
+ i18n("The Erasing process failed. Do you want to see the debugging output?"),
+ i18n("Erasing failed.") ) == KMessageBox::Yes )
+ d->debugDialog->exec();
+}
+
+
+void K3bBlankingDialog::slotWriterChanged()
+{
+ // check if it is a cdrw writer
+ K3bDevice::Device* dev = m_writerSelectionWidget->writerDevice();
+
+ if( !dev )
+ setButtonEnabled( START_BUTTON, false );
+ else if( dev->writesCdrw() )
+ setButtonEnabled( START_BUTTON, true );
+ else {
+ setButtonEnabled( START_BUTTON, false );
+ KMessageBox::sorry( this, i18n("%1 does not support CD-RW writing.").arg(dev->devicename()) );
+ }
+}
+
+void K3bBlankingDialog::slotWritingAppChanged(int app)
+{
+ QWhatsThis::remove( m_comboEraseMode );
+ QString whatsThisInfo;
+
+ static QString wsComplete = i18n("Erases the complete disk. This takes as long "
+ "as writing the complete CD.");
+ static QString wsFast = i18n("Erases just the TOC, the PMA, and the pregap.");
+ static QString wsTrack = i18n("Erases just the last track.");
+ static QString wsUnclose = i18n("Reopen the last session to make it possible to append "
+ "further data.");
+ static QString wsSession = i18n("Erases the last session of a multisession CD.");
+
+ int lastMode = d->comboTypeMap[m_comboEraseMode->currentItem()];
+
+ m_comboEraseMode->clear();
+ d->comboTypeMap.clear();
+ d->typeComboMap.clear();
+
+ m_comboEraseMode->insertItem( i18n("Fast") );
+ d->comboTypeMap[0] = K3bBlankingJob::Fast;
+ d->typeComboMap[K3bBlankingJob::Fast] = 0;
+ m_comboEraseMode->insertItem( i18n("Complete") );
+ d->comboTypeMap[1] = K3bBlankingJob::Complete;
+ d->typeComboMap[K3bBlankingJob::Complete] = 1;
+
+ whatsThisInfo = "<p>" + i18n("Blanking mode:") +
+ "<p><b>" + i18n("Fast") + "</b><br>" + wsFast;
+ whatsThisInfo += "<p><b>" + i18n("Complete") + "</b><br>" + wsComplete;
+
+ if ( app != K3b::CDRDAO ) {
+ m_comboEraseMode->insertItem( i18n("Erase Last Track") );
+ d->comboTypeMap[2] = K3bBlankingJob::Track;
+ d->typeComboMap[K3bBlankingJob::Track] = 2;
+ whatsThisInfo += "<p><b>" + i18n("Erase Last Track") + "</b><br>" + wsTrack;
+ m_comboEraseMode->insertItem( i18n("Reopen Last Session") );
+ d->comboTypeMap[3] = K3bBlankingJob::Unclose;
+ d->typeComboMap[K3bBlankingJob::Unclose] = 3;
+ whatsThisInfo += "<p><b>" + i18n("Reopen Last Session") + "</b><br>" + wsUnclose;
+ m_comboEraseMode->insertItem( i18n("Erase Last Session") );
+ d->comboTypeMap[4] = K3bBlankingJob::Session;
+ d->typeComboMap[K3bBlankingJob::Session] = 4;
+ whatsThisInfo += "<p><b>" + i18n("Erase Last Session") + "</b><br>" + wsSession;
+ }
+
+ QWhatsThis::add( m_comboEraseMode, whatsThisInfo );
+
+ // try to reset last mode
+ if( d->typeComboMap.contains( lastMode ) )
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[lastMode] );
+ else
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[K3bBlankingJob::Fast] );
+}
+
+
+void K3bBlankingDialog::loadK3bDefaults()
+{
+ m_writerSelectionWidget->loadDefaults();
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[K3bBlankingJob::Fast] );
+}
+
+void K3bBlankingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_writerSelectionWidget->loadConfig( c );
+ slotWritingAppChanged( m_writerSelectionWidget->writingApp() );
+
+ QString mode = c->readEntry( "erase_mode" );
+ kdDebug() << "(K3bBlankingDialog) slotWritingAppChanged mode: " << mode << endl;
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[K3bBlankingJob::Fast] );
+ if( mode == "complete" )
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[K3bBlankingJob::Complete] );
+ else if( d->typeComboMap.size() > 2 ) {
+ if( mode == "session" )
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[K3bBlankingJob::Session] );
+ else if( mode == "track" )
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[K3bBlankingJob::Track] );
+ else if( mode == "unclose_session" )
+ m_comboEraseMode->setCurrentItem( d->typeComboMap[K3bBlankingJob::Unclose] );
+ }
+}
+
+void K3bBlankingDialog::saveUserDefaults( KConfigBase* c )
+{
+ QString mode;
+ switch( d->comboTypeMap[m_comboEraseMode->currentItem()] ) {
+ case K3bBlankingJob::Complete:
+ mode = "complete";
+ break;
+ case K3bBlankingJob::Session:
+ mode = "session";
+ break;
+ case K3bBlankingJob::Track:
+ mode = "track";
+ break;
+ case K3bBlankingJob::Unclose:
+ mode = "unclose_session";
+ break;
+ default:
+ mode = "fast";
+ break;
+ }
+ c->writeEntry( "erase_mode", mode );
+
+ m_writerSelectionWidget->saveConfig( c );
+}
+
+
+int K3bBlankingDialog::waitForMedia( K3bDevice::Device* device,
+ int mediaState,
+ int mediaType,
+ const QString& message )
+{
+ // this is only needed for the formatting
+ return K3bEmptyDiscWaiter::wait( device, mediaState, mediaType, message, this );
+}
+
+
+bool K3bBlankingDialog::questionYesNo( const QString& text,
+ const QString& caption,
+ const QString& yesText,
+ const QString& noText )
+{
+ return ( KMessageBox::questionYesNo( this,
+ text,
+ caption,
+ yesText.isEmpty() ? KStdGuiItem::yes() : KGuiItem(yesText),
+ noText.isEmpty() ? KStdGuiItem::no() : KGuiItem(noText) ) == KMessageBox::Yes );
+}
+
+
+void K3bBlankingDialog::blockingInformation( const QString& text,
+ const QString& caption )
+{
+ KMessageBox::information( this, text, caption );
+}
+
+#include "k3bblankingdialog.moc"
diff --git a/src/misc/k3bblankingdialog.h b/src/misc/k3bblankingdialog.h
new file mode 100644
index 0000000..cbd5583
--- /dev/null
+++ b/src/misc/k3bblankingdialog.h
@@ -0,0 +1,86 @@
+/*
+ *
+ * $Id: k3bblankingdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_BLANKING_DIALOG_H
+#define K3B_BLANKING_DIALOG_H
+
+#include "k3binteractiondialog.h"
+#include <k3bjobhandler.h>
+
+class QGroupBox;
+class QComboBox;
+class QCloseEvent;
+class KListView;
+class K3bWriterSelectionWidget;
+namespace K3bDevice {
+ class Device;
+}
+
+
+class K3bBlankingDialog : public K3bInteractionDialog, public K3bJobHandler
+{
+Q_OBJECT
+
+ public:
+ K3bBlankingDialog( QWidget*, const char* );
+ ~K3bBlankingDialog();
+
+ /**
+ * @reimplemented from K3bJobHandler
+ */
+ int waitForMedia( K3bDevice::Device*,
+ int mediaState = K3bDevice::STATE_EMPTY,
+ int mediaType = K3bDevice::MEDIA_WRITABLE_CD,
+ const QString& message = QString::null );
+
+ /**
+ * @reimplemented from K3bJobHandler
+ */
+ bool questionYesNo( const QString& text,
+ const QString& caption = QString::null,
+ const QString& yesText = QString::null,
+ const QString& noText = QString::null );
+
+ /**
+ * reimplemented from K3bJobHandler
+ */
+ void blockingInformation( const QString& text,
+ const QString& caption = QString::null );
+
+ public slots:
+ void setDevice( K3bDevice::Device* );
+
+ protected slots:
+ void slotStartClicked();
+ void slotWriterChanged();
+ void slotWritingAppChanged( int );
+ void slotJobFinished( bool );
+
+ private:
+ void setupGui();
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+
+ K3bWriterSelectionWidget* m_writerSelectionWidget;
+
+ QComboBox* m_comboEraseMode;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/misc/k3bcdcopydialog.cpp b/src/misc/k3bcdcopydialog.cpp
new file mode 100644
index 0000000..4f1ce3b
--- /dev/null
+++ b/src/misc/k3bcdcopydialog.cpp
@@ -0,0 +1,556 @@
+/*
+ *
+ * $Id: k3bcdcopydialog.cpp 733470 2007-11-06 12:10:29Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ * Klaus-Dieter Krannich <kd@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bcdcopydialog.h"
+
+#include "k3bmediaselectioncombobox.h"
+#include "k3bcdcopyjob.h"
+#include "k3bclonejob.h"
+
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bcore.h>
+#include <k3bstdguiitems.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bburnprogressdialog.h>
+#include <k3bglobals.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bthememanager.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bapplication.h>
+#include <k3bmediacache.h>
+
+#include <kguiitem.h>
+#include <klocale.h>
+#include <kstdguiitem.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qptrlist.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qtabwidget.h>
+#include <qwhatsthis.h>
+#include <qhbox.h>
+#include <qpushbutton.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qsizepolicy.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+
+K3bCdCopyDialog::K3bCdCopyDialog( QWidget *parent, const char *name, bool modal )
+ : K3bInteractionDialog( parent, name, i18n("CD Copy"), i18n("and CD Cloning"),
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "CD Copy",
+ modal )
+{
+ QWidget* main = mainWidget();
+
+ QGridLayout* mainGrid = new QGridLayout( main );
+ mainGrid->setSpacing( spacingHint() );
+ mainGrid->setMargin( 0 );
+
+ QGroupBox* groupSource = new QGroupBox( 1, Qt::Vertical, i18n("Source Medium"), main );
+ groupSource->setInsideSpacing( spacingHint() );
+ groupSource->setInsideMargin( marginHint() );
+ m_comboSourceDevice = new K3bMediaSelectionComboBox( groupSource );
+ m_comboSourceDevice->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_CD|K3bDevice::MEDIA_CD_ROM );
+ m_comboSourceDevice->setWantedMediumState( K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE );
+
+ m_writerSelectionWidget = new K3bWriterSelectionWidget( main );
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_CD );
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY );
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::CDRECORD );
+
+ // tab widget --------------------
+ QTabWidget* tabWidget = new QTabWidget( main );
+
+ //
+ // option tab --------------------
+ //
+ QWidget* optionTab = new QWidget( tabWidget );
+ QGridLayout* optionTabGrid = new QGridLayout( optionTab );
+ optionTabGrid->setSpacing( spacingHint() );
+ optionTabGrid->setMargin( marginHint() );
+
+ QGroupBox* groupCopyMode = new QGroupBox( 1, Qt::Vertical, i18n("Copy Mode"), optionTab );
+ groupCopyMode->setInsideMargin( marginHint() );
+ groupCopyMode->setInsideSpacing( spacingHint() );
+ m_comboCopyMode = new QComboBox( groupCopyMode );
+ m_comboCopyMode->insertItem( i18n("Normal Copy") );
+ m_comboCopyMode->insertItem( i18n("Clone Copy") );
+
+ QGroupBox* groupWritingMode = new QGroupBox( 1, Qt::Vertical, i18n("Writing Mode"), optionTab );
+ groupWritingMode->setInsideMargin( marginHint() );
+ m_writingModeWidget = new K3bWritingModeWidget( groupWritingMode );
+
+ QGroupBox* groupCopies = new QGroupBox( 2, Qt::Horizontal, i18n("Copies"), optionTab );
+ groupCopies->setInsideSpacing( spacingHint() );
+ groupCopies->setInsideMargin( marginHint() );
+ QLabel* pixLabel = new QLabel( groupCopies );
+ pixLabel->setPixmap( SmallIcon( "cdcopy", KIcon::SizeMedium ) );
+ pixLabel->setScaledContents( false );
+ m_spinCopies = new QSpinBox( 1, 999, 1, groupCopies );
+
+ QGroupBox* groupOptions = new QGroupBox( 5, Qt::Vertical, i18n("Settings"), optionTab );
+ groupOptions->setInsideSpacing( spacingHint() );
+ groupOptions->setInsideMargin( marginHint() );
+ m_checkSimulate = K3bStdGuiItems::simulateCheckbox( groupOptions );
+ m_checkCacheImage = K3bStdGuiItems::createCacheImageCheckbox( groupOptions );
+ m_checkOnlyCreateImage = K3bStdGuiItems::onlyCreateImagesCheckbox( groupOptions );
+ m_checkDeleteImages = K3bStdGuiItems::removeImagesCheckbox( groupOptions );
+
+ optionTabGrid->addWidget( groupCopyMode, 0, 0 );
+ optionTabGrid->addWidget( groupWritingMode, 1, 0 );
+ optionTabGrid->addMultiCellWidget( groupOptions, 0, 2, 1, 1 );
+ optionTabGrid->addWidget( groupCopies, 2, 0 );
+ optionTabGrid->setRowStretch( 2, 1 );
+ optionTabGrid->setColStretch( 1, 1 );
+
+ tabWidget->addTab( optionTab, i18n("&Options") );
+
+
+ //
+ // image tab ------------------
+ //
+ QWidget* imageTab = new QWidget( tabWidget );
+ QGridLayout* imageTabGrid = new QGridLayout( imageTab );
+ imageTabGrid->setSpacing( spacingHint() );
+ imageTabGrid->setMargin( marginHint() );
+
+ m_tempDirSelectionWidget = new K3bTempDirSelectionWidget( imageTab );
+
+ imageTabGrid->addWidget( m_tempDirSelectionWidget, 0, 0 );
+
+ tabWidget->addTab( imageTab, i18n("&Image") );
+
+
+ //
+ // advanced tab ------------------
+ //
+ QWidget* advancedTab = new QWidget( tabWidget );
+ QGridLayout* advancedTabGrid = new QGridLayout( advancedTab );
+ advancedTabGrid->setSpacing( spacingHint() );
+ advancedTabGrid->setMargin( marginHint() );
+
+ m_groupAdvancedDataOptions = new QGroupBox( 3, Qt::Vertical, i18n("Data"), advancedTab, "data_options" );
+ m_groupAdvancedDataOptions->setInsideSpacing( spacingHint() );
+ m_groupAdvancedDataOptions->setInsideMargin( marginHint() );
+ QHBox* box = new QHBox( m_groupAdvancedDataOptions );
+ box->setSpacing( spacingHint() );
+ box->setStretchFactor( new QLabel( i18n("Read retries:"), box ), 1 );
+ m_spinDataRetries = new QSpinBox( 1, 128, 1, box );
+ m_checkIgnoreDataReadErrors = K3bStdGuiItems::ignoreAudioReadErrorsCheckBox( m_groupAdvancedDataOptions );
+ m_checkNoCorrection = new QCheckBox( i18n("No error correction"), m_groupAdvancedDataOptions );
+
+ m_groupAdvancedAudioOptions = new QGroupBox( 5, Qt::Vertical, i18n("Audio"), advancedTab, "audio_options" );
+ m_groupAdvancedAudioOptions->setInsideSpacing( spacingHint() );
+ m_groupAdvancedAudioOptions->setInsideMargin( marginHint() );
+ box = new QHBox( m_groupAdvancedAudioOptions );
+ box->setSpacing( spacingHint() );
+ box->setStretchFactor( new QLabel( i18n("Read retries:"), box ), 1 );
+ m_spinAudioRetries = new QSpinBox( 1, 128, 1, box );
+ m_checkIgnoreAudioReadErrors = K3bStdGuiItems::ignoreAudioReadErrorsCheckBox( m_groupAdvancedAudioOptions );
+ box = new QHBox( m_groupAdvancedAudioOptions );
+ box->setSpacing( spacingHint() );
+ box->setStretchFactor(new QLabel( i18n("Paranoia mode:"), box ), 1 );
+ m_comboParanoiaMode = K3bStdGuiItems::paranoiaModeComboBox( box );
+ m_checkReadCdText = new QCheckBox( i18n("Copy CD-Text"), m_groupAdvancedAudioOptions );
+ m_checkPrefereCdText = new QCheckBox( i18n("Prefer CD-Text"), m_groupAdvancedAudioOptions );
+
+ advancedTabGrid->addWidget( m_groupAdvancedDataOptions, 0, 1 );
+ advancedTabGrid->addWidget( m_groupAdvancedAudioOptions, 0, 0 );
+
+ tabWidget->addTab( advancedTab, i18n("&Advanced") );
+
+ mainGrid->addWidget( groupSource, 0, 0 );
+ mainGrid->addWidget( m_writerSelectionWidget, 1, 0 );
+ mainGrid->addWidget( tabWidget, 2, 0 );
+ mainGrid->setRowStretch( 2, 1 );
+
+
+ connect( m_comboSourceDevice, SIGNAL(selectionChanged(K3bDevice::Device*)), this, SLOT(slotToggleAll()) );
+ connect( m_comboSourceDevice, SIGNAL(selectionChanged(K3bDevice::Device*)),
+ this, SLOT(slotSourceMediumChanged(K3bDevice::Device*)) );
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged()), this, SLOT(slotToggleAll()) );
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged(K3bDevice::Device*)),
+ m_writingModeWidget, SLOT(setDevice(K3bDevice::Device*)) );
+ connect( m_writingModeWidget, SIGNAL(writingModeChanged(int)), this, SLOT(slotToggleAll()) );
+ connect( m_checkCacheImage, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_checkSimulate, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_checkOnlyCreateImage, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_comboCopyMode, SIGNAL(activated(int)), this, SLOT(slotToggleAll()) );
+ connect( m_checkReadCdText, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+
+ QToolTip::add( m_checkIgnoreDataReadErrors, i18n("Skip unreadable data sectors") );
+ QToolTip::add( m_checkNoCorrection, i18n("Disable the source drive's error correction") );
+ QToolTip::add( m_checkPrefereCdText, i18n("Use CD-Text instead of cddb if available.") );
+ QToolTip::add( m_checkReadCdText, i18n("Copy CD-Text from the source CD if available.") );
+
+ QWhatsThis::add( m_checkNoCorrection, i18n("<p>If this option is checked K3b will disable the "
+ "source drive's ECC/EDC error correction. This way sectors "
+ "that are unreadable by intention can be read."
+ "<p>This may be useful for cloning CDs with copy "
+ "protection based on corrupted sectors.") );
+ QWhatsThis::add( m_checkReadCdText, i18n("<p>If this option is checked K3b will search for CD-Text on the source CD. "
+ "Disable it if your CD drive has problems with reading CD-Text or you want "
+ "to stick to Cddb info.") );
+ QWhatsThis::add( m_checkPrefereCdText, i18n("<p>If this option is checked and K3b finds CD-Text on the source media it will be "
+ "copied to the resulting CD ignoring any potentially existing Cddb entries.") );
+ QWhatsThis::add( m_checkIgnoreDataReadErrors, i18n("<p>If this option is checked and K3b is not able to read a data sector from the "
+ "source CD/DVD it will be replaced with zeros on the resulting copy.") );
+
+ QWhatsThis::add( m_comboCopyMode,
+ "<p><b>" + i18n("Normal Copy") + "</b>"
+ + i18n("<p>This is the normal copy mode recommended for most CD types. "
+ "It allows copying Audio CDs, multi and single session Data CDs, and "
+ "Enhanced Audio CDs (an Audio CD containing an additional data session)."
+ "<p>For VideoCDs please use the CD Cloning mode.")
+ + "<p><b>" + i18n("Clone Copy") + "</b>"
+ + i18n("<p>In CD Cloning mode K3b performs a raw copy of the CD. That means it does "
+ "not care about the content but simply copies the CD bit by bit. It may be used "
+ "to copy VideoCDs or CDs which contain erroneous sectors."
+ "<p><b>Caution:</b> Only single session CDs can be cloned.") );
+}
+
+
+K3bCdCopyDialog::~K3bCdCopyDialog()
+{
+}
+
+
+void K3bCdCopyDialog::init()
+{
+ slotSourceMediumChanged( m_comboSourceDevice->selectedDevice() );
+}
+
+
+void K3bCdCopyDialog::setReadingDevice( K3bDevice::Device* dev )
+{
+ m_comboSourceDevice->setSelectedDevice( dev );
+}
+
+
+K3bDevice::Device* K3bCdCopyDialog::readingDevice() const
+{
+ return m_comboSourceDevice->selectedDevice();
+}
+
+
+void K3bCdCopyDialog::slotStartClicked()
+{
+ //
+ // Let's check the available size
+ //
+ if( m_checkCacheImage->isChecked() || m_checkOnlyCreateImage->isChecked() ) {
+ if( neededSize()/1024 > m_tempDirSelectionWidget->freeTempSpace() ) {
+ if( KMessageBox::warningContinueCancel( this, i18n("There seems to be not enough free space in temporary directory. "
+ "Write anyway?") ) == KMessageBox::Cancel )
+ return;
+ }
+ }
+
+
+ K3bJobProgressDialog* dlg = 0;
+ if( m_checkOnlyCreateImage->isChecked() ) {
+ dlg = new K3bJobProgressDialog( kapp->mainWidget() );
+ }
+ else {
+ dlg = new K3bBurnProgressDialog( kapp->mainWidget() );
+ }
+
+ K3bBurnJob* burnJob = 0;
+
+ if( m_comboCopyMode->currentItem() == 1 ) {
+
+ //
+ // check for m_tempDirSelectionWidget->tempPath() and
+ // m_tempDirSelectionWidget-tempPath() + ".toc"
+ //
+ if( QFileInfo( m_tempDirSelectionWidget->tempPath() ).isFile() ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(m_tempDirSelectionWidget->tempPath()),
+ i18n("File Exists"), i18n("Overwrite") )
+ != KMessageBox::Continue )
+ return;
+ }
+
+ if( QFileInfo( m_tempDirSelectionWidget->tempPath() + ".toc" ).isFile() ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(m_tempDirSelectionWidget->tempPath() + ".toc"),
+ i18n("File Exists"), i18n("Overwrite") )
+ != KMessageBox::Continue )
+ return;
+ }
+
+ K3bCloneJob* job = new K3bCloneJob( dlg, this );
+
+ job->setWriterDevice( m_writerSelectionWidget->writerDevice() );
+ job->setReaderDevice( m_comboSourceDevice->selectedDevice() );
+ job->setImagePath( m_tempDirSelectionWidget->tempPath() );
+ job->setNoCorrection( m_checkNoCorrection->isChecked() );
+ job->setRemoveImageFiles( m_checkDeleteImages->isChecked() && !m_checkOnlyCreateImage->isChecked() );
+ job->setOnlyCreateImage( m_checkOnlyCreateImage->isChecked() );
+ job->setSimulate( m_checkSimulate->isChecked() );
+ job->setWriteSpeed( m_writerSelectionWidget->writerSpeed() );
+ job->setCopies( m_checkSimulate->isChecked() ? 1 : m_spinCopies->value() );
+ job->setReadRetries( m_spinDataRetries->value() );
+
+ burnJob = job;
+ }
+ else {
+ K3bCdCopyJob* job = new K3bCdCopyJob( dlg, this );
+
+ job->setWriterDevice( m_writerSelectionWidget->writerDevice() );
+ job->setReaderDevice( m_comboSourceDevice->selectedDevice() );
+ job->setSpeed( m_writerSelectionWidget->writerSpeed() );
+ job->setSimulate( m_checkSimulate->isChecked() );
+ job->setOnTheFly( !m_checkCacheImage->isChecked() );
+ job->setKeepImage( !m_checkDeleteImages->isChecked() || m_checkOnlyCreateImage->isChecked() );
+ job->setOnlyCreateImage( m_checkOnlyCreateImage->isChecked() );
+ job->setTempPath( m_tempDirSelectionWidget->plainTempPath() );
+ job->setCopies( m_checkSimulate->isChecked() ? 1 : m_spinCopies->value() );
+ job->setParanoiaMode( m_comboParanoiaMode->currentText().toInt() );
+ job->setDataReadRetries( m_spinDataRetries->value() );
+ job->setAudioReadRetries( m_spinAudioRetries->value() );
+ job->setCopyCdText( m_checkReadCdText->isChecked() );
+ job->setPreferCdText( m_checkPrefereCdText->isChecked() );
+ job->setIgnoreDataReadErrors( m_checkIgnoreDataReadErrors->isChecked() );
+ job->setIgnoreAudioReadErrors( m_checkIgnoreAudioReadErrors->isChecked() );
+ job->setNoCorrection( m_checkNoCorrection->isChecked() );
+ job->setWritingMode( m_writingModeWidget->writingMode() );
+
+ burnJob = job;
+ }
+
+ if( !exitLoopOnHide() )
+ hide();
+
+ dlg->startJob( burnJob );
+
+ delete dlg;
+ delete burnJob;
+
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "keep action dialogs open", false ) &&
+ !exitLoopOnHide() )
+ show();
+ else
+ close();
+}
+
+
+void K3bCdCopyDialog::toggleAll()
+{
+ updateOverrideDevice();
+
+ K3bDevice::Device* dev = m_writerSelectionWidget->writerDevice();
+
+ m_checkSimulate->setEnabled( !m_checkOnlyCreateImage->isChecked() );
+ m_checkDeleteImages->setEnabled( !m_checkOnlyCreateImage->isChecked() && m_checkCacheImage->isChecked() );
+ m_spinCopies->setDisabled( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() );
+ m_tempDirSelectionWidget->setDisabled( !m_checkCacheImage->isChecked() );
+ m_checkOnlyCreateImage->setEnabled( m_checkCacheImage->isChecked() );
+ m_writerSelectionWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_checkCacheImage->setEnabled( !m_checkOnlyCreateImage->isChecked() );
+
+ if( m_comboCopyMode->currentItem() == 1 ) {
+ // cdrecord does not support cloning on-the-fly
+ m_checkCacheImage->setChecked(true);
+ m_checkCacheImage->setEnabled(false);
+
+ m_writingModeWidget->setSupportedModes( K3b::RAW );
+ }
+ else {
+ m_writingModeWidget->setSupportedModes( K3b::TAO|K3b::DAO|K3b::RAW );
+ }
+
+
+
+ static_cast<QWidget*>( child( "audio_options" ) )->setDisabled( m_comboCopyMode->currentItem() == 1 );
+
+ m_checkIgnoreDataReadErrors->setDisabled( m_comboCopyMode->currentItem() == 1 );
+
+ m_groupAdvancedAudioOptions->setEnabled( k3bappcore->mediaCache()->medium( m_comboSourceDevice->selectedDevice() ).content() & K3bMedium::CONTENT_AUDIO &&
+ m_comboCopyMode->currentItem() == 0 );
+
+ m_writingModeWidget->setEnabled( !m_checkOnlyCreateImage->isChecked() );
+
+ m_tempDirSelectionWidget->setNeededSize( neededSize() );
+
+ setButtonEnabled( START_BUTTON, m_comboSourceDevice->selectedDevice() &&
+ (dev || m_checkOnlyCreateImage->isChecked()) );
+}
+
+
+void K3bCdCopyDialog::slotSourceMediumChanged( K3bDevice::Device* dev )
+{
+ updateOverrideDevice();
+
+ K3bMedium medium = k3bappcore->mediaCache()->medium( dev );
+
+ m_tempDirSelectionWidget->setNeededSize( neededSize() );
+
+ if( k3bappcore->mediaCache()->toc( dev ).contentType() == K3bDevice::DATA ) {
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+ m_tempDirSelectionWidget->setDefaultImageFileName( medium.volumeId().lower()
+ + ( medium.toc().count() == 1 ? QString(".iso") : QString::null ) );
+ }
+ else {
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::DIR );
+ }
+
+ m_groupAdvancedAudioOptions->setEnabled( k3bappcore->mediaCache()->medium( dev ).content() & K3bMedium::CONTENT_AUDIO );
+ m_groupAdvancedDataOptions->setEnabled( k3bappcore->mediaCache()->medium( dev ).content() & K3bMedium::CONTENT_DATA );
+
+ // we can only clone single session CDs
+ if( k3bappcore->mediaCache()->toc( dev ).sessions() > 1 ) {
+ m_comboCopyMode->setEnabled( false );
+ m_comboCopyMode->setCurrentItem( 0 );
+ }
+ else {
+ m_comboCopyMode->setEnabled( true );
+ }
+
+ toggleAll();
+}
+
+
+void K3bCdCopyDialog::updateOverrideDevice()
+{
+ if( !m_checkCacheImage->isChecked() ) {
+ m_writerSelectionWidget->setOverrideDevice( 0 );
+ m_writerSelectionWidget->setIgnoreDevice( m_comboSourceDevice->selectedDevice() );
+ }
+ else {
+ m_writerSelectionWidget->setIgnoreDevice( 0 );
+ m_writerSelectionWidget->setOverrideDevice( m_comboSourceDevice->selectedDevice(),
+ i18n("Use the same device for burning"),
+ i18n("<qt>Use the same device for burning <i>(Or insert another medium)</i>") );
+ }
+}
+
+
+void K3bCdCopyDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_writerSelectionWidget->loadConfig( c );
+ m_comboSourceDevice->setSelectedDevice( k3bcore->deviceManager()->findDevice( c->readEntry( "source_device" ) ) );
+ m_writingModeWidget->loadConfig( c );
+ m_checkSimulate->setChecked( c->readBoolEntry( "simulate", false ) );
+ m_checkCacheImage->setChecked( !c->readBoolEntry( "on_the_fly", false ) );
+ m_checkDeleteImages->setChecked( c->readBoolEntry( "delete_images", true ) );
+ m_checkOnlyCreateImage->setChecked( c->readBoolEntry( "only_create_image", false ) );
+ m_comboParanoiaMode->setCurrentItem( c->readNumEntry( "paranoia_mode", 0 ) );
+
+ m_spinCopies->setValue( c->readNumEntry( "copies", 1 ) );
+
+ m_tempDirSelectionWidget->readConfig( c );
+
+ if( c->readEntry( "copy mode", "normal" ) == "normal" )
+ m_comboCopyMode->setCurrentItem( 0 );
+ else
+ m_comboCopyMode->setCurrentItem( 1 );
+
+ m_checkReadCdText->setChecked( c->readBoolEntry( "copy cdtext", true ) );
+ m_checkPrefereCdText->setChecked( c->readBoolEntry( "prefer cdtext", false ) );
+ m_checkIgnoreDataReadErrors->setChecked( c->readBoolEntry( "ignore data read errors", false ) );
+ m_checkIgnoreAudioReadErrors->setChecked( c->readBoolEntry( "ignore audio read errors", true ) );
+ m_checkNoCorrection->setChecked( c->readBoolEntry( "no correction", false ) );
+
+ m_spinDataRetries->setValue( c->readNumEntry( "data retries", 128 ) );
+ m_spinAudioRetries->setValue( c->readNumEntry( "audio retries", 5 ) );
+
+ slotToggleAll();
+}
+
+
+void K3bCdCopyDialog::saveUserDefaults( KConfigBase* c )
+{
+ m_writingModeWidget->saveConfig( c );
+ c->writeEntry( "simulate", m_checkSimulate->isChecked() );
+ c->writeEntry( "on_the_fly", !m_checkCacheImage->isChecked() );
+ c->writeEntry( "delete_images", m_checkDeleteImages->isChecked() );
+ c->writeEntry( "only_create_image", m_checkOnlyCreateImage->isChecked() );
+ c->writeEntry( "paranoia_mode", m_comboParanoiaMode->currentText().toInt() );
+ c->writeEntry( "copies", m_spinCopies->value() );
+
+ m_writerSelectionWidget->saveConfig( c );
+ m_tempDirSelectionWidget->saveConfig( c );
+
+ c->writeEntry( "source_device", m_comboSourceDevice->selectedDevice() ? m_comboSourceDevice->selectedDevice()->devicename() : QString() );
+
+ c->writeEntry( "copy cdtext", m_checkReadCdText->isChecked() );
+ c->writeEntry( "prefer cdtext", m_checkPrefereCdText->isChecked() );
+ c->writeEntry( "ignore data read errors", m_checkIgnoreDataReadErrors->isChecked() );
+ c->writeEntry( "ignore audio read errors", m_checkIgnoreAudioReadErrors->isChecked() );
+ c->writeEntry( "no correction", m_checkNoCorrection->isChecked() );
+ c->writeEntry( "data retries", m_spinDataRetries->value() );
+ c->writeEntry( "audio retries", m_spinAudioRetries->value() );
+
+ QString s;
+ if( m_comboCopyMode->currentItem() == 1 )
+ s = "clone";
+ else
+ s = "normal";
+ c->writeEntry( "copy mode", s );
+}
+
+
+void K3bCdCopyDialog::loadK3bDefaults()
+{
+ m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO );
+ m_writerSelectionWidget->loadDefaults();
+ m_checkSimulate->setChecked( false );
+ m_checkCacheImage->setChecked( true );
+ m_checkDeleteImages->setChecked( true );
+ m_checkOnlyCreateImage->setChecked( false );
+ m_comboParanoiaMode->setCurrentItem(0);
+ m_spinCopies->setValue(1);
+ m_checkReadCdText->setChecked(true);
+ m_checkPrefereCdText->setChecked(false);
+ m_checkIgnoreDataReadErrors->setChecked(false);
+ m_checkIgnoreAudioReadErrors->setChecked(true);
+ m_checkNoCorrection->setChecked(false);
+ m_comboCopyMode->setCurrentItem( 0 ); // normal
+ m_spinDataRetries->setValue(128);
+ m_spinAudioRetries->setValue(5);
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() );
+
+ slotToggleAll();
+}
+
+
+KIO::filesize_t K3bCdCopyDialog::neededSize() const
+{
+ if( m_comboCopyMode->currentItem() == 0 )
+ return k3bappcore->mediaCache()->medium( m_comboSourceDevice->selectedDevice() ).diskInfo().size().mode1Bytes();
+ else
+ return k3bappcore->mediaCache()->medium( m_comboSourceDevice->selectedDevice() ).diskInfo().size().rawBytes();
+}
+
+#include "k3bcdcopydialog.moc"
diff --git a/src/misc/k3bcdcopydialog.h b/src/misc/k3bcdcopydialog.h
new file mode 100644
index 0000000..b7a4bd2
--- /dev/null
+++ b/src/misc/k3bcdcopydialog.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * $Id: k3bcdcopydialog.h 733470 2007-11-06 12:10:29Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ * Klaus-Dieter Krannich <kd@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BCDCOPYDIALOG_H
+#define K3BCDCOPYDIALOG_H
+
+
+#include <k3binteractiondialog.h>
+
+#include <kio/global.h>
+
+namespace K3bDevice {
+ class Device;
+ class DeviceManager;
+}
+
+class K3bWriterSelectionWidget;
+class K3bTempDirSelectionWidget;
+class K3bMediaSelectionComboBox;
+class QCheckBox;
+class QSpinBox;
+class QComboBox;
+class K3bWritingModeWidget;
+class QButtonGroup;
+class QGroupBox;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bCdCopyDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bCdCopyDialog(QWidget *parent = 0, const char *name = 0, bool modal = true );
+ ~K3bCdCopyDialog();
+
+ void setReadingDevice( K3bDevice::Device* );
+ K3bDevice::Device* readingDevice() const;
+
+ private slots:
+ void slotStartClicked();
+
+ void slotSourceMediumChanged( K3bDevice::Device* );
+ void updateOverrideDevice();
+
+ protected:
+ void init();
+ void toggleAll();
+
+ private:
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void loadK3bDefaults();
+
+ KIO::filesize_t neededSize() const;
+
+ K3bWriterSelectionWidget* m_writerSelectionWidget;
+ K3bTempDirSelectionWidget* m_tempDirSelectionWidget;
+ QCheckBox* m_checkSimulate;
+ QCheckBox* m_checkCacheImage;
+ QCheckBox* m_checkDeleteImages;
+ QCheckBox* m_checkOnlyCreateImage;
+ QCheckBox* m_checkReadCdText;
+ QCheckBox* m_checkPrefereCdText;
+ QCheckBox* m_checkIgnoreDataReadErrors;
+ QCheckBox* m_checkIgnoreAudioReadErrors;
+ QCheckBox* m_checkNoCorrection;
+ K3bMediaSelectionComboBox* m_comboSourceDevice;
+ QComboBox* m_comboParanoiaMode;
+ QSpinBox* m_spinCopies;
+ QSpinBox* m_spinDataRetries;
+ QSpinBox* m_spinAudioRetries;
+ K3bWritingModeWidget* m_writingModeWidget;
+ QComboBox* m_comboCopyMode;
+
+ QGroupBox* m_groupAdvancedDataOptions;
+ QGroupBox* m_groupAdvancedAudioOptions;
+};
+
+#endif
diff --git a/src/misc/k3bcdimagewritingdialog.cpp b/src/misc/k3bcdimagewritingdialog.cpp
new file mode 100644
index 0000000..b071d94
--- /dev/null
+++ b/src/misc/k3bcdimagewritingdialog.cpp
@@ -0,0 +1,1049 @@
+/*
+ *
+ * $Id: k3bcdimagewritingdialog.cpp 630454 2007-02-05 13:06:45Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3bcdimagewritingdialog.h"
+#include "k3biso9660imagewritingjob.h"
+#include "k3bbinimagewritingjob.h"
+#include "k3bcuefileparser.h"
+#include "k3bclonetocreader.h"
+#include "k3baudiocuefilewritingjob.h"
+#include <k3bclonejob.h>
+
+#include <k3btempdirselectionwidget.h>
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3bburnprogressdialog.h>
+#include <kcutlabel.h>
+#include <k3bstdguiitems.h>
+#include <k3bmd5job.h>
+#include <k3bdatamodewidget.h>
+#include <k3bglobals.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bcore.h>
+#include <k3blistview.h>
+#include <k3biso9660.h>
+#include <k3btoc.h>
+#include <k3btrack.h>
+#include <k3bcdtext.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kurlrequester.h>
+#include <kfiledialog.h>
+#include <kstdguiitem.h>
+#include <kguiitem.h>
+#include <kiconloader.h>
+#include <kconfig.h>
+#include <kio/global.h>
+#include <kurl.h>
+#include <kinputdialog.h>
+#include <kurldrag.h>
+
+#include <qheader.h>
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qptrlist.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qspinbox.h>
+#include <qmap.h>
+#include <qptrqueue.h>
+#include <qpopupmenu.h>
+#include <qclipboard.h>
+
+
+class K3bCdImageWritingDialog::Private
+{
+public:
+ Private()
+ : md5SumItem(0),
+ haveMd5Sum( false ),
+ foundImageType( IMAGE_UNKNOWN ),
+ imageForced( false ) {
+ }
+
+ K3bListViewItem* md5SumItem;
+ QString lastCheckedFile;
+
+ K3bMd5Job* md5Job;
+ bool haveMd5Sum;
+
+ int foundImageType;
+
+ QMap<int,int> imageTypeSelectionMap;
+ QMap<int,int> imageTypeSelectionMapRev;
+ QString imageFile;
+ QString tocFile;
+
+ QTabWidget* optionTabbed;
+
+ QWidget* advancedTab;
+ QWidget* tempPathTab;
+ bool advancedTabVisible;
+ bool tempPathTabVisible;
+
+ bool imageForced;
+};
+
+
+K3bCdImageWritingDialog::K3bCdImageWritingDialog( QWidget* parent, const char* name, bool modal )
+ : K3bInteractionDialog( parent, name,
+ i18n("Burn CD Image"),
+ "iso cue toc",
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "image writing", // config group
+ modal )
+{
+ d = new Private();
+
+ setAcceptDrops( true );
+
+ setupGui();
+
+ d->md5Job = new K3bMd5Job( 0, this );
+ connect( d->md5Job, SIGNAL(finished(bool)),
+ this, SLOT(slotMd5JobFinished(bool)) );
+ connect( d->md5Job, SIGNAL(percent(int)),
+ this, SLOT(slotMd5JobPercent(int)) );
+
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged()),
+ this, SLOT(slotToggleAll()) );
+ connect( m_writerSelectionWidget, SIGNAL(writingAppChanged(int)),
+ this, SLOT(slotToggleAll()) );
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged(K3bDevice::Device*)),
+ m_writingModeWidget, SLOT(setDevice(K3bDevice::Device*)) );
+ connect( m_comboImageType, SIGNAL(activated(int)),
+ this, SLOT(slotToggleAll()) );
+ connect( m_writingModeWidget, SIGNAL(writingModeChanged(int)),
+ this, SLOT(slotToggleAll()) );
+ connect( m_editImagePath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotUpdateImage(const QString&)) );
+ connect( m_checkDummy, SIGNAL(toggled(bool)),
+ this, SLOT(slotToggleAll()) );
+ connect( m_checkCacheImage, SIGNAL(toggled(bool)),
+ this, SLOT(slotToggleAll()) );
+}
+
+
+K3bCdImageWritingDialog::~K3bCdImageWritingDialog()
+{
+ d->md5Job->cancel();
+ delete d;
+}
+
+
+void K3bCdImageWritingDialog::init()
+{
+ if( !d->imageForced ) {
+ // when opening the dialog first the default settings are loaded and afterwards we set the
+ // last written image because that's what most users want
+ KConfig* c = k3bcore->config();
+ c->setGroup( configGroup() );
+ QString image = c->readPathEntry( "last written image" );
+ if( QFile::exists( image ) )
+ m_editImagePath->setURL( image );
+ }
+}
+
+
+void K3bCdImageWritingDialog::setupGui()
+{
+ QWidget* frame = mainWidget();
+
+ // image
+ // -----------------------------------------------------------------------
+ QGroupBox* groupImageUrl = new QGroupBox( 1, Qt::Horizontal, i18n("Image to Burn"), frame );
+ m_editImagePath = new KURLRequester( groupImageUrl );
+ m_editImagePath->setMode( KFile::File|KFile::ExistingOnly );
+ m_editImagePath->setCaption( i18n("Choose Image File") );
+ m_editImagePath->setFilter( i18n("*.iso *.toc *.ISO *.TOC *.cue *.CUE|Image Files")
+ + "\n"
+ + i18n("*.iso *.ISO|ISO9660 Image Files")
+ + "\n"
+ + i18n("*.cue *.CUE|Cue Files")
+ + "\n"
+ + i18n("*.toc *.TOC|Cdrdao TOC Files and Cdrecord Clone Images")
+ + "\n"
+ + i18n("*|All Files") );
+
+ QGroupBox* groupImageType = new QGroupBox( 1, Qt::Horizontal, i18n("Image Type"), frame );
+ m_comboImageType = new QComboBox( groupImageType );
+ m_comboImageType->insertItem( i18n("Auto Detection") );
+ m_comboImageType->insertItem( i18n("ISO9660 Image") );
+ m_comboImageType->insertItem( i18n("Cue/Bin Image") );
+ m_comboImageType->insertItem( i18n("Audio Cue File") );
+ m_comboImageType->insertItem( i18n("Cdrdao TOC File") );
+ m_comboImageType->insertItem( i18n("Cdrecord Clone Image") );
+ d->imageTypeSelectionMap[1] = IMAGE_ISO;
+ d->imageTypeSelectionMap[2] = IMAGE_CUE_BIN;
+ d->imageTypeSelectionMap[3] = IMAGE_AUDIO_CUE;
+ d->imageTypeSelectionMap[4] = IMAGE_CDRDAO_TOC;
+ d->imageTypeSelectionMap[5] = IMAGE_CDRECORD_CLONE;
+ d->imageTypeSelectionMapRev[IMAGE_ISO] = 1;
+ d->imageTypeSelectionMapRev[IMAGE_CUE_BIN] = 2;
+ d->imageTypeSelectionMapRev[IMAGE_AUDIO_CUE] = 3;
+ d->imageTypeSelectionMapRev[IMAGE_CDRDAO_TOC] = 4;
+ d->imageTypeSelectionMapRev[IMAGE_CDRECORD_CLONE] = 5;
+
+
+ // image info
+ // -----------------------------------------------------------------------
+ m_infoView = new K3bListView( frame );
+ m_infoView->addColumn( "key" );
+ m_infoView->addColumn( "value" );
+ m_infoView->header()->hide();
+ m_infoView->setNoItemText( i18n("No image file selected") );
+ m_infoView->setSorting( -1 );
+ m_infoView->setAlternateBackground( QColor() );
+ m_infoView->setFullWidth(true);
+ m_infoView->setSelectionMode( QListView::NoSelection );
+
+ connect( m_infoView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) );
+
+
+ m_writerSelectionWidget = new K3bWriterSelectionWidget( frame );
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_CD );
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY );
+
+ // options
+ // -----------------------------------------------------------------------
+ d->optionTabbed = new QTabWidget( frame );
+
+ QWidget* optionTab = new QWidget( d->optionTabbed );
+ QGridLayout* optionTabLayout = new QGridLayout( optionTab );
+ optionTabLayout->setAlignment( Qt::AlignTop );
+ optionTabLayout->setSpacing( spacingHint() );
+ optionTabLayout->setMargin( marginHint() );
+
+ QGroupBox* writingModeGroup = new QGroupBox( 1, Vertical, i18n("Writing Mode"), optionTab );
+ writingModeGroup->setInsideMargin( marginHint() );
+ m_writingModeWidget = new K3bWritingModeWidget( writingModeGroup );
+
+
+ // copies --------
+ QGroupBox* groupCopies = new QGroupBox( 2, Qt::Horizontal, i18n("Copies"), optionTab );
+ groupCopies->setInsideSpacing( spacingHint() );
+ groupCopies->setInsideMargin( marginHint() );
+ QLabel* pixLabel = new QLabel( groupCopies );
+ pixLabel->setPixmap( SmallIcon( "cdcopy", KIcon::SizeMedium ) );
+ pixLabel->setScaledContents( false );
+ m_spinCopies = new QSpinBox( groupCopies );
+ m_spinCopies->setMinValue( 1 );
+ m_spinCopies->setMaxValue( 999 );
+ // -------- copies
+
+ QGroupBox* optionGroup = new QGroupBox( 3, Vertical, i18n("Settings"), optionTab );
+ optionGroup->setInsideMargin( marginHint() );
+ optionGroup->setInsideSpacing( spacingHint() );
+ m_checkDummy = K3bStdGuiItems::simulateCheckbox( optionGroup );
+ m_checkCacheImage = K3bStdGuiItems::createCacheImageCheckbox( optionGroup );
+ m_checkVerify = K3bStdGuiItems::verifyCheckBox( optionGroup );
+
+ optionTabLayout->addWidget( writingModeGroup, 0, 0 );
+ optionTabLayout->addWidget( groupCopies, 1, 0 );
+ optionTabLayout->addMultiCellWidget( optionGroup, 0, 1, 1, 1 );
+ optionTabLayout->setRowStretch( 1, 1 );
+ optionTabLayout->setColStretch( 1, 1 );
+
+ d->optionTabbed->addTab( optionTab, i18n("Settings") );
+
+
+ // image tab ------------------------------------
+ d->tempPathTab = new QWidget( d->optionTabbed );
+ QGridLayout* imageTabGrid = new QGridLayout( d->tempPathTab );
+ imageTabGrid->setSpacing( spacingHint() );
+ imageTabGrid->setMargin( marginHint() );
+
+ m_tempDirSelectionWidget = new K3bTempDirSelectionWidget( d->tempPathTab );
+
+ imageTabGrid->addWidget( m_tempDirSelectionWidget, 0, 0 );
+
+ d->optionTabbed->addTab( d->tempPathTab, i18n("&Image") );
+ d->tempPathTabVisible = true;
+ // -------------------------------------------------------------
+
+
+ // advanced ---------------------------------
+ d->advancedTab = new QWidget( d->optionTabbed );
+ QGridLayout* advancedTabLayout = new QGridLayout( d->advancedTab );
+ advancedTabLayout->setAlignment( Qt::AlignTop );
+ advancedTabLayout->setSpacing( spacingHint() );
+ advancedTabLayout->setMargin( marginHint() );
+
+ m_dataModeWidget = new K3bDataModeWidget( d->advancedTab );
+ m_checkNoFix = K3bStdGuiItems::startMultisessionCheckBox( d->advancedTab );
+
+ advancedTabLayout->addWidget( new QLabel( i18n("Data mode:"), d->advancedTab ), 0, 0 );
+ advancedTabLayout->addWidget( m_dataModeWidget, 0, 1 );
+ advancedTabLayout->addMultiCellWidget( m_checkNoFix, 1, 1, 0, 2 );
+ advancedTabLayout->setRowStretch( 2, 1 );
+ advancedTabLayout->setColStretch( 2, 1 );
+
+ d->optionTabbed->addTab( d->advancedTab, i18n("Advanced") );
+ d->advancedTabVisible = true;
+ // -----------------------------------------------------------------------
+
+
+
+
+ QGridLayout* grid = new QGridLayout( frame );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( 0 );
+
+ grid->addWidget( groupImageUrl, 0, 0 );
+ grid->addWidget( groupImageType, 0, 1 );
+ grid->addMultiCellWidget( m_infoView, 1, 1, 0, 1 );
+ grid->addMultiCellWidget( m_writerSelectionWidget, 2, 2, 0, 1 );
+ grid->addMultiCellWidget( d->optionTabbed, 3, 3, 0, 1 );
+
+ grid->setRowStretch( 1, 1 );
+}
+
+
+void K3bCdImageWritingDialog::slotStartClicked()
+{
+ // FIXME: this results in a call to slotMd5JobFinished
+ // if this dialog is deleted becasue it is not opened with exec(false)
+ // this results in a crash.
+ // For now this is not a problem in K3b since the dialog is not deleted
+ // when hiding (due to the exec(false) call in k3b.cpp
+ d->md5Job->cancel();
+
+ // save the path
+ KConfig* c = k3bcore->config();
+ c->setGroup( configGroup() );
+ c->writePathEntry( "last written image", imagePath() );
+
+ if( d->imageFile.isEmpty() )
+ d->imageFile = imagePath();
+ if( d->tocFile.isEmpty() )
+ d->tocFile = imagePath();
+
+ // create a progresswidget
+ K3bBurnProgressDialog dlg( kapp->mainWidget(), "burnProgress", true );
+
+ // create the job
+ K3bBurnJob* job = 0;
+ switch( currentImageType() ) {
+ case IMAGE_CDRECORD_CLONE:
+ {
+ K3bCloneJob* _job = new K3bCloneJob( &dlg, this );
+ _job->setWriterDevice( m_writerSelectionWidget->writerDevice() );
+ _job->setImagePath( d->imageFile );
+ _job->setSimulate( m_checkDummy->isChecked() );
+ _job->setWriteSpeed( m_writerSelectionWidget->writerSpeed() );
+ _job->setCopies( m_checkDummy->isChecked() ? 1 : m_spinCopies->value() );
+ _job->setOnlyBurnExistingImage( true );
+
+ job = _job;
+ }
+ break;
+
+ case IMAGE_AUDIO_CUE:
+ {
+ K3bAudioCueFileWritingJob* job_ = new K3bAudioCueFileWritingJob( &dlg, this );
+
+ job_->setBurnDevice( m_writerSelectionWidget->writerDevice() );
+ job_->setSpeed( m_writerSelectionWidget->writerSpeed() );
+ job_->setSimulate( m_checkDummy->isChecked() );
+ job_->setWritingMode( m_writingModeWidget->writingMode() );
+ job_->setCueFile( d->tocFile );
+ job_->setCopies( m_checkDummy->isChecked() ? 1 : m_spinCopies->value() );
+ job_->setOnTheFly( !m_checkCacheImage->isChecked() );
+ job_->setTempDir( m_tempDirSelectionWidget->tempPath() );
+
+ job = job_;
+ }
+ break;
+
+ case IMAGE_CUE_BIN:
+ // for now the K3bBinImageWritingJob decides if it's a toc or a cue file
+ case IMAGE_CDRDAO_TOC:
+ {
+ K3bBinImageWritingJob* job_ = new K3bBinImageWritingJob( &dlg, this );
+
+ job_->setWriter( m_writerSelectionWidget->writerDevice() );
+ job_->setSpeed( m_writerSelectionWidget->writerSpeed() );
+ job_->setTocFile( d->tocFile );
+ job_->setSimulate(m_checkDummy->isChecked());
+ job_->setMulti( false /*m_checkNoFix->isChecked()*/ );
+ job_->setCopies( m_checkDummy->isChecked() ? 1 : m_spinCopies->value() );
+
+ job = job_;
+ }
+ break;
+
+ case IMAGE_ISO:
+ {
+ K3bIso9660 isoFs( d->imageFile );
+ if( isoFs.open() ) {
+ if( K3b::filesize( KURL::fromPathOrURL(d->imageFile) ) < (KIO::filesize_t)(isoFs.primaryDescriptor().volumeSpaceSize*2048) ) {
+ if( KMessageBox::questionYesNo( this,
+ i18n("<p>This image has an invalid file size."
+ "If it has been downloaded make sure the download is complete."
+ "<p>Only continue if you know what you are doing."),
+ i18n("Warning"),
+ i18n("Continue"),
+ i18n("Cancel") ) == KMessageBox::No )
+ return;
+ }
+ }
+
+ K3bIso9660ImageWritingJob* job_ = new K3bIso9660ImageWritingJob( &dlg );
+
+ job_->setBurnDevice( m_writerSelectionWidget->writerDevice() );
+ job_->setSpeed( m_writerSelectionWidget->writerSpeed() );
+ job_->setSimulate( m_checkDummy->isChecked() );
+ job_->setWritingMode( m_writingModeWidget->writingMode() );
+ job_->setVerifyData( m_checkVerify->isChecked() );
+ job_->setNoFix( m_checkNoFix->isChecked() );
+ job_->setDataMode( m_dataModeWidget->dataMode() );
+ job_->setImagePath( d->imageFile );
+ job_->setCopies( m_checkDummy->isChecked() ? 1 : m_spinCopies->value() );
+
+ job = job_;
+ }
+ break;
+
+ default:
+ kdDebug() << "(K3bCdImageWritingDialog) this should really not happen!" << endl;
+ break;
+ }
+
+ if( job ) {
+ job->setWritingApp( m_writerSelectionWidget->writingApp() );
+
+ if( !exitLoopOnHide() )
+ hide();
+
+ dlg.startJob(job);
+
+ delete job;
+
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "keep action dialogs open", false ) &&
+ !exitLoopOnHide() )
+ show();
+ else
+ close();
+ }
+}
+
+
+void K3bCdImageWritingDialog::slotUpdateImage( const QString& )
+{
+ QString path = imagePath();
+
+ // check the image types
+
+ d->haveMd5Sum = false;
+ d->md5Job->cancel();
+ m_infoView->clear();
+ m_infoView->header()->resizeSection( 0, 20 );
+ d->md5SumItem = 0;
+ d->foundImageType = IMAGE_UNKNOWN;
+ d->tocFile.truncate(0);
+ d->imageFile.truncate(0);
+
+ QFileInfo info( path );
+ if( info.isFile() ) {
+
+ // ------------------------------------------------
+ // Test for iso9660 image
+ // ------------------------------------------------
+ K3bIso9660 isoF( path );
+ if( isoF.open() ) {
+#ifdef K3B_DEBUG
+ isoF.debug();
+#endif
+
+ createIso9660InfoItems( &isoF );
+ isoF.close();
+ calculateMd5Sum( path );
+
+ d->foundImageType = IMAGE_ISO;
+ d->imageFile = path;
+ }
+
+ if( d->foundImageType == IMAGE_UNKNOWN ) {
+
+ // check for cdrecord clone image
+ // try both path and path.toc as tocfiles
+ K3bCloneTocReader cr;
+
+ if( path.right(4) == ".toc" ) {
+ cr.openFile( path );
+ if( cr.isValid() ) {
+ d->tocFile = path;
+ d->imageFile = cr.imageFilename();
+ }
+ }
+ if( d->imageFile.isEmpty() ) {
+ cr.openFile( path + ".toc" );
+ if( cr.isValid() ) {
+ d->tocFile = cr.filename();
+ d->imageFile = cr.imageFilename();
+ }
+ }
+
+ if( !d->imageFile.isEmpty() ) {
+ // we have a cdrecord clone image
+ createCdrecordCloneItems( d->tocFile, d->imageFile );
+ calculateMd5Sum( d->imageFile );
+
+ d->foundImageType = IMAGE_CDRECORD_CLONE;
+ }
+ }
+
+ if( d->foundImageType == IMAGE_UNKNOWN ) {
+
+ // check for cue/bin stuff
+ // once again we try both path and path.cue
+ K3bCueFileParser cp;
+
+ if( path.right(4).lower() == ".cue" )
+ cp.openFile( path );
+ else if( path.right(4).lower() == ".bin" )
+ cp.openFile( path.left( path.length()-3) + "cue" );
+
+ if( cp.isValid() ) {
+ d->tocFile = cp.filename();
+ d->imageFile = cp.imageFilename();
+ }
+
+ if( d->imageFile.isEmpty() ) {
+ cp.openFile( path + ".cue" );
+ if( cp.isValid() ) {
+ d->tocFile = cp.filename();
+ d->imageFile = cp.imageFilename();
+ }
+ }
+
+ if( !d->imageFile.isEmpty() ) {
+ // we have a cue file
+ if( cp.toc().contentType() == K3bDevice::AUDIO ) {
+ d->foundImageType = IMAGE_AUDIO_CUE;
+ createAudioCueItems( cp );
+ }
+ else {
+ d->foundImageType = IMAGE_CUE_BIN; // we cannot be sure if writing will work... :(
+ createCueBinItems( d->tocFile, d->imageFile );
+ calculateMd5Sum( d->imageFile );
+ }
+ }
+ }
+
+ if( d->foundImageType == IMAGE_UNKNOWN ) {
+ // TODO: check for cdrdao tocfile
+ }
+
+
+
+ if( d->foundImageType == IMAGE_UNKNOWN ) {
+ K3bListViewItem* item = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("Seems not to be a usable image") );
+ item->setForegroundColor( 0, Qt::red );
+ item->setPixmap( 0, SmallIcon( "stop") );
+ }
+ }
+ else {
+ K3bListViewItem* item = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("File not found") );
+ item->setForegroundColor( 0, Qt::red );
+ item->setPixmap( 0, SmallIcon( "stop") );
+ }
+
+ slotToggleAll();
+}
+
+
+void K3bCdImageWritingDialog::createIso9660InfoItems( K3bIso9660* isoF )
+{
+ K3bListViewItem* isoRootItem = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("Detected:"),
+ i18n("Iso9660 image") );
+ isoRootItem->setForegroundColor( 0, palette().disabled().foreground() );
+ isoRootItem->setPixmap( 0, SmallIcon( "cdimage") );
+
+ KIO::filesize_t size = K3b::filesize( KURL::fromPathOrURL(isoF->fileName()) );
+ K3bListViewItem* item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(),
+ i18n("Filesize:"),
+ KIO::convertSize( size ) );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("System Id:"),
+ isoF->primaryDescriptor().systemId.isEmpty()
+ ? QString("-")
+ : isoF->primaryDescriptor().systemId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Volume Id:"),
+ isoF->primaryDescriptor().volumeId.isEmpty()
+ ? QString("-")
+ : isoF->primaryDescriptor().volumeId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Volume Set Id:"),
+ isoF->primaryDescriptor().volumeSetId.isEmpty()
+ ? QString("-")
+ : isoF->primaryDescriptor().volumeSetId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Publisher Id:"),
+ isoF->primaryDescriptor().publisherId.isEmpty()
+ ? QString("-")
+ : isoF->primaryDescriptor().publisherId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Preparer Id:"),
+ isoF->primaryDescriptor().preparerId.isEmpty()
+ ? QString("-") : isoF->primaryDescriptor().preparerId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Application Id:"),
+ isoF->primaryDescriptor().applicationId.isEmpty()
+ ? QString("-")
+ : isoF->primaryDescriptor().applicationId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ isoRootItem->setOpen( true );
+}
+
+
+void K3bCdImageWritingDialog::createCdrecordCloneItems( const QString& tocFile, const QString& imageFile )
+{
+ K3bListViewItem* isoRootItem = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("Detected:"),
+ i18n("Cdrecord clone image") );
+ isoRootItem->setForegroundColor( 0, palette().disabled().foreground() );
+ isoRootItem->setPixmap( 0, SmallIcon( "cdimage") );
+
+ K3bListViewItem* item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(),
+ i18n("Filesize:"), KIO::convertSize( K3b::filesize(KURL::fromPathOrURL(imageFile)) ) );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Image file:"),
+ imageFile );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("TOC file:"),
+ tocFile );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ isoRootItem->setOpen( true );
+}
+
+
+void K3bCdImageWritingDialog::createCueBinItems( const QString& cueFile, const QString& imageFile )
+{
+ K3bListViewItem* isoRootItem = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("Detected:"),
+ i18n("Cue/bin image") );
+ isoRootItem->setForegroundColor( 0, palette().disabled().foreground() );
+ isoRootItem->setPixmap( 0, SmallIcon( "cdimage") );
+
+ K3bListViewItem* item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(),
+ i18n("Filesize:"), KIO::convertSize( K3b::filesize(KURL::fromPathOrURL(imageFile)) ) );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Image file:"),
+ imageFile );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Cue file:"),
+ cueFile );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ isoRootItem->setOpen( true );
+}
+
+
+void K3bCdImageWritingDialog::createAudioCueItems( const K3bCueFileParser& cp )
+{
+ K3bListViewItem* rootItem = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("Detected:"),
+ i18n("Audio Cue Image") );
+ rootItem->setForegroundColor( 0, palette().disabled().foreground() );
+ rootItem->setPixmap( 0, SmallIcon( "sound") );
+
+ K3bListViewItem* trackParent = new K3bListViewItem( rootItem,
+ i18n("%n track", "%n tracks", cp.toc().count() ),
+ cp.toc().length().toString() );
+ if( !cp.cdText().isEmpty() )
+ trackParent->setText( 1,
+ QString("%1 (%2 - %3)")
+ .arg(trackParent->text(1))
+ .arg(cp.cdText().performer())
+ .arg(cp.cdText().title()) );
+
+ unsigned int i = 1;
+ for( K3bDevice::Toc::const_iterator it = cp.toc().begin();
+ it != cp.toc().end(); ++it ) {
+
+ K3bListViewItem* trackItem =
+ new K3bListViewItem( trackParent, m_infoView->lastItem(),
+ i18n("Track") + " " + QString::number(i).rightJustify( 2, '0' ),
+ " " + ( i < cp.toc().count()
+ ? (*it).length().toString()
+ : QString("??:??:??") ) );
+
+ if( !cp.cdText().isEmpty() && !cp.cdText()[i-1].isEmpty() )
+ trackItem->setText( 1,
+ QString("%1 (%2 - %3)")
+ .arg(trackItem->text(1))
+ .arg(cp.cdText()[i-1].performer())
+ .arg(cp.cdText()[i-1].title()) );
+
+ ++i;
+ }
+
+ rootItem->setOpen( true );
+ trackParent->setOpen( true );
+}
+
+
+void K3bCdImageWritingDialog::toggleAll()
+{
+ // enable the Write-Button if we found a valid image or the user forced an image type
+ setButtonEnabled( START_BUTTON, m_writerSelectionWidget->writerDevice()
+ && currentImageType() != IMAGE_UNKNOWN
+ && QFile::exists( imagePath() ) );
+
+ // cdrecord clone and cue both need DAO
+ if( m_writerSelectionWidget->writingApp() != K3b::CDRDAO
+ && ( currentImageType() == IMAGE_ISO ||
+ currentImageType() == IMAGE_AUDIO_CUE ) )
+ m_writingModeWidget->setSupportedModes( K3b::TAO|K3b::DAO|K3b::RAW ); // stuff supported by cdrecord
+ else
+ m_writingModeWidget->setSupportedModes( K3b::DAO );
+
+ // some stuff is only available for iso images
+ if( currentImageType() == IMAGE_ISO ) {
+ m_checkVerify->show();
+ if( !d->advancedTabVisible )
+ d->optionTabbed->addTab( d->advancedTab, i18n("Advanced") );
+ d->advancedTabVisible = true;
+ if( m_checkDummy->isChecked() ) {
+ m_checkVerify->setEnabled( false );
+ m_checkVerify->setChecked( false );
+ }
+ else
+ m_checkVerify->setEnabled( true );
+ }
+ else {
+ if( d->advancedTabVisible )
+ d->optionTabbed->removePage( d->advancedTab );
+ d->advancedTabVisible = false;
+ m_checkVerify->hide();
+ }
+
+ // and some other stuff only makes sense for audio cues
+ if( currentImageType() == IMAGE_AUDIO_CUE ) {
+ if( !d->tempPathTabVisible )
+ d->optionTabbed->addTab( d->tempPathTab, i18n("&Image") );
+ d->tempPathTabVisible = true;
+ m_tempDirSelectionWidget->setDisabled( !m_checkCacheImage->isChecked() );
+ }
+ else {
+ if( d->tempPathTabVisible )
+ d->optionTabbed->removePage( d->tempPathTab );
+ d->tempPathTabVisible = false;
+ }
+ m_checkCacheImage->setShown( currentImageType() == IMAGE_AUDIO_CUE );
+
+ m_spinCopies->setEnabled( !m_checkDummy->isChecked() );
+
+ switch( currentImageType() ) {
+ case IMAGE_CDRDAO_TOC:
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::CDRDAO );
+ break;
+ case IMAGE_CDRECORD_CLONE:
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::CDRECORD );
+ break;
+ default:
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::CDRECORD|K3b::CDRDAO );
+ break;
+ }
+
+ K3bListViewItem* item = dynamic_cast<K3bListViewItem*>(m_infoView->firstChild());
+ if( item )
+ item->setForegroundColor( 1,
+ currentImageType() != d->foundImageType
+ ? Qt::red
+ : m_infoView->colorGroup().foreground() );
+}
+
+
+void K3bCdImageWritingDialog::setImage( const KURL& url )
+{
+ d->imageForced = true;
+#if KDE_IS_VERSION(3,4,0)
+ m_editImagePath->setKURL( url );
+#else
+ m_editImagePath->setURL( url.path() );
+#endif
+}
+
+
+void K3bCdImageWritingDialog::calculateMd5Sum( const QString& file )
+{
+ d->haveMd5Sum = false;
+
+ if( !d->md5SumItem )
+ d->md5SumItem = new K3bListViewItem( m_infoView, m_infoView->firstChild() );
+
+ d->md5SumItem->setText( 0, i18n("Md5 Sum:") );
+ d->md5SumItem->setForegroundColor( 0, palette().disabled().foreground() );
+ d->md5SumItem->setProgress( 1, 0 );
+ d->md5SumItem->setPixmap( 0, SmallIcon( "exec") );
+
+ if( file != d->lastCheckedFile ) {
+ d->lastCheckedFile = file;
+ d->md5Job->setFile( file );
+ d->md5Job->start();
+ }
+ else
+ slotMd5JobFinished( true );
+}
+
+
+void K3bCdImageWritingDialog::slotMd5JobPercent( int p )
+{
+ d->md5SumItem->setProgress( 1, p );
+}
+
+
+void K3bCdImageWritingDialog::slotMd5JobFinished( bool success )
+{
+ if( success ) {
+ d->md5SumItem->setText( 1, d->md5Job->hexDigest() );
+ d->haveMd5Sum = true;
+ }
+ else {
+ d->md5SumItem->setForegroundColor( 1, Qt::red );
+ if( d->md5Job->hasBeenCanceled() )
+ d->md5SumItem->setText( 1, i18n("Calculation cancelled") );
+ else
+ d->md5SumItem->setText( 1, i18n("Calculation failed") );
+ d->md5SumItem->setPixmap( 0, SmallIcon( "stop") );
+ d->lastCheckedFile.truncate(0);
+ }
+
+ d->md5SumItem->setDisplayProgressBar( 1, false );
+}
+
+
+void K3bCdImageWritingDialog::slotContextMenu( KListView*, QListViewItem*, const QPoint& pos )
+{
+ if( !d->haveMd5Sum )
+ return;
+
+ QPopupMenu popup;
+ int copyItem = popup.insertItem( i18n("Copy checksum to clipboard") );
+ int compareItem = popup.insertItem( i18n("Compare checksum...") );
+
+ int r = popup.exec( pos );
+
+ if( r == compareItem ) {
+ bool ok;
+ QString md5sumToCompare = KInputDialog::getText( i18n("MD5 Sum Check"),
+ i18n("Please insert the MD5 Sum to compare:"),
+ QString::null,
+ &ok,
+ this );
+ if( ok ) {
+ if( md5sumToCompare.lower().utf8() == d->md5Job->hexDigest().lower() )
+ KMessageBox::information( this, i18n("The MD5 Sum of %1 equals the specified.").arg(imagePath()),
+ i18n("MD5 Sums Equal") );
+ else
+ KMessageBox::sorry( this, i18n("The MD5 Sum of %1 differs from the specified.").arg(imagePath()),
+ i18n("MD5 Sums Differ") );
+ }
+ }
+ else if( r == copyItem ) {
+ QApplication::clipboard()->setText( d->md5Job->hexDigest().lower(), QClipboard::Clipboard );
+ }
+}
+
+
+void K3bCdImageWritingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_writingModeWidget->loadConfig( c );
+ m_checkDummy->setChecked( c->readBoolEntry("simulate", false ) );
+ m_checkNoFix->setChecked( c->readBoolEntry("multisession", false ) );
+ m_checkCacheImage->setChecked( !c->readBoolEntry("on_the_fly", true ) );
+
+ m_dataModeWidget->loadConfig(c);
+
+ m_spinCopies->setValue( c->readNumEntry( "copies", 1 ) );
+
+ m_checkVerify->setChecked( c->readBoolEntry( "verify_data", false ) );
+
+ m_writerSelectionWidget->loadConfig( c );
+
+ if( !d->imageForced ) {
+ QString image = c->readPathEntry( "image path", c->readPathEntry( "last written image" ) );
+ if( QFile::exists( image ) )
+ m_editImagePath->setURL( image );
+ }
+
+ QString imageType = c->readEntry( "image type", "auto" );
+ int x = 0;
+ if( imageType == "iso9660" )
+ x = d->imageTypeSelectionMapRev[IMAGE_ISO];
+ else if( imageType == "cue-bin" )
+ x = d->imageTypeSelectionMapRev[IMAGE_CUE_BIN];
+ else if( imageType == "audio-cue" )
+ x = d->imageTypeSelectionMapRev[IMAGE_AUDIO_CUE];
+ else if( imageType == "cdrecord-clone" )
+ x = d->imageTypeSelectionMapRev[IMAGE_CDRECORD_CLONE];
+ else if( imageType == "cdrdao-toc" )
+ x = d->imageTypeSelectionMapRev[IMAGE_CDRDAO_TOC];
+
+ m_comboImageType->setCurrentItem( x );
+
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() );
+
+ slotToggleAll();
+}
+
+
+void K3bCdImageWritingDialog::saveUserDefaults( KConfigBase* c )
+{
+ m_writingModeWidget->saveConfig( c ),
+ c->writeEntry( "simulate", m_checkDummy->isChecked() );
+ c->writeEntry( "multisession", m_checkNoFix->isChecked() );
+ c->writeEntry( "on_the_fly", !m_checkCacheImage->isChecked() );
+ m_dataModeWidget->saveConfig(c);
+
+ c->writeEntry( "verify_data", m_checkVerify->isChecked() );
+
+ m_writerSelectionWidget->saveConfig( c );
+
+ c->writePathEntry( "image path", imagePath() );
+
+ c->writeEntry( "copies", m_spinCopies->value() );
+
+ QString imageType;
+ if( m_comboImageType->currentItem() == 0 )
+ imageType = "auto";
+ else {
+ switch( d->imageTypeSelectionMap[m_comboImageType->currentItem()] ) {
+ case IMAGE_ISO:
+ imageType = "iso9660";
+ break;
+ case IMAGE_CUE_BIN:
+ imageType = "cue-bin";
+ break;
+ case IMAGE_AUDIO_CUE:
+ imageType = "audio-cue";
+ break;
+ case IMAGE_CDRECORD_CLONE:
+ imageType = "cdrecord-clone";
+ break;
+ case IMAGE_CDRDAO_TOC:
+ imageType = "cdrdao-toc";
+ break;
+ }
+ }
+ c->writeEntry( "image type", imageType );
+
+ if( m_tempDirSelectionWidget->isEnabled() )
+ m_tempDirSelectionWidget->saveConfig();
+}
+
+void K3bCdImageWritingDialog::loadK3bDefaults()
+{
+ m_writerSelectionWidget->loadDefaults();
+ m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO );
+ m_checkDummy->setChecked( false );
+ m_checkVerify->setChecked( false );
+ m_checkNoFix->setChecked( false );
+ m_checkCacheImage->setChecked( false );
+ m_dataModeWidget->setDataMode( K3b::DATA_MODE_AUTO );
+ m_comboImageType->setCurrentItem(0);
+ m_spinCopies->setValue( 1 );
+
+ slotToggleAll();
+}
+
+
+int K3bCdImageWritingDialog::currentImageType()
+{
+ if( m_comboImageType->currentItem() == 0 )
+ return d->foundImageType;
+ else
+ return d->imageTypeSelectionMap[m_comboImageType->currentItem()];
+}
+
+
+QString K3bCdImageWritingDialog::imagePath() const
+{
+ return K3b::convertToLocalUrl( KURL::fromPathOrURL( m_editImagePath->url() ) ).path();
+}
+
+
+void K3bCdImageWritingDialog::dragEnterEvent( QDragEnterEvent* e )
+{
+ e->accept( KURLDrag::canDecode(e) );
+}
+
+
+void K3bCdImageWritingDialog::dropEvent( QDropEvent* e )
+{
+ KURL::List urls;
+ KURLDrag::decode( e, urls );
+#if KDE_IS_VERSION(3,4,0)
+ m_editImagePath->setKURL( urls.first() );
+#else
+ m_editImagePath->setURL( urls.first().path() );
+#endif
+}
+
+#include "k3bcdimagewritingdialog.moc"
diff --git a/src/misc/k3bcdimagewritingdialog.h b/src/misc/k3bcdimagewritingdialog.h
new file mode 100644
index 0000000..143f023
--- /dev/null
+++ b/src/misc/k3bcdimagewritingdialog.h
@@ -0,0 +1,116 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_CDIMAGEWRITINGDIALOG_H_
+#define _K3B_CDIMAGEWRITINGDIALOG_H_
+
+#include <k3binteractiondialog.h>
+
+
+class QCheckBox;
+class K3bWriterSelectionWidget;
+class QLabel;
+class KURL;
+class KActiveLabel;
+class KProgress;
+class K3bDataModeWidget;
+class K3bWritingModeWidget;
+class K3bTempDirSelectionWidget;
+class KURLRequester;
+class K3bListView;
+class QSpinBox;
+class QComboBox;
+class K3bIso9660;
+class K3bCueFileParser;
+class QDragEnterEvent;
+class QDropEvent;
+class KListView;
+class QListViewItem;
+class QPoint;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bCdImageWritingDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bCdImageWritingDialog( QWidget* = 0, const char* = 0, bool = true );
+ ~K3bCdImageWritingDialog();
+
+ void setImage( const KURL& url );
+
+ protected slots:
+ void slotStartClicked();
+
+ void slotMd5JobPercent( int );
+ void slotMd5JobFinished( bool );
+ void slotContextMenu( KListView*, QListViewItem*, const QPoint& pos );
+
+ void slotUpdateImage( const QString& );
+
+ protected:
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void loadK3bDefaults();
+
+ void calculateMd5Sum( const QString& );
+ void dragEnterEvent( QDragEnterEvent* );
+ void dropEvent( QDropEvent* );
+
+ void init();
+
+ void toggleAll();
+
+ private:
+ enum {
+ IMAGE_UNKNOWN,
+ IMAGE_ISO,
+ IMAGE_CUE_BIN,
+ IMAGE_AUDIO_CUE,
+ IMAGE_CDRDAO_TOC,
+ IMAGE_CDRECORD_CLONE };
+
+ void setupGui();
+ void createIso9660InfoItems( K3bIso9660* );
+ void createCdrecordCloneItems( const QString&, const QString& );
+ void createCueBinItems( const QString&, const QString& );
+ void createAudioCueItems( const K3bCueFileParser& cp );
+ int currentImageType();
+ QString imagePath() const;
+
+ K3bWriterSelectionWidget* m_writerSelectionWidget;
+ QCheckBox* m_checkDummy;
+ QCheckBox* m_checkNoFix;
+ QCheckBox* m_checkCacheImage;
+ QCheckBox* m_checkVerify;
+ K3bDataModeWidget* m_dataModeWidget;
+ K3bWritingModeWidget* m_writingModeWidget;
+ QSpinBox* m_spinCopies;
+
+ KURLRequester* m_editImagePath;
+ QComboBox* m_comboImageType;
+
+ K3bListView* m_infoView;
+ K3bTempDirSelectionWidget* m_tempDirSelectionWidget;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/misc/k3bdvdcopydialog.cpp b/src/misc/k3bdvdcopydialog.cpp
new file mode 100644
index 0000000..f93abba
--- /dev/null
+++ b/src/misc/k3bdvdcopydialog.cpp
@@ -0,0 +1,455 @@
+/*
+ *
+ * $Id: k3bdvdcopydialog.cpp 733470 2007-11-06 12:10:29Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdvdcopydialog.h"
+#include "k3bdvdcopyjob.h"
+
+#include <k3btempdirselectionwidget.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3bglobals.h>
+#include <k3bstdguiitems.h>
+#include <k3bmediaselectioncombobox.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bburnprogressdialog.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bthememanager.h>
+#include <k3bapplication.h>
+#include <k3bmediacache.h>
+#include <k3biso9660.h>
+
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qtabwidget.h>
+#include <qspinbox.h>
+#include <qptrlist.h>
+#include <qfile.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qhbox.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kglobal.h>
+
+
+
+K3bDvdCopyDialog::K3bDvdCopyDialog( QWidget* parent, const char* name, bool modal )
+ : K3bInteractionDialog( parent, name,
+ i18n("DVD Copy"),
+ i18n("No video transcoding!"),
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "default dvd copy settings",
+ modal )
+{
+ QWidget* w = mainWidget();
+
+ //
+ // Source group
+ // //////////////////////////////////////////////////////////////////////////
+ QGroupBox* groupSource = new QGroupBox( 1, Qt::Vertical, i18n("Source Medium"), w );
+ groupSource->setInsideSpacing( spacingHint() );
+ groupSource->setInsideMargin( marginHint() );
+ m_comboSourceDevice = new K3bMediaSelectionComboBox( groupSource );
+ m_comboSourceDevice->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD|K3bDevice::MEDIA_DVD_ROM );
+ m_comboSourceDevice->setWantedMediumState( K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE );
+ // //////////////////////////////////////////////////////////////////////////
+
+ //
+ // Writer group
+ // //////////////////////////////////////////////////////////////////////////
+ m_writerSelectionWidget = new K3bWriterSelectionWidget( w );
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::GROWISOFS );
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD );
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY );
+ // //////////////////////////////////////////////////////////////////////////
+
+ //
+ // Option tab
+ // //////////////////////////////////////////////////////////////////////////
+ QTabWidget* tabWidget = new QTabWidget( w );
+
+ // option tab --------------------
+ QWidget* optionTab = new QWidget( tabWidget );
+ QGridLayout* optionTabGrid = new QGridLayout( optionTab );
+ optionTabGrid->setSpacing( spacingHint() );
+ optionTabGrid->setMargin( marginHint() );
+
+ QGroupBox* groupWritingMode = new QGroupBox( 1, Qt::Vertical, i18n("Writing Mode"), optionTab );
+ groupWritingMode->setInsideMargin( marginHint() );
+ m_writingModeWidget = new K3bWritingModeWidget( groupWritingMode );
+
+ QGroupBox* groupOptions = new QGroupBox( 5, Qt::Vertical, i18n("Settings"), optionTab );
+ groupOptions->setInsideSpacing( spacingHint() );
+ groupOptions->setInsideMargin( marginHint() );
+ m_checkSimulate = K3bStdGuiItems::simulateCheckbox( groupOptions );
+ m_checkCacheImage = K3bStdGuiItems::createCacheImageCheckbox( groupOptions );
+ m_checkOnlyCreateImage = K3bStdGuiItems::onlyCreateImagesCheckbox( groupOptions );
+ m_checkDeleteImages = K3bStdGuiItems::removeImagesCheckbox( groupOptions );
+ m_checkVerifyData = K3bStdGuiItems::verifyCheckBox( groupOptions );
+
+ QGroupBox* groupCopies = new QGroupBox( 2, Qt::Horizontal, i18n("Copies"), optionTab );
+ groupCopies->setInsideSpacing( spacingHint() );
+ groupCopies->setInsideMargin( marginHint() );
+ QLabel* pixLabel = new QLabel( groupCopies );
+ pixLabel->setPixmap( SmallIcon( "cdcopy", KIcon::SizeMedium ) );
+ pixLabel->setScaledContents( false );
+ m_spinCopies = new QSpinBox( groupCopies );
+ m_spinCopies->setMinValue( 1 );
+ m_spinCopies->setMaxValue( 999 );
+
+ optionTabGrid->addWidget( groupWritingMode, 0, 0 );
+ optionTabGrid->addMultiCellWidget( groupOptions, 0, 1, 1, 1 );
+ optionTabGrid->addWidget( groupCopies, 1, 0 );
+ optionTabGrid->setRowStretch( 1, 1 );
+ optionTabGrid->setColStretch( 1, 1 );
+
+ tabWidget->addTab( optionTab, i18n("&Options") );
+
+
+ //
+ // Image tab
+ // //////////////////////////////////////////////////////////////////////////
+ QWidget* imageTab = new QWidget( tabWidget );
+ QGridLayout* imageTabGrid = new QGridLayout( imageTab );
+ imageTabGrid->setSpacing( spacingHint() );
+ imageTabGrid->setMargin( marginHint() );
+
+ m_tempDirSelectionWidget = new K3bTempDirSelectionWidget( imageTab );
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+
+ imageTabGrid->addWidget( m_tempDirSelectionWidget, 0, 0 );
+
+ tabWidget->addTab( imageTab, i18n("&Image") );
+
+
+ //
+ // advanced tab ------------------
+ // //////////////////////////////////////////////////////////////////////////
+ QWidget* advancedTab = new QWidget( tabWidget );
+ QGridLayout* advancedTabGrid = new QGridLayout( advancedTab );
+ advancedTabGrid->setSpacing( spacingHint() );
+ advancedTabGrid->setMargin( marginHint() );
+
+ QGroupBox* groupGeneral = new QGroupBox( 2, Qt::Vertical, i18n("General"), advancedTab );
+ groupGeneral->setInsideSpacing( spacingHint() );
+ groupGeneral->setInsideMargin( marginHint() );
+ QHBox* box = new QHBox( groupGeneral );
+ box->setSpacing( spacingHint() );
+ box->setStretchFactor( new QLabel( i18n("Read retries:"), box ), 1 );
+ m_spinRetries = new QSpinBox( 1, 128, 1, box );
+ m_checkIgnoreReadErrors = new QCheckBox( i18n("Ignore read errors"), groupGeneral );
+
+ advancedTabGrid->addWidget( groupGeneral, 0, 0 );
+
+ tabWidget->addTab( advancedTab, i18n("&Advanced") );
+ // //////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // setup layout
+ // //////////////////////////////////////////////////////////////////////////
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setMargin( 0 );
+ grid->setSpacing( spacingHint() );
+
+ grid->addWidget( groupSource, 0, 0 );
+ grid->addWidget( m_writerSelectionWidget, 1, 0 );
+ grid->addWidget( tabWidget, 2, 0 );
+ grid->setRowStretch( 2, 1 );
+ // //////////////////////////////////////////////////////////////////////////
+
+
+ // tab order
+ setTabOrder( m_writingModeWidget, m_spinCopies );
+ setTabOrder( m_spinCopies, groupOptions );
+
+
+ //
+ // setup connections
+ // //////////////////////////////////////////////////////////////////////////
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged()), this, SLOT(slotToggleAll()) );
+ connect( m_comboSourceDevice, SIGNAL(selectionChanged(K3bDevice::Device*)), this, SLOT(slotToggleAll()) );
+ connect( m_comboSourceDevice, SIGNAL(selectionChanged(K3bDevice::Device*)),
+ this, SLOT(slotSourceMediumChanged(K3bDevice::Device*)) );
+ connect( m_checkSimulate, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_checkCacheImage, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_checkOnlyCreateImage, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_writingModeWidget, SIGNAL(writingModeChanged(int)), this, SLOT(slotToggleAll()) );
+
+ QToolTip::add( m_checkIgnoreReadErrors, i18n("Skip unreadable sectors") );
+ QWhatsThis::add( m_checkIgnoreReadErrors, i18n("<p>If this option is checked and K3b is not able to read a sector from the "
+ "source CD/DVD it will be replaced with zeros on the resulting copy.") );
+}
+
+
+K3bDvdCopyDialog::~K3bDvdCopyDialog()
+{
+}
+
+
+void K3bDvdCopyDialog::init()
+{
+ slotSourceMediumChanged( m_comboSourceDevice->selectedDevice() );
+}
+
+
+void K3bDvdCopyDialog::setReadingDevice( K3bDevice::Device* dev )
+{
+ m_comboSourceDevice->setSelectedDevice( dev );
+}
+
+
+K3bDevice::Device* K3bDvdCopyDialog::readingDevice() const
+{
+ return m_comboSourceDevice->selectedDevice();
+}
+
+
+void K3bDvdCopyDialog::slotStartClicked()
+{
+ //
+ // Let's check the available size
+ //
+ if( m_checkCacheImage->isChecked() || m_checkOnlyCreateImage->isChecked() ) {
+ if( neededSize()/1024 > m_tempDirSelectionWidget->freeTempSpace() ) {
+ if( KMessageBox::warningContinueCancel( this, i18n("There seems to be not enough free space in temporary directory. "
+ "Write anyway?") ) == KMessageBox::Cancel )
+ return;
+ }
+ }
+
+ //
+ // The job asks if we want to overwrite.
+ //
+
+ K3bJobProgressDialog* dlg = 0;
+ if( m_checkOnlyCreateImage->isChecked() ) {
+ dlg = new K3bJobProgressDialog( kapp->mainWidget() );
+ }
+ else {
+ dlg = new K3bBurnProgressDialog( kapp->mainWidget() );
+ }
+
+ K3bDvdCopyJob* job = new K3bDvdCopyJob( dlg, this );
+
+ job->setWriterDevice( m_writerSelectionWidget->writerDevice() );
+ job->setReaderDevice( m_comboSourceDevice->selectedDevice() );
+ job->setImagePath( m_tempDirSelectionWidget->tempPath() );
+ job->setRemoveImageFiles( m_checkDeleteImages->isChecked() && !m_checkOnlyCreateImage->isChecked() );
+ job->setOnlyCreateImage( m_checkOnlyCreateImage->isChecked() );
+ job->setSimulate( m_checkSimulate->isChecked() );
+ job->setOnTheFly( !m_checkCacheImage->isChecked() );
+ job->setWriteSpeed( m_writerSelectionWidget->writerSpeed() );
+ job->setCopies( m_checkSimulate->isChecked() ? 1 : m_spinCopies->value() );
+ job->setWritingMode( m_writingModeWidget->writingMode() );
+ job->setIgnoreReadErrors( m_checkIgnoreReadErrors->isChecked() );
+ job->setReadRetries( m_spinRetries->value() );
+ job->setVerifyData( m_checkVerifyData->isChecked() );
+
+ if( !exitLoopOnHide() )
+ hide();
+
+ dlg->startJob( job );
+
+ delete dlg;
+ delete job;
+
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "keep action dialogs open", false ) &&
+ !exitLoopOnHide() )
+ show();
+ else
+ close();
+}
+
+
+void K3bDvdCopyDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_comboSourceDevice->setSelectedDevice( k3bcore->deviceManager()->findDevice( c->readEntry( "source_device" ) ) );
+
+ m_writerSelectionWidget->loadConfig( c );
+
+ m_writingModeWidget->loadConfig( c );
+
+ m_tempDirSelectionWidget->readConfig( c );
+
+ m_checkSimulate->setChecked( c->readBoolEntry( "simulate", false ) );
+ m_checkCacheImage->setChecked( !c->readBoolEntry( "on_the_fly", false ) );
+ m_checkOnlyCreateImage->setChecked( c->readBoolEntry( "only_create_image", false ) );
+ m_checkDeleteImages->setChecked( c->readBoolEntry( "remove_image", true ) );
+ m_checkIgnoreReadErrors->setChecked( c->readBoolEntry( "ignore read errors", false ) );
+ m_spinRetries->setValue( c->readNumEntry( "retries", 128 ) );
+ m_spinCopies->setValue( c->readNumEntry( "copies", 1 ) );
+ m_checkVerifyData->setChecked( c->readBoolEntry( "verify data", false ) );
+
+ slotToggleAll();
+}
+
+
+void K3bDvdCopyDialog::saveUserDefaults( KConfigBase* c )
+{
+ m_tempDirSelectionWidget->saveConfig();
+
+ m_writingModeWidget->saveConfig( c );
+ m_tempDirSelectionWidget->saveConfig( c );
+
+ c->writeEntry( "source_device", m_comboSourceDevice->selectedDevice() ? m_comboSourceDevice->selectedDevice()->devicename() : QString() );
+
+ c->writeEntry( "simulate", m_checkSimulate->isChecked() );
+ c->writeEntry( "on_the_fly", !m_checkCacheImage->isChecked() );
+ c->writeEntry( "only_create_image", m_checkOnlyCreateImage->isChecked() );
+ c->writeEntry( "remove_image", m_checkDeleteImages->isChecked() );
+ c->writeEntry( "ignore read errors", m_checkIgnoreReadErrors->isChecked() );
+ c->writeEntry( "retries", m_spinRetries->value() );
+ c->writeEntry( "copies", m_spinCopies->value() );
+ c->writeEntry( "verify data", m_checkVerifyData->isChecked() );
+
+ m_writerSelectionWidget->saveConfig( c );
+
+ if( m_tempDirSelectionWidget->isEnabled() )
+ m_tempDirSelectionWidget->saveConfig();
+}
+
+
+void K3bDvdCopyDialog::loadK3bDefaults()
+{
+ m_writerSelectionWidget->loadDefaults();
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() );
+
+ m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO );
+
+ m_checkSimulate->setChecked( false );
+ m_checkCacheImage->setChecked( true );
+ m_checkOnlyCreateImage->setChecked( false );
+ m_checkDeleteImages->setChecked( true );
+ m_checkIgnoreReadErrors->setChecked(false);
+ m_spinCopies->setValue( 1 );
+ m_spinRetries->setValue(128);
+ m_checkVerifyData->setChecked( false );
+
+ slotToggleAll();
+}
+
+
+void K3bDvdCopyDialog::toggleAll()
+{
+ updateOverrideDevice();
+
+ m_checkSimulate->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_checkCacheImage->setDisabled( m_checkOnlyCreateImage->isChecked() );
+
+ K3bDevice::Device* dev = m_writerSelectionWidget->writerDevice();
+ if( dev ) {
+ // select the proper writing modes
+ // if writing and reading devices are the same we cannot use
+ // K3bWritingModeWidget::determineSupportedModesFromMedium since the inserted medium is not the one we
+ // will be using for burning. In that case we go the old fashioned way.
+ if( dev == m_comboSourceDevice->selectedDevice() ) {
+ int modes = 0;
+ if( dev->type() & (K3bDevice::DVDR|K3bDevice::DVDRW) ) {
+ modes |= K3b::DAO|K3b::WRITING_MODE_RES_OVWR;
+ if( dev->featureCurrent( K3bDevice::FEATURE_INCREMENTAL_STREAMING_WRITABLE ) != 0 )
+ modes |= K3b::WRITING_MODE_INCR_SEQ;
+ }
+
+ m_writingModeWidget->setSupportedModes( modes );
+ m_checkSimulate->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ }
+ else {
+ m_writingModeWidget->determineSupportedModesFromMedium( dev );
+
+ if( k3bappcore->mediaCache()->diskInfo( dev ).mediaType() & K3bDevice::MEDIA_DVD_PLUS_ALL ) {
+ // no simulation support for DVD+R(W) media
+ m_checkSimulate->setChecked(false);
+ m_checkSimulate->setEnabled(false);
+ }
+ else {
+ m_checkSimulate->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ }
+ }
+ }
+
+
+
+ m_writingModeWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_writerSelectionWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_tempDirSelectionWidget->setDisabled( !m_checkCacheImage->isChecked() && !m_checkOnlyCreateImage->isChecked() );
+ m_writingModeWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_checkDeleteImages->setDisabled( m_checkOnlyCreateImage->isChecked() || !m_checkCacheImage->isChecked() );
+ m_spinCopies->setDisabled( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() );
+ m_checkVerifyData->setDisabled( m_checkOnlyCreateImage->isChecked() || m_checkSimulate->isChecked() );
+
+ setButtonEnabled( START_BUTTON, m_comboSourceDevice->selectedDevice() &&
+ (dev || m_checkOnlyCreateImage->isChecked()) );
+}
+
+
+void K3bDvdCopyDialog::slotSourceMediumChanged( K3bDevice::Device* dev )
+{
+ updateOverrideDevice();
+
+ K3bMedium medium = k3bappcore->mediaCache()->medium( dev );
+
+ m_writerSelectionWidget->setWantedMediumType( k3bappcore->mediaCache()->diskInfo( dev ).numLayers() > 1 &&
+ k3bappcore->mediaCache()->diskInfo( dev ).size().mode1Bytes() > 4700372992LL
+ ? K3bDevice::MEDIA_WRITABLE_DVD_DL
+ : K3bDevice::MEDIA_WRITABLE_DVD_SL );
+
+ m_tempDirSelectionWidget->setNeededSize( neededSize() );
+
+ m_tempDirSelectionWidget->setDefaultImageFileName( medium.volumeId().lower() + ".iso" );
+
+ toggleAll();
+}
+
+
+void K3bDvdCopyDialog::updateOverrideDevice()
+{
+ if( !m_checkCacheImage->isChecked() ) {
+ m_writerSelectionWidget->setOverrideDevice( 0 );
+ m_writerSelectionWidget->setIgnoreDevice( m_comboSourceDevice->selectedDevice() );
+ }
+ else {
+ m_writerSelectionWidget->setIgnoreDevice( 0 );
+ m_writerSelectionWidget->setOverrideDevice( m_comboSourceDevice->selectedDevice(),
+ i18n("Use the same device for burning"),
+ i18n("<qt>Use the same device for burning <i>(Or insert another medium)</i>") );
+ }
+}
+
+
+KIO::filesize_t K3bDvdCopyDialog::neededSize() const
+{
+ K3bMedium medium = k3bappcore->mediaCache()->medium( m_comboSourceDevice->selectedDevice() );
+
+ if( medium.diskInfo().diskState() == K3bDevice::STATE_NO_MEDIA )
+ return 0;
+ else if( medium.diskInfo().mediaType() & (K3bDevice::MEDIA_DVD_RW_OVWR|K3bDevice::MEDIA_DVD_PLUS_RW) )
+ return (KIO::filesize_t)medium.iso9660Descriptor().volumeSpaceSize * (KIO::filesize_t)2048;
+ else
+ return medium.diskInfo().size().mode1Bytes();
+}
+
+#include "k3bdvdcopydialog.moc"
diff --git a/src/misc/k3bdvdcopydialog.h b/src/misc/k3bdvdcopydialog.h
new file mode 100644
index 0000000..be696c4
--- /dev/null
+++ b/src/misc/k3bdvdcopydialog.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * $Id: k3bdvdcopydialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_DVD_COPY_DIALOG_H_
+#define _K3B_DVD_COPY_DIALOG_H_
+
+#include <k3binteractiondialog.h>
+
+#include <kio/global.h>
+
+
+namespace K3bDevice {
+ class Device;
+ class DeviceManager;
+}
+
+class K3bTempDirSelectionWidget;
+class K3bWriterSelectionWidget;
+class K3bMediaSelectionComboBox;
+class QCheckBox;
+class QSpinBox;
+class K3bWritingModeWidget;
+
+
+class K3bDvdCopyDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bDvdCopyDialog( QWidget* parent = 0, const char* name = 0, bool modal = true );
+ ~K3bDvdCopyDialog();
+
+ void setReadingDevice( K3bDevice::Device* );
+ K3bDevice::Device* readingDevice() const;
+
+ private slots:
+ void slotStartClicked();
+ void slotSourceMediumChanged( K3bDevice::Device* );
+ void updateOverrideDevice();
+
+ protected:
+ void init();
+ void toggleAll();
+
+ private:
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void loadK3bDefaults();
+
+ KIO::filesize_t neededSize() const;
+
+ K3bWriterSelectionWidget* m_writerSelectionWidget;
+ K3bTempDirSelectionWidget* m_tempDirSelectionWidget;
+ K3bMediaSelectionComboBox* m_comboSourceDevice;
+ QCheckBox* m_checkSimulate;
+ QCheckBox* m_checkDeleteImages;
+ QCheckBox* m_checkOnlyCreateImage;
+ QCheckBox* m_checkCacheImage;
+ QCheckBox* m_checkVerifyData;
+ QSpinBox* m_spinCopies;
+ QSpinBox* m_spinRetries;
+ QCheckBox* m_checkIgnoreReadErrors;
+ K3bWritingModeWidget* m_writingModeWidget;
+};
+
+#endif
diff --git a/src/misc/k3bdvdformattingdialog.cpp b/src/misc/k3bdvdformattingdialog.cpp
new file mode 100644
index 0000000..d84c4fc
--- /dev/null
+++ b/src/misc/k3bdvdformattingdialog.cpp
@@ -0,0 +1,185 @@
+/*
+ *
+ * $Id: k3bdvdformattingdialog.cpp 640188 2007-03-07 09:15:25Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdvdformattingdialog.h"
+#include "k3bdvdformattingjob.h"
+
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bjobprogressdialog.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kapplication.h>
+
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qframe.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+
+K3bDvdFormattingDialog::K3bDvdFormattingDialog( QWidget* parent, const char* name, bool modal )
+ : K3bInteractionDialog( parent, name,
+ i18n("DVD Formatting"),
+ i18n("DVD%1RW").arg(""),
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "DVD Formatting", // config group
+ modal )
+{
+ QWidget* frame = mainWidget();
+
+ m_writerSelectionWidget = new K3bWriterSelectionWidget( frame );
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_REWRITABLE_DVD );
+ // we need state empty here for preformatting DVD+RW.
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_COMPLETE|
+ K3bDevice::STATE_INCOMPLETE|
+ K3bDevice::STATE_EMPTY );
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::DVD_RW_FORMAT );
+ m_writerSelectionWidget->setForceAutoSpeed(true);
+
+ QGroupBox* groupWritingMode = new QGroupBox( 1, Qt::Vertical, i18n("Writing Mode"), frame );
+ groupWritingMode->layout()->setMargin( marginHint() );
+ groupWritingMode->layout()->setSpacing( spacingHint() );
+ m_writingModeWidget = new K3bWritingModeWidget( K3b::WRITING_MODE_INCR_SEQ|K3b::WRITING_MODE_RES_OVWR,
+ groupWritingMode );
+
+
+ QGroupBox* groupOptions = new QGroupBox( 2, Qt::Vertical, i18n("Settings"), frame );
+ groupOptions->layout()->setMargin( marginHint() );
+ groupOptions->layout()->setSpacing( spacingHint() );
+ m_checkForce = new QCheckBox( i18n("Force"), groupOptions );
+ m_checkQuickFormat = new QCheckBox( i18n("Quick format"), groupOptions );
+
+ QGridLayout* grid = new QGridLayout( frame );
+ grid->setMargin( 0 );
+ grid->setSpacing( spacingHint() );
+
+ grid->addMultiCellWidget( m_writerSelectionWidget, 0, 0, 0, 1 );
+ grid->addWidget( groupWritingMode, 1, 0 );
+ grid->addWidget( groupOptions, 1, 1 );
+ grid->setRowStretch( 1, 1 );
+
+
+ QToolTip::add( m_checkForce, i18n("Force formatting of empty DVDs") );
+ QWhatsThis::add( m_checkForce, i18n("<p>If this option is checked K3b will format a "
+ "DVD-RW even if it is empty. It may also be used to "
+ "force K3b to format a DVD+RW or a DVD-RW in restricted "
+ "overwrite mode."
+ "<p><b>Caution:</b> It is not recommended to often format a DVD "
+ "since it may already be unusable after 10-20 reformat procedures."
+ "<p>DVD+RW media only needs to be formatted once. After that it "
+ "just needs to be overwritten. The same applies to DVD-RW in "
+ "restricted overwrite mode.") );
+
+ QToolTip::add( m_checkQuickFormat, i18n("Try to perform quick formatting") );
+ QWhatsThis::add( m_checkQuickFormat, i18n("<p>If this option is checked K3b will tell the writer "
+ "to perform a quick format."
+ "<p>Formatting a DVD-RW completely can take a very long "
+ "time and some DVD writers perform a full format even if "
+ "quick format is enabled." ) );
+
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged()), this, SLOT(slotWriterChanged()) );
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged(K3bDevice::Device*)),
+ m_writingModeWidget, SLOT(determineSupportedModesFromMedium(K3bDevice::Device*)) );
+
+ slotWriterChanged();
+}
+
+
+K3bDvdFormattingDialog::~K3bDvdFormattingDialog()
+{
+}
+
+
+void K3bDvdFormattingDialog::setDevice( K3bDevice::Device* dev )
+{
+ m_writerSelectionWidget->setWriterDevice( dev );
+}
+
+
+void K3bDvdFormattingDialog::slotStartClicked()
+{
+ //
+ // create a jobprogressdialog and start the job
+ //
+
+
+
+ K3bJobProgressDialog d( kapp->mainWidget(), "formattingProgress", false );
+
+ K3bDvdFormattingJob* job = new K3bDvdFormattingJob( &d, this );
+ job->setDevice( m_writerSelectionWidget->writerDevice() );
+ job->setMode( m_writingModeWidget->writingMode() );
+ job->setForce( m_checkForce->isChecked() );
+ job->setQuickFormat( m_checkQuickFormat->isChecked() );
+
+ if( !exitLoopOnHide() )
+ hide();
+
+ d.startJob( job );
+
+ delete job;
+
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "keep action dialogs open", false ) &&
+ !exitLoopOnHide() )
+ show();
+ else
+ close();
+}
+
+
+void K3bDvdFormattingDialog::slotWriterChanged()
+{
+ setButtonEnabled( START_BUTTON, m_writerSelectionWidget->writerDevice() != 0 );
+}
+
+
+void K3bDvdFormattingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_checkForce->setChecked( c->readBoolEntry( "force", false ) );
+ m_checkQuickFormat->setChecked( c->readBoolEntry( "quick format", true ) );
+ m_writerSelectionWidget->loadConfig( c );
+ m_writingModeWidget->loadConfig( c );
+}
+
+
+void K3bDvdFormattingDialog::saveUserDefaults( KConfigBase* c )
+{
+ c->writeEntry( "force", m_checkForce->isChecked() );
+ c->writeEntry( "quick format", m_checkQuickFormat->isChecked() );
+ m_writerSelectionWidget->saveConfig( c );
+ m_writingModeWidget->saveConfig( c );
+}
+
+
+void K3bDvdFormattingDialog::loadK3bDefaults()
+{
+ m_writerSelectionWidget->loadDefaults();
+ m_checkForce->setChecked( false );
+ m_checkQuickFormat->setChecked( true );
+ m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO );
+}
+
+
+#include "k3bdvdformattingdialog.moc"
diff --git a/src/misc/k3bdvdformattingdialog.h b/src/misc/k3bdvdformattingdialog.h
new file mode 100644
index 0000000..1314ae1
--- /dev/null
+++ b/src/misc/k3bdvdformattingdialog.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id: k3bdvdformattingdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_DVD_FORMATTING_DIALOG_H_
+#define _K3B_DVD_FORMATTING_DIALOG_H_
+
+#include <k3binteractiondialog.h>
+
+
+class QCheckBox;
+class K3bWritingModeWidget;
+class K3bWriterSelectionWidget;
+namespace K3bDevice {
+ class Device;
+}
+
+class K3bDvdFormattingDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bDvdFormattingDialog( QWidget* = 0, const char* = 0, bool modal = true );
+ ~K3bDvdFormattingDialog();
+
+ public slots:
+ void setDevice( K3bDevice::Device* );
+
+ protected slots:
+ void slotStartClicked();
+ void slotWriterChanged();
+
+ private:
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void loadK3bDefaults();
+
+ K3bWriterSelectionWidget* m_writerSelectionWidget;
+ K3bWritingModeWidget* m_writingModeWidget;
+ QCheckBox* m_checkForce;
+ QCheckBox* m_checkQuickFormat;
+};
+
+#endif
diff --git a/src/misc/k3bisoimagewritingdialog.cpp b/src/misc/k3bisoimagewritingdialog.cpp
new file mode 100644
index 0000000..1832ee5
--- /dev/null
+++ b/src/misc/k3bisoimagewritingdialog.cpp
@@ -0,0 +1,580 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bisoimagewritingdialog.h"
+#include "k3biso9660imagewritingjob.h"
+
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3bburnprogressdialog.h>
+#include <kcutlabel.h>
+#include <k3bstdguiitems.h>
+#include <k3bmd5job.h>
+#include <k3bglobals.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bcore.h>
+#include <k3blistview.h>
+#include <k3biso9660.h>
+#include <k3bapplication.h>
+#include <k3bmediacache.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kurlrequester.h>
+#include <kfiledialog.h>
+#include <kstdguiitem.h>
+#include <kguiitem.h>
+#include <kiconloader.h>
+#include <kconfig.h>
+#include <kio/global.h>
+#include <kurl.h>
+#include <kinputdialog.h>
+#include <kurldrag.h>
+#include <klineedit.h>
+
+#include <qheader.h>
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qspinbox.h>
+#include <qevent.h>
+#include <qpopupmenu.h>
+#include <qclipboard.h>
+
+
+class K3bIsoImageWritingDialog::Private
+{
+public:
+ Private()
+ : md5SumItem(0),
+ haveMd5Sum( false ),
+ imageForced( false ) {
+ }
+
+ K3bListViewItem* md5SumItem;
+ bool haveMd5Sum;
+ QString lastCheckedFile;
+ bool isIsoImage;
+
+ bool imageForced;
+};
+
+
+K3bIsoImageWritingDialog::K3bIsoImageWritingDialog( QWidget* parent, const char* name, bool modal )
+ : K3bInteractionDialog( parent, name,
+ i18n("Burn Iso9660 Image"),
+ i18n("to DVD"),
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "DVD image writing",
+ modal )
+{
+ d = new Private();
+
+ setAcceptDrops(true);
+ setupGui();
+
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD );
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY );
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::GROWISOFS );
+ m_writingModeWidget->setSupportedModes( K3b::DAO|K3b::WRITING_MODE_INCR_SEQ|K3b::WRITING_MODE_RES_OVWR );
+
+ m_md5Job = new K3bMd5Job( 0, this );
+ connect( m_md5Job, SIGNAL(finished(bool)),
+ this, SLOT(slotMd5JobFinished(bool)) );
+ connect( m_md5Job, SIGNAL(percent(int)),
+ this, SLOT(slotMd5JobPercent(int)) );
+
+ updateImageSize( imagePath() );
+
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged()),
+ this, SLOT(slotWriterChanged()) );
+ connect( m_writerSelectionWidget, SIGNAL(writingAppChanged(int)),
+ this, SLOT(slotWriterChanged()) );
+ connect( m_writingModeWidget, SIGNAL(writingModeChanged(int)),
+ this, SLOT(slotWriterChanged()) );
+ connect( m_editImagePath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(updateImageSize(const QString&)) );
+ connect( m_checkDummy, SIGNAL(toggled(bool)),
+ this, SLOT(slotWriterChanged()) );
+}
+
+
+K3bIsoImageWritingDialog::~K3bIsoImageWritingDialog()
+{
+ delete d;
+}
+
+
+void K3bIsoImageWritingDialog::init()
+{
+ if( !d->imageForced ) {
+ // when opening the dialog first the default settings are loaded and afterwards we set the
+ // last written image because that's what most users want
+ KConfig* c = k3bcore->config();
+ c->setGroup( configGroup() );
+ QString image = c->readPathEntry( "last written image" );
+ if( QFile::exists( image ) )
+ m_editImagePath->setURL( image );
+ }
+}
+
+
+void K3bIsoImageWritingDialog::setupGui()
+{
+ QWidget* frame = mainWidget();
+
+ // image
+ // -----------------------------------------------------------------------
+ QGroupBox* groupImageUrl = new QGroupBox( 1, Qt::Horizontal, i18n("Image to Burn"), frame );
+ m_editImagePath = new KURLRequester( groupImageUrl );
+ m_editImagePath->setMode( KFile::File|KFile::ExistingOnly );
+ m_editImagePath->setCaption( i18n("Choose Image File") );
+ m_editImagePath->setFilter( i18n("*.iso *.ISO|ISO9660 Image Files") + "\n"
+ + i18n("*|All Files") );
+
+ connect( m_editImagePath->lineEdit(), SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotWriterChanged() ) );
+
+ // image info
+ // -----------------------------------------------------------------------
+ m_infoView = new K3bListView( frame );
+ m_infoView->addColumn( "key" );
+ m_infoView->addColumn( "value" );
+ m_infoView->header()->hide();
+ m_infoView->setNoItemText( i18n("No image file selected") );
+ m_infoView->setSorting( -1 );
+ m_infoView->setAlternateBackground( QColor() );
+ m_infoView->setFullWidth(true);
+ m_infoView->setSelectionMode( QListView::NoSelection );
+
+ connect( m_infoView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) );
+
+ m_writerSelectionWidget = new K3bWriterSelectionWidget( frame );
+
+ // options
+ // -----------------------------------------------------------------------
+ QTabWidget* optionTabbed = new QTabWidget( frame );
+
+ QWidget* optionTab = new QWidget( optionTabbed );
+ QGridLayout* optionTabLayout = new QGridLayout( optionTab );
+ optionTabLayout->setAlignment( Qt::AlignTop );
+ optionTabLayout->setSpacing( spacingHint() );
+ optionTabLayout->setMargin( marginHint() );
+
+ QGroupBox* writingModeGroup = new QGroupBox( 1, Vertical, i18n("Writing Mode"), optionTab );
+ writingModeGroup->setInsideMargin( marginHint() );
+ m_writingModeWidget = new K3bWritingModeWidget( writingModeGroup );
+
+
+ // copies --------
+ QGroupBox* groupCopies = new QGroupBox( 2, Qt::Horizontal, i18n("Copies"), optionTab );
+ groupCopies->setInsideSpacing( spacingHint() );
+ groupCopies->setInsideMargin( marginHint() );
+ QLabel* pixLabel = new QLabel( groupCopies );
+ pixLabel->setPixmap( SmallIcon( "cdcopy", KIcon::SizeMedium ) );
+ pixLabel->setScaledContents( false );
+ m_spinCopies = new QSpinBox( groupCopies );
+ m_spinCopies->setMinValue( 1 );
+ m_spinCopies->setMaxValue( 999 );
+ // -------- copies
+
+ QGroupBox* optionGroup = new QGroupBox( 3, Vertical, i18n("Settings"), optionTab );
+ optionGroup->setInsideMargin( marginHint() );
+ optionGroup->setInsideSpacing( spacingHint() );
+ m_checkDummy = K3bStdGuiItems::simulateCheckbox( optionGroup );
+ m_checkVerify = K3bStdGuiItems::verifyCheckBox( optionGroup );
+
+
+ optionTabLayout->addWidget( writingModeGroup, 0, 0 );
+ optionTabLayout->addWidget( groupCopies, 1, 0 );
+ optionTabLayout->addMultiCellWidget( optionGroup, 0, 1, 1, 1 );
+ optionTabLayout->setRowStretch( 1, 1 );
+ optionTabLayout->setColStretch( 1, 1 );
+
+ optionTabbed->addTab( optionTab, i18n("Settings") );
+
+
+ QGridLayout* grid = new QGridLayout( frame );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( 0 );
+
+ grid->addWidget( groupImageUrl, 0, 0 );
+ grid->addWidget( m_infoView, 1, 0 );
+ grid->addWidget( m_writerSelectionWidget, 2, 0 );
+ grid->addWidget( optionTabbed, 3, 0 );
+
+ grid->setRowStretch( 1, 1 );
+}
+
+
+void K3bIsoImageWritingDialog::slotStartClicked()
+{
+ if( !d->isIsoImage ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("The image you selected is not a valid ISO9660 image. "
+ "Are you sure you want to burn it anyway? "
+ "(There may exist other valid image types that are not detected by K3b but "
+ "will work fine.)"), i18n("Burn") ) == KMessageBox::Cancel )
+ return;
+ }
+
+ K3bIso9660 isoFs( imagePath() );
+ if( isoFs.open() ) {
+ if( K3b::imageFilesize( KURL::fromPathOrURL( imagePath() ) ) < (KIO::filesize_t)(isoFs.primaryDescriptor().volumeSpaceSize*2048) ) {
+ if( KMessageBox::questionYesNo( this,
+ i18n("<p>This image has an invalid file size."
+ "If it has been downloaded make sure the download is complete."
+ "<p>Only continue if you know what you are doing."),
+ i18n("Warning"),
+ i18n("Continue"),
+ i18n("Cancel") ) == KMessageBox::No )
+ return;
+ }
+ }
+
+ m_md5Job->cancel();
+
+ // save the path
+ KConfig* c = k3bcore->config();
+ c->setGroup( configGroup() );
+ if( c->readPathEntry( "last written image" ).isEmpty() )
+ c->writePathEntry( "last written image", imagePath() );
+
+ // create a progresswidget
+ K3bBurnProgressDialog dlg( kapp->mainWidget(), "burnProgress", true );
+
+ // create the job
+ K3bIso9660ImageWritingJob* job = new K3bIso9660ImageWritingJob( &dlg );
+
+ job->setBurnDevice( m_writerSelectionWidget->writerDevice() );
+ job->setSpeed( m_writerSelectionWidget->writerSpeed() );
+ job->setSimulate( m_checkDummy->isChecked() );
+ job->setWritingMode( m_writingModeWidget->writingMode() );
+ job->setVerifyData( m_checkVerify->isChecked() );
+ job->setCopies( m_checkDummy->isChecked() ? 1 : m_spinCopies->value() );
+ job->setImagePath( imagePath() );
+
+ // HACK (needed since if the medium is forced the stupid K3bIso9660ImageWritingJob defaults to cd writing)
+ job->setWritingApp( K3b::GROWISOFS );
+
+ if( !exitLoopOnHide() )
+ hide();
+
+ dlg.startJob( job );
+
+ delete job;
+
+ if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "keep action dialogs open", false ) &&
+ !exitLoopOnHide() )
+ show();
+ else
+ close();
+}
+
+
+void K3bIsoImageWritingDialog::updateImageSize( const QString& path )
+{
+ m_md5Job->cancel();
+ m_infoView->clear();
+ d->md5SumItem = 0;
+ d->haveMd5Sum = false;
+ d->isIsoImage = false;
+
+ QFileInfo info( path );
+ if( info.isFile() ) {
+
+ KIO::filesize_t imageSize = K3b::filesize( KURL::fromPathOrURL(path) );
+
+ // ------------------------------------------------
+ // Test for iso9660 image
+ // ------------------------------------------------
+ K3bIso9660 isoF( path );
+ if( isoF.open() ) {
+
+ d->isIsoImage = true;
+
+ K3bListViewItem* isoRootItem = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("Iso9660 image") );
+ isoRootItem->setForegroundColor( 0, palette().disabled().foreground() );
+ isoRootItem->setPixmap( 0, SmallIcon( "cdimage") );
+
+ K3bListViewItem* item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(),
+ i18n("Filesize:"), KIO::convertSize( imageSize ) );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("System Id:"),
+ isoF.primaryDescriptor().systemId.isEmpty()
+ ? QString("-")
+ : isoF.primaryDescriptor().systemId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Volume Id:"),
+ isoF.primaryDescriptor().volumeId.isEmpty()
+ ? QString("-")
+ : isoF.primaryDescriptor().volumeId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Volume Set Id:"),
+ isoF.primaryDescriptor().volumeSetId.isEmpty()
+ ? QString("-")
+ : isoF.primaryDescriptor().volumeSetId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Publisher Id:"),
+ isoF.primaryDescriptor().publisherId.isEmpty()
+ ? QString("-")
+ : isoF.primaryDescriptor().publisherId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Preparer Id:"),
+ isoF.primaryDescriptor().preparerId.isEmpty()
+ ? QString("-") : isoF.primaryDescriptor().preparerId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ item = new K3bListViewItem( isoRootItem,
+ m_infoView->lastItem(),
+ i18n("Application Id:"),
+ isoF.primaryDescriptor().applicationId.isEmpty()
+ ? QString("-")
+ : isoF.primaryDescriptor().applicationId );
+ item->setForegroundColor( 0, palette().disabled().foreground() );
+
+ isoRootItem->setOpen( true );
+
+ isoF.close();
+ }
+ else {
+ K3bListViewItem* item = new K3bListViewItem( m_infoView, m_infoView->lastItem(),
+ i18n("Not an Iso9660 image") );
+ item->setForegroundColor( 0, Qt::red );
+ item->setPixmap( 0, SmallIcon( "stop") );
+ }
+
+ calculateMd5Sum( path );
+ }
+
+ slotWriterChanged();
+}
+
+
+void K3bIsoImageWritingDialog::slotWriterChanged()
+{
+ K3bDevice::Device* dev = m_writerSelectionWidget->writerDevice();
+ if( dev ) {
+ K3bMedium medium = k3bappcore->mediaCache()->medium( dev );
+ if( medium.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_PLUS_ALL ) {
+ // no simulation support for DVD+R(W) media
+ m_checkDummy->setChecked(false);
+ m_checkDummy->setEnabled(false);
+ }
+ else {
+ m_checkDummy->setDisabled( false );
+ }
+
+ m_writingModeWidget->determineSupportedModesFromMedium( dev );
+
+ if( m_checkDummy->isChecked() ) {
+ m_checkVerify->setEnabled( false );
+ m_checkVerify->setChecked( false );
+ }
+ else
+ m_checkVerify->setEnabled( true );
+
+ m_spinCopies->setEnabled( !m_checkDummy->isChecked() );
+ }
+
+ setButtonEnabled( START_BUTTON,
+ dev && !m_editImagePath->lineEdit()->text().isEmpty() );
+}
+
+
+void K3bIsoImageWritingDialog::setImage( const KURL& url )
+{
+ d->imageForced = true;
+#if KDE_IS_VERSION(3,4,0)
+ m_editImagePath->setKURL( url );
+#else
+ m_editImagePath->setURL( url.path() );
+#endif
+}
+
+
+void K3bIsoImageWritingDialog::calculateMd5Sum( const QString& file )
+{
+ d->haveMd5Sum = false;
+
+ if( !d->md5SumItem )
+ d->md5SumItem = new K3bListViewItem( m_infoView, m_infoView->firstChild() );
+
+ d->md5SumItem->setText( 0, i18n("Md5 Sum:") );
+ d->md5SumItem->setForegroundColor( 0, palette().disabled().foreground() );
+ d->md5SumItem->setProgress( 1, 0 );
+ d->md5SumItem->setPixmap( 0, SmallIcon( "exec") );
+
+ if( file != d->lastCheckedFile ) {
+ d->lastCheckedFile = file;
+ m_md5Job->setFile( file );
+ m_md5Job->start();
+ }
+ else
+ slotMd5JobFinished( true );
+}
+
+
+void K3bIsoImageWritingDialog::slotMd5JobPercent( int p )
+{
+ d->md5SumItem->setProgress( 1, p );
+}
+
+
+void K3bIsoImageWritingDialog::slotMd5JobFinished( bool success )
+{
+ if( success ) {
+ d->md5SumItem->setText( 1, m_md5Job->hexDigest() );
+ d->haveMd5Sum = true;
+ }
+ else {
+ d->md5SumItem->setForegroundColor( 1, Qt::red );
+ if( m_md5Job->hasBeenCanceled() )
+ d->md5SumItem->setText( 1, i18n("Calculation cancelled") );
+ else
+ d->md5SumItem->setText( 1, i18n("Calculation failed") );
+ d->md5SumItem->setPixmap( 0, SmallIcon( "stop") );
+ d->lastCheckedFile.truncate(0);
+ }
+
+ d->md5SumItem->setDisplayProgressBar( 1, false );
+}
+
+
+void K3bIsoImageWritingDialog::slotContextMenu( KListView*, QListViewItem*, const QPoint& pos )
+{
+ if( !d->haveMd5Sum )
+ return;
+
+ QPopupMenu popup;
+ int copyItem = popup.insertItem( i18n("Copy checksum to clipboard") );
+ int compareItem = popup.insertItem( i18n("Compare checksum...") );
+
+ int r = popup.exec( pos );
+
+ if( r == compareItem ) {
+ bool ok;
+ QString md5sumToCompare = KInputDialog::getText( i18n("MD5 Sum Check"),
+ i18n("Please insert the MD5 Sum to compare:"),
+ QString::null,
+ &ok,
+ this );
+ if( ok ) {
+ if( md5sumToCompare.lower().utf8() == m_md5Job->hexDigest().lower() )
+ KMessageBox::information( this, i18n("The MD5 Sum of %1 equals the specified.").arg(imagePath()),
+ i18n("MD5 Sums Equal") );
+ else
+ KMessageBox::sorry( this, i18n("The MD5 Sum of %1 differs from the specified.").arg(imagePath()),
+ i18n("MD5 Sums Differ") );
+ }
+ }
+ else if( r == copyItem ) {
+ QApplication::clipboard()->setText( m_md5Job->hexDigest().lower(), QClipboard::Clipboard );
+ }
+}
+
+
+void K3bIsoImageWritingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_writingModeWidget->loadConfig( c );
+ m_checkDummy->setChecked( c->readBoolEntry("simulate", false ) );
+ m_checkVerify->setChecked( c->readBoolEntry( "verify_data", false ) );
+ m_spinCopies->setValue( c->readNumEntry( "copies", 1 ) );
+
+ m_writerSelectionWidget->loadConfig( c );
+
+ if( !d->imageForced ) {
+ QString image = c->readPathEntry( "image path", c->readPathEntry( "last written image" ) );
+ if( QFile::exists( image ) )
+ m_editImagePath->setURL( image );
+ }
+}
+
+
+void K3bIsoImageWritingDialog::saveUserDefaults( KConfigBase* c )
+{
+ m_writingModeWidget->saveConfig( c ),
+ c->writeEntry( "simulate", m_checkDummy->isChecked() );
+ c->writeEntry( "verify_data", m_checkVerify->isChecked() );
+ c->writeEntry( "copies", m_spinCopies->value() );
+
+ m_writerSelectionWidget->saveConfig( c );
+
+ c->writePathEntry( "image path", imagePath() );
+}
+
+
+void K3bIsoImageWritingDialog::loadK3bDefaults()
+{
+ m_writerSelectionWidget->loadDefaults();
+ m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO );
+ m_checkDummy->setChecked( false );
+ m_checkVerify->setChecked( false );
+ m_spinCopies->setValue( 1 );
+}
+
+
+QString K3bIsoImageWritingDialog::imagePath() const
+{
+ return K3b::convertToLocalUrl( KURL::fromPathOrURL( m_editImagePath->url() ) ).path();
+}
+
+
+void K3bIsoImageWritingDialog::dragEnterEvent( QDragEnterEvent* e )
+{
+ e->accept( KURLDrag::canDecode(e) );
+}
+
+
+void K3bIsoImageWritingDialog::dropEvent( QDropEvent* e )
+{
+ KURL::List urls;
+ KURLDrag::decode( e, urls );
+#if KDE_IS_VERSION(3,4,0)
+ m_editImagePath->setKURL( urls.first() );
+#else
+ m_editImagePath->setURL( urls.first().path() );
+#endif
+}
+
+#include "k3bisoimagewritingdialog.moc"
diff --git a/src/misc/k3bisoimagewritingdialog.h b/src/misc/k3bisoimagewritingdialog.h
new file mode 100644
index 0000000..caf0f4f
--- /dev/null
+++ b/src/misc/k3bisoimagewritingdialog.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BISOIMAGEWRITINGDIALOG_H
+#define K3BISOIMAGEWRITINGDIALOG_H
+
+#include <k3binteractiondialog.h>
+
+
+class QCheckBox;
+class K3bWriterSelectionWidget;
+class QLabel;
+class KURL;
+class K3bMd5Job;
+class K3bWritingModeWidget;
+class KURLRequester;
+class K3bListView;
+class QSpinBox;
+class QDragEnterEvent;
+class QDropEvent;
+class KListView;
+class QListViewItem;
+class QPoint;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bIsoImageWritingDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bIsoImageWritingDialog( QWidget* = 0, const char* = 0, bool = true );
+ ~K3bIsoImageWritingDialog();
+
+ void setImage( const KURL& url );
+
+ protected slots:
+ void slotStartClicked();
+ void updateImageSize( const QString& );
+ void slotWriterChanged();
+ void slotMd5JobPercent( int );
+ void slotMd5JobFinished( bool );
+ void slotContextMenu( KListView*, QListViewItem*, const QPoint& pos );
+
+ protected:
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void loadK3bDefaults();
+
+ void calculateMd5Sum( const QString& );
+ void dragEnterEvent( QDragEnterEvent* );
+ void dropEvent( QDropEvent* );
+
+ void init();
+
+ private:
+ void setupGui();
+ QString imagePath() const;
+
+ K3bMd5Job* m_md5Job;
+
+ K3bWriterSelectionWidget* m_writerSelectionWidget;
+ QCheckBox* m_checkDummy;
+ QCheckBox* m_checkVerify;
+ QSpinBox* m_spinCopies;
+ K3bWritingModeWidget* m_writingModeWidget;
+
+ KURLRequester* m_editImagePath;
+ K3bListView* m_infoView;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/option/Makefile.am b/src/option/Makefile.am
new file mode 100644
index 0000000..7b99dd3
--- /dev/null
+++ b/src/option/Makefile.am
@@ -0,0 +1,20 @@
+AM_CPPFLAGS = -I$(srcdir)/../../libk3b/core \
+ -I$(srcdir)/../../libk3bdevice \
+ -I$(srcdir)/../../libk3b/plugin \
+ -I$(srcdir)/../../libk3b/tools \
+ -I$(srcdir)/.. \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = liboption.la
+
+liboption_la_SOURCES = base_k3bcddboptiontab.ui base_k3bmiscoptiontab.ui \
+ base_k3bpluginoptiontab.ui \
+ base_k3bthemeoptiontab.ui k3bmiscoptiontab.cpp \
+ k3bexternalbinoptiontab.cpp k3bcddboptiontab.cpp \
+ k3bburningoptiontab.cpp k3boptiondialog.cpp \
+ k3bdeviceoptiontab.cpp k3bnotifyoptiontab.cpp \
+ k3bpluginoptiontab.cpp \
+ k3bthemeoptiontab.cpp k3bdevicewidget.cpp \
+ k3bexternalbinwidget.cpp
diff --git a/src/option/base_k3bcddboptiontab.ui b/src/option/base_k3bcddboptiontab.ui
new file mode 100644
index 0000000..f46e970
--- /dev/null
+++ b/src/option/base_k3bcddboptiontab.ui
@@ -0,0 +1,560 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bCddbOptionTab</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bCddbOptionTab</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>648</width>
+ <height>553</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>CDDB Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>m_mainTabbed</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Local</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_checkUseLocalCddb</cstring>
+ </property>
+ <property name="text">
+ <string>Use local CDDB directory</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>m_checkSaveLocalEntries</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Save entries in local directory (the first directory in the list)</string>
+ </property>
+ </widget>
+ <widget class="QFrame" row="2" column="0">
+ <property name="name">
+ <cstring>m_boxLocalDirectory</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_4</cstring>
+ </property>
+ <property name="text">
+ <string>Directory:</string>
+ </property>
+ </widget>
+ <widget class="KListView" row="1" column="0" rowspan="4" colspan="2">
+ <column>
+ <property name="text">
+ <string>Directory</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_viewLocalDir</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="3" column="2">
+ <property name="name">
+ <cstring>m_buttonLocalDirDown</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Move directory down</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="0" column="2">
+ <property name="name">
+ <cstring>m_buttonAddLocalDir</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Add directory</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>m_editLocalDir</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="1" column="2">
+ <property name="name">
+ <cstring>m_buttonRemoveLocalDir</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Remove directory</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="2" column="2">
+ <property name="name">
+ <cstring>m_buttonLocalDirUp</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Move directory up</string>
+ </property>
+ </widget>
+ <spacer row="4" column="2">
+ <property name="name">
+ <cstring>Spacer11_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Remote</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame" row="1" column="0">
+ <property name="name">
+ <cstring>m_boxCddbServer</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Server:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_comboCddbType</cstring>
+ </property>
+ </widget>
+ <widget class="KListView" row="1" column="0" rowspan="4" colspan="4">
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Server</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Port</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_viewCddbServer</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="2">
+ <property name="name">
+ <cstring>m_editCddbServer</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="3">
+ <property name="name">
+ <cstring>m_editCddbPort</cstring>
+ </property>
+ <property name="label">
+ <string></string>
+ </property>
+ <property name="value">
+ <number>80</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>64000</number>
+ </property>
+ <property name="prefix">
+ <string>Port </string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="0" column="4">
+ <property name="name">
+ <cstring>m_buttonAddCddbServer</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Add server</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="1" column="4">
+ <property name="name">
+ <cstring>m_buttonRemoveCddbServer</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Remove server</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="2" column="4">
+ <property name="name">
+ <cstring>m_buttonCddbServerUp</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Move server up</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="3" column="4">
+ <property name="name">
+ <cstring>m_buttonCddbServerDown</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Move server down</string>
+ </property>
+ </widget>
+ <spacer row="4" column="4">
+ <property name="name">
+ <cstring>Spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_checkRemoteCddb</cstring>
+ </property>
+ <property name="text">
+ <string>Enable remote CDDB queries</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Advanced</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupCgi</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>CGI Path</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="KLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>m_editManualCgiPath</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>~/cddb/cddb.cgi</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Path:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_checkManualCgiPath</cstring>
+ </property>
+ <property name="text">
+ <string>Manual CGI path</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>151</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_checkManualCgiPath</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_editManualCgiPath</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkManualCgiPath</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>TextLabel3</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkUseLocalCddb</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_boxLocalDirectory</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkUseLocalCddb</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_checkSaveLocalEntries</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkRemoteCddb</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_boxCddbServer</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_mainTabbed</tabstop>
+ <tabstop>m_checkUseLocalCddb</tabstop>
+ <tabstop>m_checkSaveLocalEntries</tabstop>
+ <tabstop>m_editLocalDir</tabstop>
+ <tabstop>m_viewLocalDir</tabstop>
+ <tabstop>m_checkRemoteCddb</tabstop>
+ <tabstop>m_comboCddbType</tabstop>
+ <tabstop>m_editCddbServer</tabstop>
+ <tabstop>m_editCddbPort</tabstop>
+ <tabstop>m_viewCddbServer</tabstop>
+ <tabstop>m_checkManualCgiPath</tabstop>
+ <tabstop>m_editManualCgiPath</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/src/option/base_k3bmiscoptiontab.ui b/src/option/base_k3bmiscoptiontab.ui
new file mode 100644
index 0000000..364e91f
--- /dev/null
+++ b/src/option/base_k3bmiscoptiontab.ui
@@ -0,0 +1,284 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bMiscOptionTab</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bMiscOptionTab</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Misc</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkSaveOnExit</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Ask to save projects on exit</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Ask to save modified projects on exit</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Default Temporary Directory:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>m_editTempDir</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>The directory where K3b stores temporary files</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;This is the default temporary directory. This is where K3b will store temporary files like iso images or decoded audio files.
+&lt;p&gt;Be aware that the temporary directory may also be changed in every project burn dialog.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>System</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkSystemConfig</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Check system configuration</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Check system Configuration</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will check the system configuration for any problems on startup and when the the user changes the settings.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Used audio output system:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>m_comboAudioOutputSystem</cstring>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonConfigureAudioOutput</cstring>
+ </property>
+ <property name="text">
+ <string>Confi&amp;gure...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>GUI Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkShowProgressOSD</cstring>
+ </property>
+ <property name="text">
+ <string>Show progress &amp;OSD</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will display the progress in an OSD which always stays on top of all other windows.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkHideMainWindowWhileWriting</cstring>
+ </property>
+ <property name="text">
+ <string>Hide &amp;main window while writing</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Hide the main window while displaying the progress window</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will hide the main window while displaying the progress dialog.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkShowSplash</cstring>
+ </property>
+ <property name="text">
+ <string>Show splash screen</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Show the splash screen when K3b starts</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkKonqiIntegration</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;nable Konqueror integration</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Enable integration of K3b actions into Konqueror menus</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;K3b can integrate itself into Konqueror. This integration allows to start K3b from the context menu in the file manager.
+&lt;p&gt;A typical example is: in order to burn a folder to a data CD one clicks on the folder using the right mouse button. In the appearing context menu one selects "Create Data CD with K3b..." and a new K3b project containing the folder is created.
+&lt;p&gt;&lt;em&gt;Konqueror integration is not enabled by default to prevent unwanted cluttering of the Konqueror menus.&lt;/em&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkKeepDialogsOpen</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Keep action dialogs open</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Do not close action dialogs after finishing the process</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will not close action dialogs such as the CD Copy dialog after the process has been finished. It will be kept open to start a new process like copying another CD.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Default action dialog settings:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_comboActionDialogSettings</cstring>
+ </property>
+ </widget>
+ <widget class="K3bIntMapComboBox">
+ <property name="name">
+ <cstring>m_comboActionDialogSettings</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Settings to load when opening an action dialog</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>K3bIntMapComboBox</class>
+ <header location="global">k3bintmapcombobox.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>k3bintmapcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/src/option/base_k3bpluginoptiontab.ui b/src/option/base_k3bpluginoptiontab.ui
new file mode 100644
index 0000000..18321ee
--- /dev/null
+++ b/src/option/base_k3bpluginoptiontab.ui
@@ -0,0 +1,90 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>base_K3bPluginOptionTab</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>m_buttonConfigure</cstring>
+ </property>
+ <property name="text">
+ <string>Configure...</string>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>411</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="K3bListView" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_viewPlugins</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;p&gt;Here all &lt;em&gt;K3b Plugins&lt;/em&gt; may be configured. Be aware that this does not include the &lt;em&gt;KPart Plugins&lt;/em&gt; which embed themselves in the K3b menu structure.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>K3bListView</class>
+ <header location="global">k3blistview.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>k3blistview.h</includehint>
+</includehints>
+</UI>
diff --git a/src/option/base_k3bthemeoptiontab.ui b/src/option/base_k3bthemeoptiontab.ui
new file mode 100644
index 0000000..47a48b4
--- /dev/null
+++ b/src/option/base_k3bthemeoptiontab.ui
@@ -0,0 +1,208 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bThemeOptionTab</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bThemeOptionTab</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>661</width>
+ <height>499</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Theme Selection</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Theme</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Author</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Version</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Comment</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_viewTheme</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox5</cstring>
+ </property>
+ <property name="title">
+ <string>Preview</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_leftPreviewLabel</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_centerPreviewLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>no Theme selected</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_rightPreviewLabel</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>161</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonInstallTheme</cstring>
+ </property>
+ <property name="text">
+ <string>Install New Theme...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonRemoveTheme</cstring>
+ </property>
+ <property name="text">
+ <string>Remove Theme</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/src/option/k3bburningoptiontab.cpp b/src/option/k3bburningoptiontab.cpp
new file mode 100644
index 0000000..21485cb
--- /dev/null
+++ b/src/option/k3bburningoptiontab.cpp
@@ -0,0 +1,198 @@
+/*
+ *
+ * $Id: k3bburningoptiontab.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bburningoptiontab.h"
+#include <k3bmsfedit.h>
+#include <k3bcore.h>
+#include <k3bstdguiitems.h>
+#include <k3bglobalsettings.h>
+
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qtabwidget.h>
+#include <qradiobutton.h>
+#include <qvalidator.h>
+#include <qbuttongroup.h>
+#include <qspinbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include <knuminput.h>
+#include <kconfig.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <klineedit.h>
+
+
+K3bBurningOptionTab::K3bBurningOptionTab( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ setupGui();
+}
+
+
+K3bBurningOptionTab::~K3bBurningOptionTab()
+{
+}
+
+
+void K3bBurningOptionTab::setupGui()
+{
+ QGridLayout* groupAdvancedLayout = new QGridLayout( this );
+ groupAdvancedLayout->setAlignment( Qt::AlignTop );
+ groupAdvancedLayout->setSpacing( KDialog::spacingHint() );
+ groupAdvancedLayout->setMargin( 0 );
+
+
+ QGroupBox* groupWritingApp = new QGroupBox( 0, Qt::Vertical, i18n("Burning"), this );
+ groupWritingApp->layout()->setMargin( 0 );
+ QGridLayout* bufferLayout = new QGridLayout( groupWritingApp->layout() );
+ bufferLayout->setMargin( KDialog::marginHint() );
+ bufferLayout->setSpacing( KDialog::spacingHint() );
+
+ m_checkBurnfree = K3bStdGuiItems::burnproofCheckbox( groupWritingApp );
+ m_checkOverburn = new QCheckBox( i18n("Allow overburning (&not supported by cdrecord <= 1.10)"), groupWritingApp );
+ m_checkForceUnsafeOperations = new QCheckBox( i18n("Force unsafe operations"), groupWritingApp );
+ m_checkManualWritingBufferSize = new QCheckBox( i18n("&Manual writing buffer size") + ":", groupWritingApp );
+ m_editWritingBufferSize = new KIntNumInput( 4, groupWritingApp );
+ m_editWritingBufferSize->setSuffix( " " + i18n("MB") );
+ m_checkAllowWritingAppSelection = new QCheckBox( i18n("Manual writing application &selection"), groupWritingApp );
+ bufferLayout->addMultiCellWidget( m_checkBurnfree, 0, 0, 0, 2 );
+ bufferLayout->addMultiCellWidget( m_checkOverburn, 1, 1, 0, 2 );
+ bufferLayout->addMultiCellWidget( m_checkForceUnsafeOperations, 2, 2, 0, 2 );
+ bufferLayout->addWidget( m_checkManualWritingBufferSize, 3, 0 );
+ bufferLayout->addWidget( m_editWritingBufferSize, 3, 1 );
+ bufferLayout->addMultiCellWidget( m_checkAllowWritingAppSelection, 4, 4, 0, 2 );
+ bufferLayout->setColStretch( 2, 1 );
+
+ QGroupBox* groupMisc = new QGroupBox( 2, Qt::Vertical, i18n("Miscellaneous"), this );
+ m_checkEject = new QCheckBox( i18n("Do not &eject medium after write process"), groupMisc );
+ m_checkAutoErasingRewritable = new QCheckBox( i18n("Automatically erase CD-RWs and DVD-RWs"), groupMisc );
+
+ groupAdvancedLayout->addWidget( groupWritingApp, 0, 0 );
+ groupAdvancedLayout->addWidget( groupMisc, 1, 0 );
+ groupAdvancedLayout->setRowStretch( 2, 1 );
+
+
+ connect( m_checkManualWritingBufferSize, SIGNAL(toggled(bool)),
+ m_editWritingBufferSize, SLOT(setEnabled(bool)) );
+ connect( m_checkManualWritingBufferSize, SIGNAL(toggled(bool)),
+ this, SLOT(slotSetDefaultBufferSizes(bool)) );
+
+
+ m_editWritingBufferSize->setDisabled( true );
+ // -----------------------------------------------------------------------
+
+
+ QToolTip::add( m_checkOverburn, i18n("Allow burning more than the official media capacity") );
+ QToolTip::add( m_checkAllowWritingAppSelection, i18n("Allow to choose between cdrecord and cdrdao") );
+ QToolTip::add( m_checkAutoErasingRewritable, i18n("Automatically erase CD-RWs and DVD-RWs without asking") );
+ QToolTip::add( m_checkEject, i18n("Do not eject the burn medium after a completed burn process") );
+ QToolTip::add( m_checkForceUnsafeOperations, i18n("Force K3b to continue some operations otherwise deemed as unsafe") );
+
+ QWhatsThis::add( m_checkAllowWritingAppSelection, i18n("<p>If this option is checked K3b gives "
+ "the possibility to choose between cdrecord "
+ "and cdrdao when writing a cd."
+ "<p>This may be useful if one of the programs "
+ "does not support the used writer."
+ "<p><b>Be aware that K3b does not support both "
+ "programs in all project types.</b>") );
+
+ QWhatsThis::add( m_checkOverburn, i18n("<p>Each medium has an official maximum capacity which is stored in a read-only "
+ "area of the medium and is guaranteed by the vendor. However, this official "
+ "maximum is not always the actual maximum. Many media have an "
+ "actual total capacity that is slightly larger than the official amount."
+ "<p>If this option is checked K3b will disable a safety check that prevents "
+ "burning beyond the offical capacity."
+ "<p><b>Caution:</b> Enabling this option can cause failures in the end of the "
+ "burning process if K3b attempts to write beyond the official capacity. It "
+ "makes sense to first determine the actual maximum capacity of the media brand "
+ "with a simulated burn.") );
+
+ QWhatsThis::add( m_checkAutoErasingRewritable, i18n("<p>If this option is checked K3b will automatically "
+ "erase CD-RWs and format DVD-RWs if one is found instead "
+ "of an empty media before writing.") );
+
+ QWhatsThis::add( m_checkManualWritingBufferSize, i18n("<p>K3b uses a software buffer during the burning process to "
+ "avoid gaps in the data stream due to high system load. The default "
+ "sizes used are %1 MB for CD and %2 MB for DVD burning."
+ "<p>If this option is checked the value specified will be used for both "
+ "CD and DVD burning.").arg(4).arg(32) );
+
+ QWhatsThis::add( m_checkEject, i18n("<p>If this option is checked K3b will not eject the medium once the burn process "
+ "finishes. This can be helpful in case one leaves the computer after starting the "
+ "burning and does not want the tray to be open all the time."
+ "<p>However, on Linux systems a freshly burned medium has to be reloaded. Otherwise "
+ "the system will not detect the changes and still treat it as an empty medium.") );
+
+ QWhatsThis::add( m_checkForceUnsafeOperations, i18n("<p>If this option is checked K3b will continue in some situations "
+ "which would otherwise be deemed as unsafe."
+ "<p>This setting for example disables the check for medium speed "
+ "verification. Thus, one can force K3b to burn a high speed medium on "
+ "a low speed writer."
+ "<p><b>Caution:</b> Enabling this option may result in damaged media.") );
+}
+
+
+void K3bBurningOptionTab::readSettings()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "General Options" );
+ m_checkAutoErasingRewritable->setChecked( c->readBoolEntry( "auto rewritable erasing", false ) );
+ m_checkAllowWritingAppSelection->setChecked( c->readBoolEntry( "Manual writing app selection", false ) );
+
+ m_checkBurnfree->setChecked( k3bcore->globalSettings()->burnfree() );
+ m_checkEject->setChecked( !k3bcore->globalSettings()->ejectMedia() );
+ m_checkOverburn->setChecked( k3bcore->globalSettings()->overburn() );
+ m_checkForceUnsafeOperations->setChecked( k3bcore->globalSettings()->force() );
+ m_checkManualWritingBufferSize->setChecked( k3bcore->globalSettings()->useManualBufferSize() );
+ if( k3bcore->globalSettings()->useManualBufferSize() )
+ m_editWritingBufferSize->setValue( k3bcore->globalSettings()->bufferSize() );
+}
+
+
+void K3bBurningOptionTab::saveSettings()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "General Options" );
+ c->writeEntry( "auto rewritable erasing", m_checkAutoErasingRewritable->isChecked() );
+ c->writeEntry( "Manual writing app selection", m_checkAllowWritingAppSelection->isChecked() );
+
+ k3bcore->globalSettings()->setEjectMedia( !m_checkEject->isChecked() );
+ k3bcore->globalSettings()->setOverburn( m_checkOverburn->isChecked() );
+ k3bcore->globalSettings()->setBurnfree( m_checkBurnfree->isChecked() );
+ k3bcore->globalSettings()->setUseManualBufferSize( m_checkManualWritingBufferSize->isChecked() );
+ k3bcore->globalSettings()->setBufferSize( m_editWritingBufferSize->value() );
+ k3bcore->globalSettings()->setForce( m_checkForceUnsafeOperations->isChecked() );
+
+ // FIXME: remove this once libk3b does not use KConfig anymore for these values
+ k3bcore->globalSettings()->saveSettings( c );
+}
+
+
+void K3bBurningOptionTab::slotSetDefaultBufferSizes( bool b )
+{
+ if( !b ) {
+ m_editWritingBufferSize->setValue( 4 );
+ }
+}
+
+
+#include "k3bburningoptiontab.moc"
diff --git a/src/option/k3bburningoptiontab.h b/src/option/k3bburningoptiontab.h
new file mode 100644
index 0000000..8b71e06
--- /dev/null
+++ b/src/option/k3bburningoptiontab.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * $Id: k3bburningoptiontab.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_BURNING_OPTION_TAB_H
+#define K3B_BURNING_OPTION_TAB_H
+
+#include <qwidget.h>
+
+class QCheckBox;
+class QLabel;
+class QGroupBox;
+class QComboBox;
+class QString;
+class QSpinBox;
+class KIntNumInput;
+class QRadioButton;
+
+
+
+class K3bBurningOptionTab : public QWidget
+{
+Q_OBJECT
+
+ public:
+ K3bBurningOptionTab( QWidget* parent = 0, const char* name = 0 );
+ ~K3bBurningOptionTab();
+
+ void saveSettings();
+ void readSettings();
+
+ private slots:
+ void slotSetDefaultBufferSizes( bool );
+
+ private:
+ void setupGui();
+
+ QCheckBox* m_checkBurnfree;
+ QCheckBox* m_checkEject;
+ QCheckBox* m_checkAutoErasingRewritable;
+ QCheckBox* m_checkOverburn;
+ QCheckBox* m_checkManualWritingBufferSize;
+ KIntNumInput* m_editWritingBufferSize;
+ QCheckBox* m_checkAllowWritingAppSelection;
+ QCheckBox* m_checkForceUnsafeOperations;
+};
+
+
+#endif
diff --git a/src/option/k3bcddboptiontab.cpp b/src/option/k3bcddboptiontab.cpp
new file mode 100644
index 0000000..33b2349
--- /dev/null
+++ b/src/option/k3bcddboptiontab.cpp
@@ -0,0 +1,338 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bcddboptiontab.h"
+
+#include <qvariant.h>
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qtabwidget.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qstringlist.h>
+#include <qcombobox.h>
+#include <qtoolbutton.h>
+
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <krun.h>
+#include <klistview.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kdeversion.h>
+
+
+K3bCddbOptionTab::K3bCddbOptionTab( QWidget* parent, const char* name )
+ : base_K3bCddbOptionTab( parent, name )
+{
+ // fix all the margins and spacings that have been corrupted by QDesigner ;-)
+ // -----------------------------------------------------------------------------
+
+ base_K3bCddbOptionTabLayout->setMargin( 0 );
+ base_K3bCddbOptionTabLayout->setSpacing( KDialog::spacingHint() );
+
+ m_mainTabbed->page(0)->layout()->setMargin( KDialog::marginHint() );
+ m_mainTabbed->page(0)->layout()->setSpacing( KDialog::spacingHint() );
+ m_mainTabbed->page(1)->layout()->setMargin( KDialog::marginHint() );
+ m_mainTabbed->page(1)->layout()->setSpacing( KDialog::spacingHint() );
+
+// m_groupLocalDir->layout()->setMargin( 0 );
+// m_groupLocalDirLayout->setMargin( KDialog::marginHint() );
+// m_groupLocalDirLayout->setSpacing( KDialog::spacingHint() );
+
+// m_groupCddbServer->layout()->setMargin( 0 );
+// m_groupCddbServerLayout->setMargin( KDialog::marginHint() );
+// m_groupCddbServerLayout->setSpacing( KDialog::spacingHint() );
+
+ m_groupCgi->layout()->setMargin( 0 );
+ m_groupCgiLayout->setMargin( KDialog::marginHint() );
+ m_groupCgiLayout->setSpacing( KDialog::spacingHint() );
+
+ m_boxLocalDirectoryLayout->setSpacing( KDialog::spacingHint() );
+ m_boxCddbServerLayout->setSpacing( KDialog::spacingHint() );
+ // -----------------------------------------------------------------------------
+
+
+ m_viewLocalDir->setSorting(-1);
+ m_viewLocalDir->setAcceptDrops( true );
+ m_viewLocalDir->setDragEnabled( true );
+ m_viewLocalDir->setDropVisualizer( true );
+
+ m_viewCddbServer->setSorting(-1);
+ m_viewCddbServer->setAcceptDrops( true );
+ m_viewCddbServer->setDragEnabled( true );
+ m_viewCddbServer->setDropVisualizer( true );
+
+ m_comboCddbType->insertItem( "Http" );
+ m_comboCddbType->insertItem( "Cddbp" );
+
+
+ // set icons for the buttons
+ m_buttonAddLocalDir->setPixmap( SmallIcon("ok") );
+ m_buttonRemoveLocalDir->setPixmap( SmallIcon("stop") );
+ m_buttonLocalDirUp->setPixmap( SmallIcon("up") );
+ m_buttonLocalDirDown->setPixmap( SmallIcon("down") );
+ m_buttonAddCddbServer->setPixmap( SmallIcon("ok") );
+ m_buttonRemoveCddbServer->setPixmap( SmallIcon("stop") );
+ m_buttonCddbServerUp->setPixmap( SmallIcon("up") );
+ m_buttonCddbServerDown->setPixmap( SmallIcon("down") );
+
+
+ // setup connections
+ // -----------------------------------------------------------------------------
+ connect( m_buttonAddLocalDir, SIGNAL(clicked()), this, SLOT(slotLocalDirAdd()) );
+ connect( m_buttonRemoveLocalDir, SIGNAL(clicked()), this, SLOT(slotLocalDirRemove()) );
+ connect( m_buttonLocalDirUp, SIGNAL(clicked()), this, SLOT(slotLocalDirUp()) );
+ connect( m_buttonLocalDirDown, SIGNAL(clicked()), this, SLOT(slotLocalDirDown()) );
+
+ connect( m_buttonAddCddbServer, SIGNAL(clicked()), this, SLOT(slotCddbServerAdd()) );
+ connect( m_buttonRemoveCddbServer, SIGNAL(clicked()), this, SLOT(slotCddbServerRemove()) );
+ connect( m_buttonCddbServerUp, SIGNAL(clicked()), this, SLOT(slotCddbServerUp()) );
+ connect( m_buttonCddbServerDown, SIGNAL(clicked()), this, SLOT(slotCddbServerDown()) );
+
+ connect( m_editLocalDir, SIGNAL(textChanged(const QString&)), this, SLOT(enDisableButtons()) );
+ connect( m_editCddbServer, SIGNAL(textChanged(const QString&)), this, SLOT(enDisableButtons()) );
+ connect( m_viewLocalDir, SIGNAL(selectionChanged()), this, SLOT(enDisableButtons()) );
+ connect( m_viewCddbServer, SIGNAL(selectionChanged()), this, SLOT(enDisableButtons()) );
+ connect( m_comboCddbType, SIGNAL(highlighted(int)),
+ this, SLOT(slotServerTypeChanged()) );
+ connect( m_comboCddbType, SIGNAL(activated(int)),
+ this, SLOT(slotServerTypeChanged()) );
+ // -----------------------------------------------------------------------------
+
+ enDisableButtons();
+}
+
+
+K3bCddbOptionTab::~K3bCddbOptionTab()
+{
+}
+
+
+void K3bCddbOptionTab::readSettings()
+{
+ KConfig* c = kapp->config();
+
+ c->setGroup( "Cddb" );
+
+ // old config <= 0.7.3
+ QStringList cddbpServer = c->readListEntry( "cddbp server" );
+ QStringList httpServer = c->readListEntry( "http server" );
+
+ // new config
+ QStringList cddbServer = c->readListEntry( "cddb server" );
+
+ QStringList localCddbDirs = c->readPathListEntry( "local cddb dirs" );
+
+ m_checkRemoteCddb->setChecked( c->readBoolEntry( "use remote cddb", true ) );
+ m_checkUseLocalCddb->setChecked( c->readBoolEntry( "use local cddb query", true ) );
+ m_checkSaveLocalEntries->setChecked( c->readBoolEntry( "save cddb entries locally", true ) );
+ m_checkManualCgiPath->setChecked( c->readBoolEntry( "use manual cgi path", false ) );
+ m_editManualCgiPath->setText( c->readEntry( "cgi path", "/~cddb/cddb.cgi" ) );
+
+ if( localCddbDirs.isEmpty() )
+ localCddbDirs.append( "~/.cddb/" );
+
+ for( QStringList::const_iterator it = localCddbDirs.begin(); it != localCddbDirs.end(); ++it )
+ (void)new KListViewItem( m_viewLocalDir, m_viewLocalDir->lastItem(), *it );
+
+
+ // old config <= 0.7.3
+ if( !httpServer.isEmpty() ) {
+ for( QStringList::iterator it = httpServer.begin(); it != httpServer.end(); ++it ) {
+ cddbServer.append( "Http " + *it );
+ }
+ }
+ if( !cddbpServer.isEmpty() ) {
+ for( QStringList::iterator it = cddbpServer.begin(); it != cddbpServer.end(); ++it ) {
+ cddbServer.append( "Cddbp " + *it );
+ }
+ }
+
+ if( cddbServer.isEmpty() )
+ cddbServer.append( "Http freedb2.org:80" );
+
+ for( QStringList::const_iterator it = cddbServer.begin(); it != cddbServer.end(); ++it ) {
+ const QString& s = *it;
+ QStringList buf = QStringList::split( ":", s.mid( s.find(" ")+1 ) );
+ QString server = buf[0];
+ int port = buf[1].toInt();
+ if( s.startsWith("Http") )
+ (void)new KListViewItem( m_viewCddbServer, m_viewCddbServer->lastItem(), "Http", server, QString::number(port) );
+ else
+ (void)new KListViewItem( m_viewCddbServer, m_viewCddbServer->lastItem(), "Cddbp", server, QString::number(port) );
+ }
+
+ enDisableButtons();
+}
+
+
+void K3bCddbOptionTab::apply()
+{
+ KConfig* c = kapp->config();
+
+ c->setGroup( "Cddb" );
+
+ c->writeEntry( "use remote cddb", m_checkRemoteCddb->isChecked() );
+ c->writeEntry( "use local cddb query", m_checkUseLocalCddb->isChecked() );
+ c->writeEntry( "save cddb entries locally", m_checkSaveLocalEntries->isChecked() );
+ c->writeEntry( "use manual cgi path", m_checkManualCgiPath->isChecked() );
+ c->writeEntry( "cgi path", m_editManualCgiPath->text() );
+
+ QStringList cddbServer;
+ QStringList localCddbDirs;
+
+ QListViewItemIterator it( m_viewLocalDir );
+ while( it.current() ) {
+ localCddbDirs.append( it.current()->text(0) );
+ ++it;
+ }
+
+ QListViewItemIterator it1( m_viewCddbServer );
+ while( it1.current() ) {
+ cddbServer.append( it1.current()->text(0) + " " + it1.current()->text(1) + ":" + it1.current()->text(2) );
+ ++it1;
+ }
+
+ // new config
+ c->writeEntry( "cddb server", cddbServer );
+
+ // old config <= 0.7.3
+ if( c->hasKey( "http server" ) )
+ c->deleteEntry( "http server" );
+ if( c->hasKey( "cddbp server" ) )
+ c->deleteEntry( "cddbp server" );
+
+ c->writePathEntry( "local cddb dirs", localCddbDirs );
+}
+
+
+void K3bCddbOptionTab::slotLocalDirAdd()
+{
+ if( !m_editLocalDir->text().isEmpty() ) {
+ QString localDir( m_editLocalDir->text() );
+ QListViewItemIterator it( m_viewLocalDir );
+ while( it.current() ) {
+ if ( it.current()->text(0) == localDir )
+ return;
+ ++it;
+ }
+ (void)new KListViewItem( m_viewLocalDir, m_viewLocalDir->lastItem(),
+ localDir );
+
+ enDisableButtons();
+ }
+}
+
+
+void K3bCddbOptionTab::slotLocalDirRemove()
+{
+ if( QListViewItem* item = m_viewLocalDir->selectedItem() )
+ delete item;
+
+ enDisableButtons();
+}
+
+
+void K3bCddbOptionTab::slotCddbServerAdd()
+{
+ if( !m_editCddbServer->text().isEmpty() ) {
+ (void)new KListViewItem( m_viewCddbServer, m_viewCddbServer->lastItem(),
+ m_comboCddbType->currentText(),
+ m_editCddbServer->text(),
+ QString::number( m_editCddbPort->value() ) );
+
+ enDisableButtons();
+ }
+}
+
+
+void K3bCddbOptionTab::slotCddbServerRemove()
+{
+ if( QListViewItem* item = m_viewCddbServer->selectedItem() )
+ delete item;
+
+ enDisableButtons();
+}
+
+
+void K3bCddbOptionTab::enDisableButtons()
+{
+ m_buttonAddLocalDir->setDisabled( m_editLocalDir->text().isEmpty() );
+ m_buttonRemoveLocalDir->setDisabled( m_viewLocalDir->selectedItem() == 0 );
+ m_buttonLocalDirUp->setDisabled( m_viewLocalDir->selectedItem() == 0 ||
+ m_viewLocalDir->selectedItem() == m_viewLocalDir->firstChild() );
+ m_buttonLocalDirDown->setDisabled( m_viewLocalDir->selectedItem() == 0 ||
+ m_viewLocalDir->selectedItem() == m_viewLocalDir->lastItem() );
+
+ m_buttonAddCddbServer->setDisabled( m_editCddbServer->text().isEmpty() );
+ m_buttonRemoveCddbServer->setDisabled( m_viewCddbServer->selectedItem() == 0 );
+ m_buttonCddbServerUp->setDisabled( m_viewCddbServer->selectedItem() == 0 ||
+ m_viewCddbServer->selectedItem() == m_viewCddbServer->firstChild() );
+ m_buttonCddbServerDown->setDisabled( m_viewCddbServer->selectedItem() == 0 ||
+ m_viewCddbServer->selectedItem() == m_viewCddbServer->lastItem() );
+
+ if( m_viewLocalDir->childCount() <= 0 ) {
+ m_checkSaveLocalEntries->setChecked(false);
+ }
+ m_checkSaveLocalEntries->setDisabled( m_viewLocalDir->childCount() <= 0 );
+}
+
+
+void K3bCddbOptionTab::slotServerTypeChanged()
+{
+ m_editCddbPort->setValue( m_comboCddbType->currentText() == "Http" ? 80 : 8880 );
+}
+
+
+void K3bCddbOptionTab::slotLocalDirDown()
+{
+ QListViewItem* sel = m_viewLocalDir->selectedItem();
+ m_viewLocalDir->moveItem( sel, 0, sel->nextSibling() );
+ m_viewLocalDir->setSelected( sel, true );
+}
+
+
+void K3bCddbOptionTab::slotLocalDirUp()
+{
+ QListViewItem* sel = m_viewLocalDir->selectedItem();
+ m_viewLocalDir->moveItem( sel, 0, sel->itemAbove()->itemAbove() );
+ m_viewLocalDir->setSelected( sel, true );
+}
+
+
+void K3bCddbOptionTab::slotCddbServerDown()
+{
+ QListViewItem* sel = m_viewCddbServer->selectedItem();
+ m_viewCddbServer->moveItem( sel, 0, sel->nextSibling() );
+ m_viewCddbServer->setSelected( sel, true );
+}
+
+
+void K3bCddbOptionTab::slotCddbServerUp()
+{
+ QListViewItem* sel = m_viewCddbServer->selectedItem();
+ m_viewCddbServer->moveItem( sel, 0, sel->itemAbove()->itemAbove() );
+ m_viewCddbServer->setSelected( sel, true );
+}
+
+#include "k3bcddboptiontab.moc"
diff --git a/src/option/k3bcddboptiontab.h b/src/option/k3bcddboptiontab.h
new file mode 100644
index 0000000..bc89259
--- /dev/null
+++ b/src/option/k3bcddboptiontab.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3B_CDDB_OPTIONTAB_H
+#define K3B_CDDB_OPTIONTAB_H
+
+#include "base_k3bcddboptiontab.h"
+
+
+class K3bCddbOptionTab : public base_K3bCddbOptionTab
+{
+ Q_OBJECT
+
+ public:
+ K3bCddbOptionTab( QWidget* parent = 0, const char* name = 0 );
+ ~K3bCddbOptionTab();
+
+ public slots:
+ void readSettings();
+ void apply();
+
+ private slots:
+ void slotLocalDirAdd();
+ void slotLocalDirRemove();
+ void slotLocalDirDown();
+ void slotLocalDirUp();
+
+ void slotCddbServerAdd();
+ void slotCddbServerRemove();
+ void slotCddbServerDown();
+ void slotCddbServerUp();
+
+ void slotServerTypeChanged();
+
+ void enDisableButtons();
+};
+
+#endif
diff --git a/src/option/k3bdeviceoptiontab.cpp b/src/option/k3bdeviceoptiontab.cpp
new file mode 100644
index 0000000..65607c6
--- /dev/null
+++ b/src/option/k3bdeviceoptiontab.cpp
@@ -0,0 +1,94 @@
+/*
+ *
+ * $Id: k3bdeviceoptiontab.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdeviceoptiontab.h"
+#include <k3bdevicemanager.h>
+#include "k3bdevicewidget.h"
+#include <k3bglobals.h>
+#include <k3bcore.h>
+
+#include <qlabel.h>
+#include <qstring.h>
+#include <qlayout.h>
+#include <qcursor.h>
+#include <qapplication.h>
+
+#include <kapplication.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+
+
+K3bDeviceOptionTab::K3bDeviceOptionTab( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ QGridLayout* frameLayout = new QGridLayout( this );
+ frameLayout->setSpacing( KDialog::spacingHint() );
+ frameLayout->setMargin( 0 );
+
+
+ // Info Label
+ // ------------------------------------------------
+ m_labelDevicesInfo = new QLabel( this, "m_labelDevicesInfo" );
+ m_labelDevicesInfo->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter | QLabel::AlignLeft ) );
+ m_labelDevicesInfo->setText( i18n( "K3b tries to detect all your devices properly. "
+ "You can add devices that have not been detected and change "
+ "the black values by clicking in the list. If K3b is unable "
+ "to detect your drive, you need to modify their permissions "
+ "to give K3b write access to all devices." ) );
+ // ------------------------------------------------
+
+ m_deviceWidget = new K3bDeviceWidget( k3bcore->deviceManager(), this );
+
+ frameLayout->addWidget( m_labelDevicesInfo, 0, 0 );
+ frameLayout->addWidget( m_deviceWidget, 1, 0 );
+
+ connect( m_deviceWidget, SIGNAL(refreshButtonClicked()), this, SLOT(slotRefreshButtonClicked()) );
+}
+
+
+K3bDeviceOptionTab::~K3bDeviceOptionTab()
+{
+}
+
+
+void K3bDeviceOptionTab::readDevices()
+{
+ m_deviceWidget->init();
+}
+
+
+
+void K3bDeviceOptionTab::saveDevices()
+{
+ // save changes to deviceManager
+ m_deviceWidget->apply();
+
+ // save the config
+ k3bcore->deviceManager()->saveConfig( kapp->config() );
+}
+
+
+void K3bDeviceOptionTab::slotRefreshButtonClicked()
+{
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+ k3bcore->deviceManager()->clear();
+ k3bcore->deviceManager()->scanBus();
+ m_deviceWidget->init();
+ QApplication::restoreOverrideCursor();
+}
+
+#include "k3bdeviceoptiontab.moc"
diff --git a/src/option/k3bdeviceoptiontab.h b/src/option/k3bdeviceoptiontab.h
new file mode 100644
index 0000000..492b421
--- /dev/null
+++ b/src/option/k3bdeviceoptiontab.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * $Id: k3bdeviceoptiontab.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_DEVICE_OPTIONTAB_H
+#define K3B_DEVICE_OPTIONTAB_H
+
+#include <qwidget.h>
+
+class QLabel;
+class K3bDeviceWidget;
+
+
+class K3bDeviceOptionTab : public QWidget
+{
+Q_OBJECT
+
+ public:
+ K3bDeviceOptionTab( QWidget*, const char* name = 0 );
+ ~K3bDeviceOptionTab();
+
+ void readDevices();
+ void saveDevices();
+
+ private slots:
+ void slotRefreshButtonClicked();
+
+ private:
+ QLabel* m_labelDevicesInfo;
+ K3bDeviceWidget* m_deviceWidget;
+};
+
+
+
+#endif
diff --git a/src/option/k3bdevicewidget.cpp b/src/option/k3bdevicewidget.cpp
new file mode 100644
index 0000000..d7d1e36
--- /dev/null
+++ b/src/option/k3bdevicewidget.cpp
@@ -0,0 +1,404 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdevicewidget.h"
+#include "k3bdevicemanager.h"
+#include "k3bdevice.h"
+#include "k3bdeviceglobals.h"
+#include <k3blistview.h>
+
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <ksimpleconfig.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kio/global.h>
+
+#include <qgroupbox.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qheader.h>
+#include <qstring.h>
+#include <qcolor.h>
+#include <qptrlist.h>
+
+
+class K3bDeviceWidget::PrivateTempDevice
+{
+public:
+ PrivateTempDevice( K3bDevice::Device* d ) {
+ device = d;
+ cdrdaoDriver = d->cdrdaoDriver();
+ cdTextCapable = ( d->cdTextCapable() != 2 );
+ writer = d->burner();
+ }
+
+ K3bDevice::Device* device;
+ QString cdrdaoDriver;
+ bool cdTextCapable;
+ bool writer;
+};
+
+
+class K3bDeviceWidget::PrivateDeviceViewItem1 : public K3bListViewItem
+{
+public:
+ PrivateDeviceViewItem1( int type, PrivateTempDevice* dev, QListView* view, QListViewItem* after )
+ : K3bListViewItem( view, after ),
+ m_type(type) {
+ this->dev = dev;
+ init();
+ }
+
+ PrivateDeviceViewItem1( int type, PrivateTempDevice* dev, QListViewItem* item, QListViewItem* after )
+ : K3bListViewItem( item, after ),
+ m_type(type) {
+ this->dev = dev;
+ init();
+ }
+
+ void setText(int col, const QString& text) {
+ if( col == 1 ) {
+ switch(m_type) {
+ case t_cdrdaoDriver:
+ dev->cdrdaoDriver = text;
+ break;
+ case t_cdTextCapable:
+ if( dev->cdrdaoDriver != "auto" )
+ dev->cdTextCapable = ( text == i18n("yes") );
+ break;
+ }
+ }
+ }
+
+ QString text( int col ) const {
+ switch(m_type) {
+ case t_cdrdaoDriver:
+ return (col == 0 ? i18n("Cdrdao driver:") : dev->cdrdaoDriver );
+ break;
+ case t_cdTextCapable:
+ if( col == 0 )
+ return i18n("CD-Text capable:");
+ else {
+ if( dev->cdrdaoDriver == "auto" )
+ return "auto";
+ else return ( dev->cdTextCapable ? i18n("yes") : i18n("no") );
+ }
+ }
+ return "???";
+ }
+
+ enum itemType { t_cdrdaoDriver, t_cdTextCapable };
+
+ PrivateTempDevice* dev;
+
+private:
+ void init() {
+ static QStringList l;
+ static QStringList l2;
+
+ switch(m_type) {
+ case t_cdrdaoDriver:
+ if( l.isEmpty() )
+ for( int i = 0; i < 13; i++ )
+ l.append(K3bDevice::Device::cdrdao_drivers[i]);
+
+ setEditor( 1, COMBO, l );
+ break;
+ case t_cdTextCapable:
+ if( l2.isEmpty() ) {
+ l2.append(i18n("auto"));
+ l2.append(i18n("yes"));
+ l2.append(i18n("no"));
+ }
+
+ setEditor( 1, COMBO, l2 );
+ }
+ }
+
+ int m_type;
+};
+
+
+
+
+
+
+K3bDeviceWidget::K3bDeviceWidget( K3bDevice::DeviceManager* manager, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_deviceManager( manager )
+{
+ QGridLayout* frameLayout = new QGridLayout( this );
+ frameLayout->setSpacing( KDialog::spacingHint() );
+ frameLayout->setMargin( 0 );
+
+
+ // buttons
+ // ------------------------------------------------
+ QGridLayout* refreshButtonGrid = new QGridLayout;
+ refreshButtonGrid->setSpacing( KDialog::spacingHint() );
+ refreshButtonGrid->setMargin(0);
+ m_buttonRefreshDevices = new QPushButton( i18n( "Refresh" ), this, "m_buttonRefreshDevices" );
+ m_buttonAddDevice = new QPushButton( i18n( "Add Device..." ), this, "m_buttonAddDevice" );
+ QToolTip::add( m_buttonRefreshDevices, i18n( "Rescan the devices" ) );
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ refreshButtonGrid->addItem( spacer, 0, 0 );
+ refreshButtonGrid->addWidget( m_buttonRefreshDevices, 0, 2 );
+ refreshButtonGrid->addWidget( m_buttonAddDevice, 0, 1 );
+ // ------------------------------------------------
+
+
+ // Devices Box
+ // ------------------------------------------------
+ QGroupBox* groupDevices = new QGroupBox( 1, Qt::Vertical, i18n( "CD/DVD Drives" ), this );
+ groupDevices->layout()->setSpacing( KDialog::spacingHint() );
+ groupDevices->layout()->setMargin( KDialog::marginHint() );
+
+ m_viewDevices = new K3bListView( groupDevices, "m_viewDevicesReader" );
+ m_viewDevices->addColumn( "V" );
+ m_viewDevices->addColumn( "D" );
+ m_viewDevices->setAllColumnsShowFocus( true );
+ m_viewDevices->header()->hide();
+ m_viewDevices->setSorting( -1 );
+ m_viewDevices->setDoubleClickForEdit(false);
+ m_viewDevices->setAlternateBackground( QColor() );
+ m_viewDevices->setSelectionMode( QListView::NoSelection );
+ m_viewDevices->setFullWidth(true);
+ // ------------------------------------------------
+
+
+ frameLayout->addWidget( groupDevices, 0, 0 );
+ frameLayout->addLayout( refreshButtonGrid, 1, 0 );
+ // ------------------------------------------------
+
+ // temporary device lists settings
+ // ------------------------------------------------
+ m_tempDevices.setAutoDelete( true );
+ // ------------------------------------------------
+
+
+ // connections
+ // ------------------------------------------------
+ // connect( m_buttonRefreshDevices, SIGNAL(clicked()), this, SLOT(slotRefreshDevices()) );
+ connect( m_buttonRefreshDevices, SIGNAL(clicked()), this, SIGNAL(refreshButtonClicked()) );
+ connect( m_buttonAddDevice, SIGNAL(clicked()), this, SLOT(slotNewDevice()) );
+ connect( m_deviceManager, SIGNAL(changed()), this, SLOT(init()) );
+ // ------------------------------------------------
+}
+
+
+K3bDeviceWidget::~K3bDeviceWidget()
+{
+ m_tempDevices.clear();
+}
+
+
+void K3bDeviceWidget::init()
+{
+ // fill the temporary lists
+ m_tempDevices.clear();
+
+ // add the reading devices
+ for( QPtrListIterator<K3bDevice::Device> it( m_deviceManager->allDevices() ); *it; ++it )
+ m_tempDevices.append( new PrivateTempDevice( *it ) );
+
+ updateDeviceListViews();
+}
+
+
+void K3bDeviceWidget::updateDeviceListViews()
+{
+ m_viewDevices->clear();
+
+ // create the parent view items
+ // -----------------------------------------
+ m_writerParentViewItem = new QListViewItem( m_viewDevices, i18n("Writer Drives") );
+ m_writerParentViewItem->setPixmap( 0, SmallIcon( "cdwriter_unmount" ) );
+ // spacer item
+ (void)new QListViewItem( m_viewDevices );
+ m_readerParentViewItem = new QListViewItem( m_viewDevices, i18n("Readonly Drives") );
+ m_readerParentViewItem->setPixmap( 0, SmallIcon( "cdrom_unmount" ) );
+ // -----------------------------------------
+
+ QFont fBold( m_viewDevices->font() );
+ fBold.setBold(true);
+ QFont fItalic( m_viewDevices->font() );
+ fItalic.setItalic(true);
+
+ PrivateTempDevice* dev = m_tempDevices.first();
+ while( dev ) {
+ // create the root device item
+ K3bListViewItem* devRoot = new K3bListViewItem( (dev->writer ? m_writerParentViewItem : m_readerParentViewItem),
+ dev->device->vendor() + " " + dev->device->description() );
+ devRoot->setFont( 0, fBold );
+
+ // create the read-only info items
+ K3bListViewItem* systemDeviceItem = new K3bListViewItem( devRoot, i18n("System device name:") );
+ if( dev->device->interfaceType() == K3bDevice::SCSI )
+ systemDeviceItem->setText( 1, QString("%1 (%2)").arg(dev->device->devicename()).arg(dev->device->busTargetLun()) );
+ else
+ systemDeviceItem->setText( 1, dev->device->devicename() );
+ systemDeviceItem->setForegroundColor( 1, palette().disabled().foreground() );
+
+ K3bListViewItem* interfaceItem = new K3bListViewItem( devRoot, systemDeviceItem,
+ i18n("Interface type:"),
+ ( dev->device->interfaceType() == K3bDevice::SCSI ?
+ i18n("Generic SCSI") :
+ i18n("ATAPI") ) );
+ interfaceItem->setForegroundColor( 1, palette().disabled().foreground() );
+
+ K3bListViewItem* vendorItem = new K3bListViewItem( devRoot, interfaceItem,
+ i18n("Vendor:"),
+ dev->device->vendor() );
+ vendorItem->setForegroundColor( 1, palette().disabled().foreground() );
+ K3bListViewItem* modelItem = new K3bListViewItem( devRoot, vendorItem,
+ i18n("Description:"),
+ dev->device->description() );
+ modelItem->setForegroundColor( 1, palette().disabled().foreground() );
+ K3bListViewItem* versionItem = new K3bListViewItem( devRoot, modelItem,
+ i18n("Firmware:"),
+ dev->device->version() );
+ versionItem->setForegroundColor( 1, palette().disabled().foreground() );
+
+
+ // drive type
+ // --------------------------------
+ K3bListViewItem* typeItem = new K3bListViewItem( devRoot, versionItem,
+ i18n("Writes CD-R:"),
+ dev->device->writesCd() ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ typeItem = new K3bListViewItem( devRoot, typeItem,
+ i18n("Writes CD-RW:"),
+ dev->device->writesCdrw() ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ typeItem = new K3bListViewItem( devRoot, typeItem,
+ i18n("Reads DVD:"),
+ dev->device->readsDvd() ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ typeItem = new K3bListViewItem( devRoot, typeItem,
+ i18n("Writes DVD-R(W):"),
+ dev->device->writesDvdMinus() ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ typeItem = new K3bListViewItem( devRoot, typeItem,
+ i18n("Writes DVD-R Dual Layer:"),
+ (dev->device->type() & K3bDevice::DEVICE_DVD_R_DL)
+ ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ typeItem = new K3bListViewItem( devRoot, typeItem,
+ i18n("Writes DVD+R(W):"),
+ dev->device->writesDvdPlus() ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ typeItem = new K3bListViewItem( devRoot, typeItem,
+ i18n("Writes DVD+R Double Layer:"),
+ (dev->device->type() & K3bDevice::DEVICE_DVD_PLUS_R_DL)
+ ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ // --------------------------------
+
+
+ // now add the reader (both interfaces) items
+ if( dev->device->bufferSize() > 0 ) {
+ typeItem = new K3bListViewItem( devRoot, typeItem,
+ i18n("Buffer Size:"),
+ KIO::convertSizeFromKB(dev->device->bufferSize()) );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+ }
+
+ PrivateDeviceViewItem1* cdrdaoDriverItem = new PrivateDeviceViewItem1( PrivateDeviceViewItem1::t_cdrdaoDriver,
+ dev,
+ devRoot,
+ typeItem );
+
+
+ // now add the writer specific items
+ if( dev->writer ) {
+ PrivateDeviceViewItem1* cdTextItem = new PrivateDeviceViewItem1( PrivateDeviceViewItem1::t_cdTextCapable,
+ dev,
+ devRoot,
+ cdrdaoDriverItem );
+
+ typeItem = new K3bListViewItem( devRoot, cdTextItem,
+ i18n("Supports Burnfree:"),
+ dev->device->burnfree() ? i18n("yes") : i18n("no") );
+ typeItem->setForegroundColor( 1, palette().disabled().foreground() );
+
+
+ // and at last the write modes
+ (new K3bListViewItem( devRoot,
+ typeItem,
+ i18n("Write modes:"),
+ K3bDevice::writingModeString(dev->device->writingModes()) ))->setForegroundColor( 1, palette().disabled().foreground() );
+ }
+
+ devRoot->setOpen(true);
+
+ dev = m_tempDevices.next();
+ }
+
+ // create empty items
+ if( m_writerParentViewItem->childCount() == 0 ) {
+ K3bListViewItem* item = new K3bListViewItem( m_writerParentViewItem, i18n("none") );
+ item->setFont( 0, fItalic );
+ }
+ if( m_readerParentViewItem->childCount() == 0 ) {
+ K3bListViewItem* item = new K3bListViewItem( m_readerParentViewItem, i18n("none") );
+ item->setFont( 0, fItalic );
+ }
+
+ m_writerParentViewItem->setOpen( true );
+ m_readerParentViewItem->setOpen( true );
+}
+
+
+void K3bDeviceWidget::slotNewDevice()
+{
+ bool ok;
+ QString newDevicename = KInputDialog::getText( i18n("Location of New Drive"),
+ i18n("Please enter the device name where K3b should search\nfor a new drive (example: /dev/cdrom):"),
+ "/dev/", &ok, this );
+
+ if( ok ) {
+ if( K3bDevice::Device* dev = m_deviceManager->addDevice( newDevicename ) ) {
+ m_tempDevices.append( new PrivateTempDevice( dev ) );
+
+ updateDeviceListViews();
+ }
+ else
+ KMessageBox::error( this, i18n("Could not find an additional device at\n%1").arg(newDevicename), i18n("Error"), false );
+ }
+}
+
+
+void K3bDeviceWidget::apply()
+{
+ // update the devices
+ PrivateTempDevice* tempDev = m_tempDevices.first();
+ while( tempDev != 0 ) {
+ tempDev->device->setCdrdaoDriver( tempDev->cdrdaoDriver );
+ tempDev->device->setCdTextCapability( tempDev->cdTextCapable );
+
+ tempDev = m_tempDevices.next();
+ }
+}
+
+
+#include "k3bdevicewidget.moc"
diff --git a/src/option/k3bdevicewidget.h b/src/option/k3bdevicewidget.h
new file mode 100644
index 0000000..a874c94
--- /dev/null
+++ b/src/option/k3bdevicewidget.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * $Id: k3bdevicewidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDEVICEWIDGET_H
+#define K3BDEVICEWIDGET_H
+
+#include <qwidget.h>
+#include <qptrlist.h>
+#include "k3bdevice.h"
+#include "k3bdevicemanager.h"
+
+class QComboBox;
+class QLabel;
+class QGroupBox;
+class QPushButton;
+class QCheckBox;
+class K3bListView;
+class QString;
+class KIntNumInput;
+class QFrame;
+class QListViewItem;
+class QString;
+class QLineEdit;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bDeviceWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bDeviceWidget( K3bDevice::DeviceManager*, QWidget *parent = 0, const char *name = 0 );
+ ~K3bDeviceWidget();
+
+ public slots:
+ void init();
+ void apply();
+
+ signals:
+ void refreshButtonClicked();
+
+ private slots:
+ void slotNewDevice();
+ void updateDeviceListViews();
+
+ private:
+ class PrivateTempDevice;
+ class PrivateDeviceViewItem1;
+
+ /** list to save changes to the devices before applying */
+ QPtrList<PrivateTempDevice> m_tempDevices;
+
+ QListViewItem* m_writerParentViewItem;
+ QListViewItem* m_readerParentViewItem;
+
+ K3bDevice::DeviceManager* m_deviceManager;
+
+ K3bListView* m_viewDevices;
+ QPushButton* m_buttonRefreshDevices;
+ QPushButton* m_buttonAddDevice;
+};
+
+#endif
diff --git a/src/option/k3bexternalbinoptiontab.cpp b/src/option/k3bexternalbinoptiontab.cpp
new file mode 100644
index 0000000..d5c78bc
--- /dev/null
+++ b/src/option/k3bexternalbinoptiontab.cpp
@@ -0,0 +1,78 @@
+/*
+ *
+ * $Id: k3bexternalbinoptiontab.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bexternalbinoptiontab.h"
+#include <k3bexternalbinmanager.h>
+#include "k3bexternalbinwidget.h"
+
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <klistview.h>
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qfile.h>
+#include <qptrlist.h>
+
+
+
+K3bExternalBinOptionTab::K3bExternalBinOptionTab( K3bExternalBinManager* manager, QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_manager = manager;
+
+ QGridLayout* frameLayout = new QGridLayout( this );
+ frameLayout->setSpacing( KDialog::spacingHint() );
+ frameLayout->setMargin( 0 );
+
+ m_externalBinWidget = new K3bExternalBinWidget( manager, this );
+ frameLayout->addWidget( m_externalBinWidget, 1, 0 );
+
+ QLabel* m_labelInfo = new QLabel( this, "m_labelInfo" );
+ m_labelInfo->setText( i18n( "Specify the paths to the external programs that K3b needs to work properly, "
+ "or press \"Search\" to let K3b search for the programs." ) );
+ m_labelInfo->setScaledContents( false );
+ m_labelInfo->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter | QLabel::AlignLeft ) );
+
+ frameLayout->addWidget( m_labelInfo, 0, 0 );
+}
+
+
+K3bExternalBinOptionTab::~K3bExternalBinOptionTab()
+{
+}
+
+
+void K3bExternalBinOptionTab::readSettings()
+{
+ m_externalBinWidget->load();
+}
+
+
+void K3bExternalBinOptionTab::saveSettings()
+{
+ m_externalBinWidget->save();
+}
+
+
+#include "k3bexternalbinoptiontab.moc"
diff --git a/src/option/k3bexternalbinoptiontab.h b/src/option/k3bexternalbinoptiontab.h
new file mode 100644
index 0000000..8622579
--- /dev/null
+++ b/src/option/k3bexternalbinoptiontab.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * $Id: k3bexternalbinoptiontab.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_EXTERNALBIN_OPTIONTAB_H
+#define K3B_EXTERNALBIN_OPTIONTAB_H
+
+#include <qwidget.h>
+
+
+
+class QPushButton;
+class QListViewItem;
+class KListView;
+class K3bExternalBinManager;
+class K3bExternalBinWidget;
+
+
+class K3bExternalBinOptionTab : public QWidget
+{
+Q_OBJECT
+
+ public:
+ K3bExternalBinOptionTab( K3bExternalBinManager*, QWidget*, const char* name = 0 );
+ ~K3bExternalBinOptionTab();
+
+ void readSettings();
+ void saveSettings();
+
+ private:
+ K3bExternalBinManager* m_manager;
+
+ K3bExternalBinWidget* m_externalBinWidget;
+};
+
+
+
+#endif
diff --git a/src/option/k3bexternalbinwidget.cpp b/src/option/k3bexternalbinwidget.cpp
new file mode 100644
index 0000000..e1c62bb
--- /dev/null
+++ b/src/option/k3bexternalbinwidget.cpp
@@ -0,0 +1,318 @@
+/*
+ *
+ * $Id: k3bexternalbinwidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bexternalbinwidget.h"
+#include "k3bexternalbinmanager.h"
+
+#include <qpushbutton.h>
+#include <kdebug.h>
+#include <qtabwidget.h>
+#include <qlayout.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qregexp.h>
+#include <qfont.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qcursor.h>
+#include <qapplication.h>
+#include <qbitmap.h>
+
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <keditlistbox.h>
+#include <klistview.h>
+#include <kglobalsettings.h>
+#include <kdeversion.h>
+
+
+
+K3bExternalBinWidget::K3bExternalProgramViewItem::K3bExternalProgramViewItem( K3bExternalProgram* p, QListView* parent )
+ : K3bListViewItem( parent ), m_program(p)
+{
+ QFont f( listView()->font() );
+ f.setBold(true);
+ setFont( 0, f );
+ setBackgroundColor( 0, KGlobalSettings::alternateBackgroundColor() );
+ setBackgroundColor( 1, KGlobalSettings::alternateBackgroundColor() );
+ setBackgroundColor( 2, KGlobalSettings::alternateBackgroundColor() );
+ setText( 0, p->name() );
+ setSelectable( false );
+}
+
+
+K3bExternalBinWidget::K3bExternalBinViewItem::K3bExternalBinViewItem( K3bExternalBin* bin, K3bExternalProgramViewItem* parent )
+ : K3bListViewItem( parent ), m_bin( bin ), m_parent( parent )
+{
+ setText( 0, bin->path );
+ setText( 1, bin->version );
+ setText( 2, bin->features().join(", ") );
+
+ setDefault(false);
+}
+
+
+void K3bExternalBinWidget::K3bExternalBinViewItem::setDefault( bool b )
+{
+ static QPixmap s_emptyPix( (int)KIcon::SizeSmall, (int)KIcon::SizeSmall );
+ static bool s_emptyPixInitialized = false;
+ if( !s_emptyPixInitialized ) {
+ s_emptyPix.setMask( QBitmap( (int)KIcon::SizeSmall, (int)KIcon::SizeSmall, true ) );
+ s_emptyPixInitialized = true;
+ }
+
+ m_default = b;
+ if( b )
+ setPixmap( 0, SmallIcon( "ok" ) );
+ else
+ setPixmap( 0, s_emptyPix );
+}
+
+
+
+
+
+// ///////////////////////////////////////////////////////////
+//
+// K3BEXTERNALBINWIDGET
+//
+// //////////////////////////////////////////////////////////
+
+
+K3bExternalBinWidget::K3bExternalBinWidget( K3bExternalBinManager* manager, QWidget* parent, const char* name )
+ : QWidget( parent, name ), m_manager( manager )
+{
+ QGridLayout* mainGrid = new QGridLayout( this );
+ mainGrid->setMargin( 0 );
+ mainGrid->setSpacing( KDialog::spacingHint() );
+
+ m_mainTabWidget = new QTabWidget( this );
+ m_rescanButton = new QPushButton( i18n("&Search"), this );
+ mainGrid->addMultiCellWidget( m_mainTabWidget, 0, 0, 0, 1 );
+ mainGrid->addWidget( m_rescanButton, 1, 1 );
+ mainGrid->setColStretch( 0, 1 );
+ mainGrid->setRowStretch( 0, 1 );
+
+
+ // setup program tab
+ // ------------------------------------------------------------
+ QWidget* programTab = new QWidget( m_mainTabWidget );
+ QGridLayout* programTabLayout = new QGridLayout( programTab );
+ programTabLayout->setMargin( KDialog::marginHint() );
+ programTabLayout->setSpacing( KDialog::spacingHint() );
+ m_programView = new K3bListView( programTab );
+ m_defaultButton = new QPushButton( i18n("Set Default"), programTab );
+ QToolTip::add( m_defaultButton, i18n("Change the versions K3b should use.") );
+ QWhatsThis::add( m_defaultButton, i18n("<p>If K3b found more than one installed version of a program "
+ "it will choose one as the <em>default</em> which will be used "
+ "to do the work. If you want to change the default select the "
+ "wanted version and press this button.") );
+ programTabLayout->addMultiCellWidget( m_programView, 1, 1, 0, 1 );
+ programTabLayout->addWidget( m_defaultButton, 0, 1 );
+ programTabLayout->addWidget( new QLabel( i18n("Use the 'Default' button to change the versions K3b should use."),
+ programTab ), 0, 0 );
+ programTabLayout->setColStretch( 0, 1 );
+ programTabLayout->setRowStretch( 1, 1 );
+
+ m_programView->addColumn( i18n("Path") );
+ m_programView->addColumn( i18n("Version") );
+ m_programView->addColumn( i18n("Features") );
+ m_programView->setAllColumnsShowFocus(true);
+ m_programView->setFullWidth(true);
+ m_programView->setAlternateBackground( QColor() );
+#if KDE_IS_VERSION(3,4,0)
+ m_programView->setShadeSortColumn( false );
+#endif
+ m_mainTabWidget->addTab( programTab, i18n("Programs") );
+
+
+ // setup parameters tab
+ // ------------------------------------------------------------
+ QWidget* parametersTab = new QWidget( m_mainTabWidget );
+ QGridLayout* parametersTabLayout = new QGridLayout( parametersTab );
+ parametersTabLayout->setMargin( KDialog::marginHint() );
+ parametersTabLayout->setSpacing( KDialog::spacingHint() );
+ m_parameterView = new K3bListView( parametersTab );
+ parametersTabLayout->addWidget( m_parameterView, 1, 0 );
+ parametersTabLayout->addWidget( new QLabel( i18n("User parameters have to be separated by space."), parametersTab ), 0, 0 );
+
+ parametersTabLayout->setRowStretch( 1, 1 );
+
+ m_parameterView->addColumn( i18n("Program") );
+ m_parameterView->addColumn( i18n("Parameters") );
+ m_parameterView->setAllColumnsShowFocus(true);
+ m_parameterView->setFullWidth(true);
+ m_parameterView->setDefaultRenameAction( QListView::Accept );
+ m_parameterView->setDoubleClickForEdit( false );
+
+ m_mainTabWidget->addTab( parametersTab, i18n("User Parameters") );
+
+
+ // setup search path tab
+ // ------------------------------------------------------------
+ QWidget* searchPathTab = new QWidget( m_mainTabWidget );
+ QGridLayout* searchPathTabLayout = new QGridLayout( searchPathTab );
+ searchPathTabLayout->setMargin( KDialog::marginHint() );
+ searchPathTabLayout->setSpacing( KDialog::spacingHint() );
+ m_searchPathBox = new KEditListBox( i18n("Search Path"), searchPathTab, "searchPathBox", true );
+ searchPathTabLayout->addWidget( m_searchPathBox, 0, 0 );
+ searchPathTabLayout->addWidget( new QLabel( i18n("<qt><b>Hint:</b> to force K3b to use another than the "
+ "default name for the executable specify it in the search path.</qt>"),
+ searchPathTab ), 1, 0 );
+
+ searchPathTabLayout->setRowStretch( 0, 1 );
+
+ m_mainTabWidget->addTab( searchPathTab, i18n("Search Path") );
+
+
+ m_programRootItems.setAutoDelete( true );
+
+
+ connect( m_rescanButton, SIGNAL(clicked()), this, SLOT(rescan()) );
+ connect( m_defaultButton, SIGNAL(clicked()), this, SLOT(slotSetDefaultButtonClicked()) );
+ connect( m_programView, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotProgramSelectionChanged(QListViewItem*)) );
+
+ slotProgramSelectionChanged( 0 );
+}
+
+
+K3bExternalBinWidget::~K3bExternalBinWidget()
+{
+}
+
+void K3bExternalBinWidget::rescan()
+{
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+ saveSearchPath();
+ m_manager->search();
+ load();
+ QApplication::restoreOverrideCursor();
+}
+
+
+void K3bExternalBinWidget::load()
+{
+ m_programRootItems.clear();
+ m_parameterView->clear();
+
+ // load programs
+ const QMap<QString, K3bExternalProgram*>& map = m_manager->programs();
+ for( QMap<QString, K3bExternalProgram*>::const_iterator it = map.begin(); it != map.end(); ++it ) {
+ K3bExternalProgram* p = it.data();
+
+ K3bExternalProgramViewItem* pV = new K3bExternalProgramViewItem( p, m_programView );
+ m_programRootItems.append( pV );
+ // populate it
+ QPtrListIterator<K3bExternalBin> binIt( p->bins() );
+ for( ; binIt.current(); ++binIt ) {
+ K3bExternalBin* b = *binIt;
+
+ K3bExternalBinViewItem* bV = new K3bExternalBinViewItem( b, pV );
+ if( b == p->defaultBin() )
+ bV->setDefault(true);
+
+ pV->setOpen(true);
+ }
+
+ if( p->bins().isEmpty() )
+ pV->setText( 0, p->name() + i18n(" (not found)") );
+
+ // load user parameters
+ if( p->supportsUserParameters() ) {
+ K3bExternalProgramViewItem* paraV = new K3bExternalProgramViewItem( p, m_parameterView );
+ paraV->setText( 1, p->userParameters().join( " " ) );
+ paraV->setEditor( 1, K3bListViewItem::LINE );
+ }
+ }
+
+
+
+ // load search path
+ m_searchPathBox->clear();
+ m_searchPathBox->insertStringList( m_manager->searchPath() );
+}
+
+
+void K3bExternalBinWidget::save()
+{
+ saveSearchPath();
+
+
+ // save the default programs
+ QListViewItemIterator progIt( m_programView );
+ while( progIt.current() ) {
+ if( K3bExternalBinViewItem* bV = dynamic_cast<K3bExternalBinViewItem*>( progIt.current() ) ) {
+ if( bV->isDefault() )
+ bV->parentProgramItem()->program()->setDefault( bV->bin() );
+ }
+
+ ++progIt;
+ }
+
+
+ // save the user parameters
+ QListViewItemIterator paraIt( m_parameterView );
+ QRegExp reSpace( "\\s" );
+ while( paraIt.current() ) {
+ K3bExternalProgramViewItem* pV = (K3bExternalProgramViewItem*)paraIt.current();
+ pV->program()->setUserParameters( QStringList::split( reSpace, pV->text(1) ) );
+
+ ++paraIt;
+ }
+}
+
+
+void K3bExternalBinWidget::saveSearchPath()
+{
+ m_manager->setSearchPath( m_searchPathBox->items() );
+}
+
+
+void K3bExternalBinWidget::slotSetDefaultButtonClicked()
+{
+ // check if we are on a binItem
+ K3bExternalBinViewItem* item = dynamic_cast<K3bExternalBinViewItem*>( m_programView->selectedItem() );
+ if( item ) {
+ // remove all default flags
+ K3bExternalBinViewItem* bi = (K3bExternalBinViewItem*)item->parentProgramItem()->firstChild();
+ QListViewItemIterator it( bi );
+ while( it.current() && it.current()->parent() == item->parentProgramItem() ) {
+ ((K3bExternalBinViewItem*)it.current())->setDefault(false);
+ ++it;
+ }
+
+ item->setDefault(true);
+ }
+}
+
+
+void K3bExternalBinWidget::slotProgramSelectionChanged( QListViewItem* item )
+{
+ K3bExternalBinViewItem* bV = dynamic_cast<K3bExternalBinViewItem*>( item );
+ if( bV ) {
+ if( bV->isDefault() )
+ m_defaultButton->setEnabled(false);
+ else
+ m_defaultButton->setEnabled(true);
+ }
+ else
+ m_defaultButton->setEnabled(false);
+}
+
+#include "k3bexternalbinwidget.moc"
diff --git a/src/option/k3bexternalbinwidget.h b/src/option/k3bexternalbinwidget.h
new file mode 100644
index 0000000..fe2e163
--- /dev/null
+++ b/src/option/k3bexternalbinwidget.h
@@ -0,0 +1,103 @@
+/*
+ *
+ * $Id: k3bexternalbinwidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_EXTERNAL_BIN_WIDGET_H
+#define K3B_EXTERNAL_BIN_WIDGET_H
+
+
+#include <qwidget.h>
+#include <qptrlist.h>
+
+#include <k3blistview.h>
+
+
+class K3bExternalBinManager;
+class QPushButton;
+class QTabWidget;
+class KEditListBox;
+class K3bExternalProgram;
+class K3bExternalBin;
+
+
+class K3bExternalBinWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bExternalBinWidget( K3bExternalBinManager*, QWidget* parent = 0, const char* name = 0 );
+ ~K3bExternalBinWidget();
+
+ class K3bExternalBinViewItem;
+ class K3bExternalProgramViewItem;
+
+ public slots:
+ void rescan();
+ void load();
+ void save();
+
+ private slots:
+ void slotSetDefaultButtonClicked();
+ void slotProgramSelectionChanged( QListViewItem* );
+ void saveSearchPath();
+
+ private:
+ K3bExternalBinManager* m_manager;
+
+ QTabWidget* m_mainTabWidget;
+ K3bListView* m_programView;
+ K3bListView* m_parameterView;
+ KEditListBox* m_searchPathBox;
+
+ QPushButton* m_defaultButton;
+ QPushButton* m_rescanButton;
+
+ QPtrList<K3bExternalProgramViewItem> m_programRootItems;
+};
+
+
+class K3bExternalBinWidget::K3bExternalProgramViewItem : public K3bListViewItem
+{
+ public:
+ K3bExternalProgramViewItem( K3bExternalProgram* p, QListView* parent );
+
+ K3bExternalProgram* program() const { return m_program; }
+
+ private:
+ K3bExternalProgram* m_program;
+};
+
+
+
+class K3bExternalBinWidget::K3bExternalBinViewItem : public K3bListViewItem
+{
+ public:
+ K3bExternalBinViewItem( K3bExternalBin* bin, K3bExternalProgramViewItem* parent );
+
+ K3bExternalBin* bin() const { return m_bin; }
+ K3bExternalProgramViewItem* parentProgramItem() const { return m_parent; }
+
+ bool isDefault() const { return m_default; }
+ void setDefault( bool b );
+
+ private:
+ K3bExternalBin* m_bin;
+ K3bExternalProgramViewItem* m_parent;
+
+ bool m_default;
+};
+
+
+#endif
diff --git a/src/option/k3bmiscoptiontab.cpp b/src/option/k3bmiscoptiontab.cpp
new file mode 100644
index 0000000..d81e565
--- /dev/null
+++ b/src/option/k3bmiscoptiontab.cpp
@@ -0,0 +1,187 @@
+/*
+ *
+ * $Id: k3bmiscoptiontab.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bmiscoptiontab.h"
+
+#include <k3bpluginmanager.h>
+#include <k3baudiooutputplugin.h>
+#include <k3baudioserver.h>
+#include <k3bcore.h>
+#include <k3bservicemenuinstaller.h>
+#include <k3binteractiondialog.h>
+#include <k3bintmapcombobox.h>
+
+#include <qcheckbox.h>
+#include <qfileinfo.h>
+#include <qradiobutton.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdialog.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kurlrequester.h>
+#include <kcombobox.h>
+
+
+K3bMiscOptionTab::K3bMiscOptionTab(QWidget *parent, const char *name )
+ : base_K3bMiscOptionTab(parent,name)
+{
+ m_editTempDir->setMode( KFile::Directory );
+ connect( m_buttonConfigureAudioOutput, SIGNAL(clicked()),
+ this, SLOT(slotConfigureAudioOutput()) );
+
+ m_comboActionDialogSettings->insertItem( K3bInteractionDialog::LOAD_K3B_DEFAULTS,
+ i18n("Default Settings"),
+ i18n("Load the K3b Defaults at dialog startup.") );
+ m_comboActionDialogSettings->insertItem( K3bInteractionDialog::LOAD_SAVED_SETTINGS,
+ i18n("Saved Settings"),
+ i18n("Load the settings saved by the user at dialog startup.") );
+ m_comboActionDialogSettings->insertItem( K3bInteractionDialog::LOAD_LAST_SETTINGS,
+ i18n("Last Used Settings"),
+ i18n("Load the last used settings at dialog startup.") );
+ m_comboActionDialogSettings->addGlobalWhatsThisText( i18n("K3b handles three sets of settings in action dialogs "
+ "(action dialogs include the CD Copy dialog or the Audio CD "
+ "project dialog):"),
+ i18n("One of these sets is loaded once an action dialog is opened. "
+ "This setting defines which set it will be.") );
+}
+
+
+K3bMiscOptionTab::~K3bMiscOptionTab()
+{
+}
+
+
+void K3bMiscOptionTab::readSettings()
+{
+ KConfig* c = kapp->config();
+ c->setGroup( "General Options" );
+ m_checkSaveOnExit->setChecked( c->readBoolEntry( "ask_for_saving_changes_on_exit", true ) );
+ m_checkShowSplash->setChecked( c->readBoolEntry("Show splash", true) );
+ m_checkShowProgressOSD->setChecked( c->readBoolEntry( "Show progress OSD", true ) );
+ m_checkHideMainWindowWhileWriting->setChecked( c->readBoolEntry( "hide main window while writing", false ) );
+ m_checkKeepDialogsOpen->setChecked( c->readBoolEntry( "keep action dialogs open", false ) );
+ m_comboActionDialogSettings->setSelectedValue( c->readNumEntry( "action dialog startup settings",
+ K3bInteractionDialog::LOAD_SAVED_SETTINGS ) );
+ m_checkSystemConfig->setChecked( c->readBoolEntry( "check system config", true ) );
+
+ QString tempdir = c->readPathEntry( "Temp Dir", KGlobal::dirs()->resourceDirs( "tmp" ).first() );
+ m_editTempDir->setURL( tempdir );
+
+// if( c->readEntry( "Multiple Instances", "smart" ) == "smart" )
+// m_radioMultipleInstancesSmart->setChecked(true);
+// else
+// m_radioMultipleInstancesNew->setChecked(true);
+
+ // Audio Output
+ m_comboAudioOutputSystem->clear();
+ QPtrList<K3bPlugin> fl = k3bcore->pluginManager()->plugins( "AudioOutput" );
+ for( QPtrListIterator<K3bPlugin> it( fl ); it.current(); ++it ) {
+ K3bAudioOutputPlugin* f = static_cast<K3bAudioOutputPlugin*>( it.current() );
+ m_comboAudioOutputSystem->insertItem( QString::fromLocal8Bit(f->soundSystem()) );
+ }
+
+ m_comboAudioOutputSystem->setCurrentItem( c->readEntry( "Audio Output System", "arts" ), false );
+ m_buttonConfigureAudioOutput->setEnabled( m_comboAudioOutputSystem->count() > 0 );
+
+ K3bServiceInstaller si;
+ m_checkKonqiIntegration->setChecked( si.allInstalled() );
+}
+
+
+bool K3bMiscOptionTab::saveSettings()
+{
+ KConfig* c = kapp->config();
+ c->setGroup( "General Options" );
+ c->writeEntry( "ask_for_saving_changes_on_exit", m_checkSaveOnExit->isChecked() );
+ c->writeEntry( "Show splash", m_checkShowSplash->isChecked() );
+ c->writeEntry( "Show progress OSD", m_checkShowProgressOSD->isChecked() );
+ c->writeEntry( "hide main window while writing", m_checkHideMainWindowWhileWriting->isChecked() );
+ c->writeEntry( "keep action dialogs open", m_checkKeepDialogsOpen->isChecked() );
+ c->writeEntry( "check system config", m_checkSystemConfig->isChecked() );
+ c->writeEntry( "action dialog startup settings", m_comboActionDialogSettings->selectedValue() );
+
+ QString tempDir = m_editTempDir->url();
+ QFileInfo fi( tempDir );
+
+ if( fi.isRelative() ) {
+ fi.setFile( fi.absFilePath() );
+ }
+
+ if( !fi.exists() ) {
+ if( KMessageBox::questionYesNo( this, i18n("Directory (%1) does not exist. Create?").arg(tempDir),
+ i18n("Create Directory"), i18n("Create"), KStdGuiItem::cancel() ) == KMessageBox::Yes ) {
+ if( !KStandardDirs::makeDir( fi.absFilePath() ) ) {
+ KMessageBox::error( this, i18n("Unable to create directory %1").arg(tempDir) );
+ return false;
+ }
+ }
+ else {
+ // the dir does not exist and the user doesn't want to create it
+ return false;
+ }
+ }
+
+ if( fi.isFile() ) {
+ KMessageBox::information( this, i18n("You specified a file for the temporary directory. "
+ "K3b will use its base path as the temporary directory."),
+ i18n("Warning"),
+ "temp file only using base path" );
+ fi.setFile( fi.dirPath() );
+ }
+
+ // check for writing permission
+ if( !fi.isWritable() ) {
+ KMessageBox::error( this, i18n("You do not have permission to write to %1.").arg(fi.absFilePath()) );
+ return false;
+ }
+
+ m_editTempDir->setURL( fi.absFilePath() );
+
+ c->writePathEntry( "Temp Dir", m_editTempDir->url() );
+
+// if( m_radioMultipleInstancesSmart->isChecked() )
+// c->writeEntry( "Multiple Instances", "smart" );
+// else
+// c->writeEntry( "Multiple Instances", "always_new" );
+
+ // Audio Output System
+ if( m_comboAudioOutputSystem->count() > 0 ) {
+ c->writeEntry( "Audio Output System", m_comboAudioOutputSystem->currentText() );
+ K3bAudioServer::instance()->setOutputMethod( m_comboAudioOutputSystem->currentText().local8Bit() );
+ }
+
+ K3bServiceInstaller si;
+ if( m_checkKonqiIntegration->isChecked() )
+ si.install( this );
+ else
+ si.remove( this );
+
+ return true;
+}
+
+
+void K3bMiscOptionTab::slotConfigureAudioOutput()
+{
+ QString system = m_comboAudioOutputSystem->currentText();
+ if( K3bAudioOutputPlugin* plugin = K3bAudioServer::findOutputPlugin( system.local8Bit() ) ) {
+ k3bcore->pluginManager()->execPluginDialog( plugin, this );
+ }
+}
+
+#include "k3bmiscoptiontab.moc"
diff --git a/src/option/k3bmiscoptiontab.h b/src/option/k3bmiscoptiontab.h
new file mode 100644
index 0000000..6e5ded6
--- /dev/null
+++ b/src/option/k3bmiscoptiontab.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * $Id: k3bmiscoptiontab.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BMISCOPTIONTAB_H
+#define K3BMISCOPTIONTAB_H
+
+#include "base_k3bmiscoptiontab.h"
+
+class QCheckBox;
+class KURLRequester;
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bMiscOptionTab : public base_K3bMiscOptionTab
+{
+ Q_OBJECT
+
+ public:
+ K3bMiscOptionTab(QWidget *parent=0, const char *name=0);
+ ~K3bMiscOptionTab();
+
+ void readSettings();
+ bool saveSettings();
+
+ private slots:
+ void slotConfigureAudioOutput();
+};
+
+#endif
diff --git a/src/option/k3bnotifyoptiontab.cpp b/src/option/k3bnotifyoptiontab.cpp
new file mode 100644
index 0000000..60ddc7c
--- /dev/null
+++ b/src/option/k3bnotifyoptiontab.cpp
@@ -0,0 +1,61 @@
+/*
+ *
+ * $Id: k3bnotifyoptiontab.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include <kdeversion.h>
+
+#include "k3bnotifyoptiontab.h"
+
+#include <knotifydialog.h>
+#include <kdebug.h>
+
+#include <qlayout.h>
+
+
+
+K3bNotifyOptionTab::K3bNotifyOptionTab( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_notifyWidget = new KNotify::KNotifyWidget( this );
+
+ QHBoxLayout* box = new QHBoxLayout( this );
+ box->addWidget( m_notifyWidget );
+}
+
+
+K3bNotifyOptionTab::~K3bNotifyOptionTab()
+{
+}
+
+
+void K3bNotifyOptionTab::readSettings()
+{
+ m_notifyWidget->clear();
+ KNotify::Application* app = m_notifyWidget->addApplicationEvents( "k3b/eventsrc" );
+ if( app )
+ m_notifyWidget->addVisibleApp(app);
+ else
+ kdDebug() << "(K3bNotifyOptionTab) could not find K3b eventsrc." << endl;
+}
+
+
+bool K3bNotifyOptionTab::saveSettings()
+{
+ m_notifyWidget->save();
+
+ return true;
+}
+
+#include "k3bnotifyoptiontab.moc"
diff --git a/src/option/k3bnotifyoptiontab.h b/src/option/k3bnotifyoptiontab.h
new file mode 100644
index 0000000..03314dc
--- /dev/null
+++ b/src/option/k3bnotifyoptiontab.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * $Id: k3bnotifyoptiontab.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef _K3B_NOTIFY_OPTIONTAB_H_
+#define _K3B_NOTIFY_OPTIONTAB_H_
+
+#include <qwidget.h>
+
+namespace KNotify {
+ class KNotifyWidget;
+}
+
+
+class K3bNotifyOptionTab : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bNotifyOptionTab( QWidget* parent = 0, const char* name = 0 );
+ ~K3bNotifyOptionTab();
+
+ void readSettings();
+ bool saveSettings();
+
+ private:
+ KNotify::KNotifyWidget* m_notifyWidget;
+};
+
+#endif
diff --git a/src/option/k3boptiondialog.cpp b/src/option/k3boptiondialog.cpp
new file mode 100644
index 0000000..d0ba7ce
--- /dev/null
+++ b/src/option/k3boptiondialog.cpp
@@ -0,0 +1,258 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3boptiondialog.h"
+#include <k3bcore.h>
+#include "k3bcddboptiontab.h"
+#include "k3bdeviceoptiontab.h"
+#include "k3bburningoptiontab.h"
+#include "k3bexternalbinoptiontab.h"
+#include "k3bmiscoptiontab.h"
+#include "k3bthemeoptiontab.h"
+#include "k3bpluginoptiontab.h"
+#include <k3bsystemproblemdialog.h>
+
+
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qtabwidget.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kconfig.h>
+#include <kdeversion.h>
+#include "k3bnotifyoptiontab.h"
+
+
+// TODO: handle the default-settings
+
+K3bOptionDialog::K3bOptionDialog(QWidget *parent, const char *name, bool modal )
+ : KDialogBase( IconList, i18n("Settings"), Apply|Ok|Cancel, Ok, parent,name, modal, true)
+{
+ setupMiscPage();
+ setupDevicePage();
+ setupProgramsPage();
+ setupCddbPage();
+ setupNotifyPage();
+ setupPluginPage();
+ setupThemePage();
+ setupBurningPage();
+
+ m_externalBinOptionTab->readSettings();
+ m_cddbOptionTab->readSettings();
+ m_deviceOptionTab->readDevices();
+ m_burningOptionTab->readSettings();
+ m_miscOptionTab->readSettings();
+ m_notifyOptionTab->readSettings();
+ m_pluginOptionTab->readSettings();
+ m_themeOptionTab->readSettings();
+
+ // if we don't do this the dialog start really huge
+ // because of the label in the device-tab
+ resize( 700, 500 );
+
+ showPage( 0 );
+}
+
+
+K3bOptionDialog::~K3bOptionDialog()
+{
+}
+
+
+void K3bOptionDialog::slotOk()
+{
+ if( saveSettings() ) {
+ accept();
+
+ k3bcore->config()->setGroup( "General Options" );
+ if( k3bcore->config()->readBoolEntry( "check system config", true ) )
+ K3bSystemProblemDialog::checkSystem();
+ }
+}
+
+void K3bOptionDialog::slotApply()
+{
+ saveSettings();
+}
+
+
+bool K3bOptionDialog::saveSettings()
+{
+ // save all the shit!
+ m_cddbOptionTab->apply();
+ m_deviceOptionTab->saveDevices();
+ m_burningOptionTab->saveSettings();
+ m_externalBinOptionTab->saveSettings();
+ m_notifyOptionTab->saveSettings();
+
+ m_themeOptionTab->saveSettings();
+
+ if( !m_miscOptionTab->saveSettings() )
+ return false;
+
+ return true;
+}
+
+
+void K3bOptionDialog::slotDefault()
+{
+ switch( activePageIndex() )
+ {
+ case 0: // device page
+
+ break;
+ case 1: // programs page
+ break;
+ default:
+ break;
+ }
+}
+
+
+void K3bOptionDialog::setupBurningPage()
+{
+ QFrame* frame = addPage( i18n("Advanced"), i18n("Advanced Settings"),
+ KGlobal::instance()->iconLoader()->loadIcon( "cdwriter_unmount", KIcon::NoGroup, KIcon::SizeMedium ) );
+
+ QGridLayout* _frameLayout = new QGridLayout( frame );
+ _frameLayout->setSpacing( 0 );
+ _frameLayout->setMargin( 0 );
+
+ m_burningOptionTab = new K3bBurningOptionTab( frame );
+ _frameLayout->addWidget( m_burningOptionTab, 0, 0 );
+}
+
+
+void K3bOptionDialog::setupProgramsPage()
+{
+ QFrame* frame = addPage( i18n("Programs"), i18n("Setup External Programs"),
+ KGlobal::instance()->iconLoader()->loadIcon( "exec", KIcon::NoGroup, KIcon::SizeMedium ) );
+
+ QGridLayout* _frameLayout = new QGridLayout( frame );
+ _frameLayout->setSpacing( 0 );
+ _frameLayout->setMargin( 0 );
+
+ m_externalBinOptionTab = new K3bExternalBinOptionTab( k3bcore->externalBinManager(), frame );
+ _frameLayout->addWidget( m_externalBinOptionTab, 0, 0 );
+}
+
+
+void K3bOptionDialog::setupCddbPage()
+{
+ QFrame* frame = addPage( i18n("CDDB"), i18n("Setup the CDDB Server"),
+ KGlobal::instance()->iconLoader()->loadIcon( "connect_established", KIcon::NoGroup, KIcon::SizeMedium ) );
+
+ QGridLayout* mainGrid = new QGridLayout( frame );
+ mainGrid->setSpacing(0);
+ mainGrid->setMargin(0);
+ // QTabWidget *_tab = new QTabWidget( frame );
+ m_cddbOptionTab = new K3bCddbOptionTab( frame, "cddbremotepage");
+ // m_cddbLocalTab = new K3bCddbLocalDBTab( frame, "cddblocalpage");
+// _tab->addTab( m_cddbOptionTab, i18n("Remote") );
+// _tab->addTab( m_cddbLocalTab, i18n("Local") );
+ //mainGrid->addWidget( m_cddbOptionTab, 0, 0 );
+ mainGrid->addWidget( m_cddbOptionTab, 0, 0 );
+}
+
+
+void K3bOptionDialog::setupDevicePage()
+{
+ QFrame* frame = addPage( i18n("Devices"), i18n("Setup Devices"),
+ KGlobal::instance()->iconLoader()->loadIcon( "blockdevice", KIcon::NoGroup, KIcon::SizeMedium ) );
+
+ QHBoxLayout* box = new QHBoxLayout( frame );
+ box->setSpacing(0);
+ box->setMargin(0);
+ m_deviceOptionTab = new K3bDeviceOptionTab( frame, "deviceOptionTab" );
+ box->addWidget( m_deviceOptionTab );
+}
+
+
+void K3bOptionDialog::setupMiscPage()
+{
+ QFrame* frame = addPage( i18n("Misc"), i18n("Miscellaneous Settings"),
+ KGlobal::instance()->iconLoader()->loadIcon( "misc", KIcon::NoGroup, KIcon::SizeMedium ) );
+
+ QVBoxLayout* box = new QVBoxLayout( frame );
+ box->setSpacing( 0 );
+ box->setMargin( 0 );
+
+ m_miscOptionTab = new K3bMiscOptionTab( frame );
+ box->addWidget( m_miscOptionTab );
+}
+
+
+void K3bOptionDialog::setupNotifyPage()
+{
+ QFrame* frame = addPage( i18n("Notifications"), i18n("System Notifications"),
+ KGlobal::instance()->iconLoader()->loadIcon( "knotify",
+ KIcon::NoGroup, KIcon::SizeMedium ) );
+ QVBoxLayout* box = new QVBoxLayout( frame );
+ box->setSpacing( 0 );
+ box->setMargin( 0 );
+
+ m_notifyOptionTab = new K3bNotifyOptionTab( frame );
+ box->addWidget( m_notifyOptionTab );
+}
+
+
+void K3bOptionDialog::setupPluginPage()
+{
+ QFrame* frame = addPage( i18n("Plugins"), i18n("K3b Plugin Configuration"),
+ KGlobal::instance()->iconLoader()->loadIcon( "gear",
+ KIcon::NoGroup, KIcon::SizeMedium ) );
+ QVBoxLayout* box = new QVBoxLayout( frame );
+ box->setSpacing( 0 );
+ box->setMargin( 0 );
+
+ m_pluginOptionTab = new K3bPluginOptionTab( frame );
+ box->addWidget( m_pluginOptionTab );
+}
+
+
+void K3bOptionDialog::setupThemePage()
+{
+ QFrame* frame = addPage( i18n("Themes"), i18n("K3b GUI Themes"),
+ KGlobal::instance()->iconLoader()->loadIcon( "style",
+ KIcon::NoGroup, KIcon::SizeMedium ) );
+ QVBoxLayout* box = new QVBoxLayout( frame );
+ box->setSpacing( 0 );
+ box->setMargin( 0 );
+
+ m_themeOptionTab = new K3bThemeOptionTab( frame );
+ box->addWidget( m_themeOptionTab );
+}
+
+
+// void K3bOptionDialog::addOptionPage( QWidget* widget,
+// const QString& name,
+// const QString& header,
+// const QPixmap& icon )
+// {
+// QFrame* frame = addPage( name, header, icon );
+
+// QVBoxLayout* box = new QVBoxLayout( frame );
+// box->setSpacing( 0 );
+// box->setMargin( 0 );
+
+// widget->reparent( frame );
+// box->addWidget( widget );
+// }
+
+
+#include "k3boptiondialog.moc"
diff --git a/src/option/k3boptiondialog.h b/src/option/k3boptiondialog.h
new file mode 100644
index 0000000..1f417b6
--- /dev/null
+++ b/src/option/k3boptiondialog.h
@@ -0,0 +1,91 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BOPTIONDIALOG_H
+#define K3BOPTIONDIALOG_H
+
+#include <kdialogbase.h>
+
+class K3bCddbOptionTab;
+class K3bDeviceOptionTab;
+class K3bBurningOptionTab;
+class K3bExternalBinOptionTab;
+class K3bMiscOptionTab;
+class K3bNotifyOptionTab;
+class K3bPluginOptionTab;
+class K3bThemeOptionTab;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bOptionDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bOptionDialog(QWidget *parent=0, const char *name=0, bool modal = true);
+ ~K3bOptionDialog();
+
+ enum m_configPageIndex { Burning = 0, Devices = 1, Programs = 2, Cddb = 3 };
+
+/* void addOptionPage( QWidget* widget, */
+/* const QString& name, */
+/* const QString& header, */
+/* const QPixmap& icon ); */
+
+ protected slots:
+ void slotOk();
+ void slotApply();
+ void slotDefault();
+
+ private:
+ bool saveSettings();
+
+ // programs tab
+ K3bExternalBinOptionTab* m_externalBinOptionTab;
+ void setupProgramsPage();
+
+ // device tab
+ K3bDeviceOptionTab* m_deviceOptionTab;
+ void setupDevicePage();
+
+ // burning tab
+ void setupBurningPage();
+ K3bBurningOptionTab* m_burningOptionTab;
+
+ // cddb tabs
+ K3bCddbOptionTab *m_cddbOptionTab;
+ void setupCddbPage();
+
+ // misc options
+ K3bMiscOptionTab* m_miscOptionTab;
+ void setupMiscPage();
+
+ // notify options
+ K3bNotifyOptionTab* m_notifyOptionTab;
+ void setupNotifyPage();
+
+ // plugin options
+ K3bPluginOptionTab* m_pluginOptionTab;
+ void setupPluginPage();
+
+ // theme options
+ K3bThemeOptionTab* m_themeOptionTab;
+ void setupThemePage();
+};
+
+#endif
diff --git a/src/option/k3bpluginoptiontab.cpp b/src/option/k3bpluginoptiontab.cpp
new file mode 100644
index 0000000..59d7b74
--- /dev/null
+++ b/src/option/k3bpluginoptiontab.cpp
@@ -0,0 +1,137 @@
+/*
+ *
+ * $Id: k3bpluginoptiontab.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bpluginoptiontab.h"
+
+
+#include <k3bpluginmanager.h>
+#include <k3bplugin.h>
+#include <k3bpluginconfigwidget.h>
+#include <k3blistview.h>
+#include <k3bcore.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kconfig.h>
+#include <kglobalsettings.h>
+#include <kdeversion.h>
+
+#include <qstringlist.h>
+#include <qpushbutton.h>
+
+
+class K3bPluginOptionTab::PluginViewItem : public K3bListViewItem
+{
+public:
+ PluginViewItem( K3bPlugin* p, KListViewItem* parent )
+ : K3bListViewItem( parent ),
+ plugin(p) {
+ const K3bPluginInfo& info = p->pluginInfo();
+ setText( 0, info.name() );
+ if( !info.author().isEmpty() ) {
+ if( info.email().isEmpty() )
+ setText( 1, info.author() );
+ else
+ setText( 1, info.author() + " <" + info.email() + ">" );
+ }
+ setText( 2, info.version() );
+ setText( 3, info.comment() );
+ setText( 4, info.licence() );
+ }
+
+ K3bPlugin* plugin;
+};
+
+
+
+K3bPluginOptionTab::K3bPluginOptionTab( QWidget* parent, const char* name )
+ : base_K3bPluginOptionTab( parent, name )
+{
+#if KDE_IS_VERSION(3,4,0)
+ m_viewPlugins->setShadeSortColumn( false );
+#endif
+ m_viewPlugins->addColumn( i18n("Name") );
+ m_viewPlugins->addColumn( i18n("Author") );
+ m_viewPlugins->addColumn( i18n("Version") );
+ m_viewPlugins->addColumn( i18n("Description") );
+ m_viewPlugins->addColumn( i18n("License") );
+ m_viewPlugins->setAlternateBackground( QColor() );
+ m_viewPlugins->setAllColumnsShowFocus(true);
+
+ connect( m_viewPlugins, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)), this, SLOT(slotConfigureButtonClicked()) );
+ connect( m_buttonConfigure, SIGNAL(clicked()), this, SLOT(slotConfigureButtonClicked()) );
+ connect( m_viewPlugins, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) );
+}
+
+
+K3bPluginOptionTab::~K3bPluginOptionTab()
+{
+}
+
+
+void K3bPluginOptionTab::readSettings()
+{
+ m_viewPlugins->clear();
+ QStringList groups = k3bcore->pluginManager()->groups();
+ for( QStringList::const_iterator it = groups.begin();
+ it != groups.end(); ++it ) {
+ const QString& group = *it;
+
+ K3bListViewItem* groupViewItem = new K3bListViewItem( m_viewPlugins,
+ m_viewPlugins->lastChild(),
+ group );
+ QFont f( font() );
+ f.setBold(true);
+ groupViewItem->setFont( 0, f );
+ groupViewItem->setBackgroundColor( 0, KGlobalSettings::alternateBackgroundColor() );
+ groupViewItem->setBackgroundColor( 1, KGlobalSettings::alternateBackgroundColor() );
+ groupViewItem->setBackgroundColor( 2, KGlobalSettings::alternateBackgroundColor() );
+ groupViewItem->setBackgroundColor( 3, KGlobalSettings::alternateBackgroundColor() );
+ groupViewItem->setBackgroundColor( 4, KGlobalSettings::alternateBackgroundColor() );
+ groupViewItem->setSelectable( false );
+
+ QPtrList<K3bPlugin> fl = k3bcore->pluginManager()->plugins( group );
+ for( QPtrListIterator<K3bPlugin> fit( fl ); fit.current(); ++fit )
+ (void)new PluginViewItem( fit.current(), groupViewItem );
+
+ groupViewItem->setOpen(true);
+ }
+
+ slotSelectionChanged();
+}
+
+
+bool K3bPluginOptionTab::saveSettings()
+{
+ return true;
+}
+
+
+void K3bPluginOptionTab::slotConfigureButtonClicked()
+{
+ QListViewItem* item = m_viewPlugins->selectedItem();
+ if( PluginViewItem* pi = dynamic_cast<PluginViewItem*>( item ) )
+ k3bcore->pluginManager()->execPluginDialog( pi->plugin, this );
+}
+
+
+void K3bPluginOptionTab::slotSelectionChanged()
+{
+ m_buttonConfigure->setEnabled( dynamic_cast<PluginViewItem*>( m_viewPlugins->selectedItem() ) != 0 );
+}
+
+#include "k3bpluginoptiontab.moc"
diff --git a/src/option/k3bpluginoptiontab.h b/src/option/k3bpluginoptiontab.h
new file mode 100644
index 0000000..1fb1821
--- /dev/null
+++ b/src/option/k3bpluginoptiontab.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * $Id: k3bpluginoptiontab.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_PLUGIN_OPTION_TAB_H_
+#define _K3B_PLUGIN_OPTION_TAB_H_
+
+#include "base_k3bpluginoptiontab.h"
+
+
+
+class K3bPluginOptionTab : public base_K3bPluginOptionTab
+{
+ Q_OBJECT
+
+ public:
+ K3bPluginOptionTab( QWidget* parent = 0, const char* name = 0 );
+ ~K3bPluginOptionTab();
+
+ public slots:
+ void readSettings();
+ bool saveSettings();
+
+ private slots:
+ void slotConfigureButtonClicked();
+ void slotSelectionChanged();
+
+ private:
+ class PluginViewItem;
+};
+
+#endif
diff --git a/src/option/k3bthemeoptiontab.cpp b/src/option/k3bthemeoptiontab.cpp
new file mode 100644
index 0000000..4fd3f61
--- /dev/null
+++ b/src/option/k3bthemeoptiontab.cpp
@@ -0,0 +1,234 @@
+/*
+ *
+ * $Id: k3bthemeoptiontab.cpp 642063 2007-03-13 09:40:13Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bthemeoptiontab.h"
+
+#include "k3bthememanager.h"
+
+#include <k3bapplication.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kurlrequester.h>
+#include <klistview.h>
+#include <kio/global.h>
+#include <kio/netaccess.h>
+#include <kio/job.h>
+#include <kstandarddirs.h>
+#include <ktar.h>
+#include <kurlrequesterdlg.h>
+#include <kdeversion.h>
+
+#include <qlabel.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+
+class K3bThemeOptionTab::Private
+{
+public:
+};
+
+
+class ThemeViewItem : public KListViewItem
+{
+public:
+ ThemeViewItem( K3bTheme* theme_, QListView* parent, QListViewItem* after )
+ : KListViewItem( parent, after ),
+ theme(theme_) {
+ setText( 0, theme->name() );
+ setText( 1, theme->author() );
+ setText( 2, theme->version() );
+ setText( 3, theme->comment() );
+ }
+
+ K3bTheme* theme;
+};
+
+K3bThemeOptionTab::K3bThemeOptionTab(QWidget *parent, const char *name )
+ : base_K3bThemeOptionTab(parent,name)
+{
+ d = new Private();
+
+#if KDE_IS_VERSION(3,4,0)
+ m_viewTheme->setShadeSortColumn( false );
+#endif
+
+ connect( m_viewTheme, SIGNAL(selectionChanged()),
+ this, SLOT(selectionChanged()) );
+ connect( kapp, SIGNAL(appearanceChanged()),
+ this, SLOT(selectionChanged()) );
+ connect( m_buttonInstallTheme, SIGNAL(clicked()),
+ this, SLOT(slotInstallTheme()) );
+ connect( m_buttonRemoveTheme, SIGNAL(clicked()),
+ this, SLOT(slotRemoveTheme()) );
+}
+
+
+K3bThemeOptionTab::~K3bThemeOptionTab()
+{
+ delete d;
+}
+
+
+void K3bThemeOptionTab::readSettings()
+{
+ m_viewTheme->clear();
+
+ k3bappcore->themeManager()->loadThemes();
+
+ QValueList<K3bTheme*> themes = k3bappcore->themeManager()->themes();
+ for( QValueList<K3bTheme*>::const_iterator it = themes.constBegin(); it != themes.constEnd(); ++it ) {
+ K3bTheme* theme = *it;
+ ThemeViewItem* item = new ThemeViewItem( theme, m_viewTheme, m_viewTheme->lastItem() );
+ if( theme == k3bappcore->themeManager()->currentTheme() )
+ m_viewTheme->setSelected( item, true );
+ }
+}
+
+
+bool K3bThemeOptionTab::saveSettings()
+{
+ ThemeViewItem* item = (ThemeViewItem*)m_viewTheme->selectedItem();
+ if( item )
+ k3bappcore->themeManager()->setCurrentTheme( item->theme );
+
+ return true;
+}
+
+
+void K3bThemeOptionTab::selectionChanged()
+{
+ ThemeViewItem* item = (ThemeViewItem*)m_viewTheme->selectedItem();
+ if( item ) {
+ m_centerPreviewLabel->setText( i18n("K3b - The CD/DVD Kreator") );
+ m_centerPreviewLabel->setPaletteBackgroundColor( item->theme->backgroundColor() );
+ m_centerPreviewLabel->setPaletteForegroundColor( item->theme->foregroundColor() );
+ m_leftPreviewLabel->setPaletteBackgroundColor( item->theme->backgroundColor() );
+ m_leftPreviewLabel->setPaletteForegroundColor( item->theme->foregroundColor() );
+ m_rightPreviewLabel->setPaletteBackgroundColor( item->theme->backgroundColor() );
+ m_rightPreviewLabel->setPaletteForegroundColor( item->theme->foregroundColor() );
+ m_leftPreviewLabel->setPixmap( item->theme->pixmap( K3bTheme::PROJECT_LEFT ) );
+ m_rightPreviewLabel->setPixmap( item->theme->pixmap( K3bTheme::PROJECT_RIGHT ) );
+
+ m_buttonRemoveTheme->setEnabled( item->theme->local() );
+ }
+}
+
+
+void K3bThemeOptionTab::slotInstallTheme()
+{
+ KURL themeURL = KURLRequesterDlg::getURL( QString::null, this,
+ i18n("Drag or Type Theme URL") );
+
+ if( themeURL.url().isEmpty() )
+ return;
+
+ QString themeTmpFile;
+ // themeTmpFile contains the name of the downloaded file
+
+ if( !KIO::NetAccess::download( themeURL, themeTmpFile, this ) ) {
+ QString sorryText;
+ if (themeURL.isLocalFile())
+ sorryText = i18n("Unable to find the icon theme archive %1.");
+ else
+ sorryText = i18n("Unable to download the icon theme archive.\n"
+ "Please check that address %1 is correct.");
+ KMessageBox::sorry( this, sorryText.arg(themeURL.prettyURL()) );
+ return;
+ }
+
+ // check if the archive contains a dir with a k3b.theme file
+ QString themeName;
+ KTar archive( themeTmpFile );
+ archive.open(IO_ReadOnly);
+ const KArchiveDirectory* themeDir = archive.directory();
+ QStringList entries = themeDir->entries();
+ bool validThemeArchive = false;
+ if( entries.count() > 0 ) {
+ if( themeDir->entry(entries.first())->isDirectory() ) {
+ const KArchiveDirectory* subDir = dynamic_cast<const KArchiveDirectory*>( themeDir->entry(entries.first()) );
+ themeName = subDir->name();
+ if( subDir && subDir->entry( "k3b.theme" ) ) {
+ validThemeArchive = true;
+
+ // check for all nessessary pixmaps (this is a little evil hacking)
+ for( int i = 0; i <= K3bTheme::WELCOME_BG; ++i ) {
+ if( !subDir->entry( K3bTheme::filenameForPixmapType( (K3bTheme::PixmapType)i ) ) ) {
+ validThemeArchive = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if( !validThemeArchive ) {
+ KMessageBox::error( this, i18n("The file is not a valid K3b theme archive.") );
+ }
+ else {
+ QString themeBasePath = locateLocal( "data", "k3b/pics/" );
+
+ // check if there already is a theme by that name
+ if( !QFile::exists( themeBasePath + '/' + themeName ) ||
+ KMessageBox::warningYesNo( this,
+ i18n("A theme with the name '%1' already exists. Do you want to "
+ "overwrite it?"),
+ i18n("Theme exists"),
+ i18n("Overwrite"),
+ i18n("Cancel") ) == KMessageBox::Yes ) {
+ // install the theme
+ archive.directory()->copyTo( themeBasePath );
+ }
+ }
+
+ archive.close();
+ KIO::NetAccess::removeTempFile(themeTmpFile);
+
+ readSettings();
+}
+
+
+void K3bThemeOptionTab::slotRemoveTheme()
+{
+ ThemeViewItem* item = (ThemeViewItem*)m_viewTheme->selectedItem();
+ if( item ) {
+ QString question=i18n("<qt>Are you sure you want to remove the "
+ "<strong>%1</strong> icon theme?<br>"
+ "<br>"
+ "This will delete the files installed by this theme.</qt>").
+ arg(item->text(0));
+
+ if( KMessageBox::warningContinueCancel( this, question, i18n("Delete") ) != KMessageBox::Continue )
+ return;
+
+ K3bTheme* theme = item->theme;
+ delete item;
+ QString path = theme->path();
+
+ // delete k3b.theme file to avoid it to get loaded
+ QFile::remove( path + "/k3b.theme" );
+
+ // reread the themes (this will also set the default theme in case we delete the
+ // selected one)
+ readSettings();
+
+ // delete the theme data itself
+ KIO::del( path, false, false );
+ }
+}
+
+#include "k3bthemeoptiontab.moc"
diff --git a/src/option/k3bthemeoptiontab.h b/src/option/k3bthemeoptiontab.h
new file mode 100644
index 0000000..bfb1d72
--- /dev/null
+++ b/src/option/k3bthemeoptiontab.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * $Id: k3bthemeoptiontab.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3BTHEMEOPTIONTAB_H_
+#define _K3BTHEMEOPTIONTAB_H_
+
+#include "base_k3bthemeoptiontab.h"
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bThemeOptionTab : public base_K3bThemeOptionTab
+{
+ Q_OBJECT
+
+ public:
+ K3bThemeOptionTab( QWidget* parent = 0, const char* name = 0 );
+ ~K3bThemeOptionTab();
+
+ void readSettings();
+ bool saveSettings();
+
+ private slots:
+ void selectionChanged();
+ void slotInstallTheme();
+ void slotRemoveTheme();
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/pics/73lab/Makefile.am b/src/pics/73lab/Makefile.am
new file mode 100644
index 0000000..50c69a4
--- /dev/null
+++ b/src/pics/73lab/Makefile.am
@@ -0,0 +1,23 @@
+picsdir = $(kde_datadir)/k3b/pics/73lab
+
+pics_DATA = splash.png \
+ project_left.png \
+ project_right.png \
+ probing.png \
+ media_audio.png \
+ media_data.png \
+ media_video.png \
+ media_empty.png \
+ media_left.png \
+ media_mixed.png \
+ media_none.png \
+ progress_working.png \
+ progress_fail.png \
+ progress_success.png \
+ progress_right.png \
+ dialog_left.png \
+ dialog_right.png \
+ welcome_bg.png \
+ k3b.theme
+
+EXTRA_DIST = $(pics_DATA)
diff --git a/src/pics/73lab/dialog_left.png b/src/pics/73lab/dialog_left.png
new file mode 100644
index 0000000..98b69c0
--- /dev/null
+++ b/src/pics/73lab/dialog_left.png
Binary files differ
diff --git a/src/pics/73lab/dialog_right.png b/src/pics/73lab/dialog_right.png
new file mode 100644
index 0000000..f7fef0e
--- /dev/null
+++ b/src/pics/73lab/dialog_right.png
Binary files differ
diff --git a/src/pics/73lab/k3b.theme b/src/pics/73lab/k3b.theme
new file mode 100644
index 0000000..ad17706
--- /dev/null
+++ b/src/pics/73lab/k3b.theme
@@ -0,0 +1,5 @@
+Author=Ayo
+Backgroundcolor=205,210,255
+Foregroundcolor=0,0,0
+Comment=Ayo's original K3b theme
+Version=2.0
diff --git a/src/pics/73lab/media_audio.png b/src/pics/73lab/media_audio.png
new file mode 100644
index 0000000..e12f591
--- /dev/null
+++ b/src/pics/73lab/media_audio.png
Binary files differ
diff --git a/src/pics/73lab/media_data.png b/src/pics/73lab/media_data.png
new file mode 100644
index 0000000..dd0cbce
--- /dev/null
+++ b/src/pics/73lab/media_data.png
Binary files differ
diff --git a/src/pics/73lab/media_empty.png b/src/pics/73lab/media_empty.png
new file mode 100644
index 0000000..9e9f05b
--- /dev/null
+++ b/src/pics/73lab/media_empty.png
Binary files differ
diff --git a/src/pics/73lab/media_left.png b/src/pics/73lab/media_left.png
new file mode 100644
index 0000000..98b69c0
--- /dev/null
+++ b/src/pics/73lab/media_left.png
Binary files differ
diff --git a/src/pics/73lab/media_mixed.png b/src/pics/73lab/media_mixed.png
new file mode 100644
index 0000000..a9404ab
--- /dev/null
+++ b/src/pics/73lab/media_mixed.png
Binary files differ
diff --git a/src/pics/73lab/media_none.png b/src/pics/73lab/media_none.png
new file mode 100644
index 0000000..f7fef0e
--- /dev/null
+++ b/src/pics/73lab/media_none.png
Binary files differ
diff --git a/src/pics/73lab/media_video.png b/src/pics/73lab/media_video.png
new file mode 100644
index 0000000..a5e6709
--- /dev/null
+++ b/src/pics/73lab/media_video.png
Binary files differ
diff --git a/src/pics/73lab/probing.png b/src/pics/73lab/probing.png
new file mode 100644
index 0000000..4a03574
--- /dev/null
+++ b/src/pics/73lab/probing.png
Binary files differ
diff --git a/src/pics/73lab/progress_fail.png b/src/pics/73lab/progress_fail.png
new file mode 100644
index 0000000..73b65d6
--- /dev/null
+++ b/src/pics/73lab/progress_fail.png
Binary files differ
diff --git a/src/pics/73lab/progress_right.png b/src/pics/73lab/progress_right.png
new file mode 100644
index 0000000..f4126f6
--- /dev/null
+++ b/src/pics/73lab/progress_right.png
Binary files differ
diff --git a/src/pics/73lab/progress_success.png b/src/pics/73lab/progress_success.png
new file mode 100644
index 0000000..abcdab6
--- /dev/null
+++ b/src/pics/73lab/progress_success.png
Binary files differ
diff --git a/src/pics/73lab/progress_working.png b/src/pics/73lab/progress_working.png
new file mode 100644
index 0000000..4a6f479
--- /dev/null
+++ b/src/pics/73lab/progress_working.png
Binary files differ
diff --git a/src/pics/73lab/project_left.png b/src/pics/73lab/project_left.png
new file mode 100644
index 0000000..9906ac6
--- /dev/null
+++ b/src/pics/73lab/project_left.png
Binary files differ
diff --git a/src/pics/73lab/project_right.png b/src/pics/73lab/project_right.png
new file mode 100644
index 0000000..f4126f6
--- /dev/null
+++ b/src/pics/73lab/project_right.png
Binary files differ
diff --git a/src/pics/73lab/splash.png b/src/pics/73lab/splash.png
new file mode 100644
index 0000000..f36348c
--- /dev/null
+++ b/src/pics/73lab/splash.png
Binary files differ
diff --git a/src/pics/73lab/welcome_bg.png b/src/pics/73lab/welcome_bg.png
new file mode 100644
index 0000000..e4f8879
--- /dev/null
+++ b/src/pics/73lab/welcome_bg.png
Binary files differ
diff --git a/src/pics/Makefile.am b/src/pics/Makefile.am
new file mode 100644
index 0000000..5c1832f
--- /dev/null
+++ b/src/pics/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = 73lab crystal quant RobsTheme
diff --git a/src/pics/RobsTheme/Makefile.am b/src/pics/RobsTheme/Makefile.am
new file mode 100644
index 0000000..01890be
--- /dev/null
+++ b/src/pics/RobsTheme/Makefile.am
@@ -0,0 +1,23 @@
+
+picsdir = $(kde_datadir)/k3b/pics/RobsTheme
+
+pics_DATA = splash.png \
+ project_left.png \
+ project_right.png \
+ media_audio.png \
+ media_data.png \
+ media_video.png \
+ media_empty.png \
+ media_left.png \
+ media_mixed.png \
+ media_none.png \
+ progress_working.png \
+ progress_fail.png \
+ progress_success.png \
+ progress_right.png \
+ dialog_left.png \
+ dialog_right.png \
+ welcome_bg.png \
+ k3b.theme
+
+EXTRA_DIST = $(pics_DATA)
diff --git a/src/pics/RobsTheme/dialog_left.png b/src/pics/RobsTheme/dialog_left.png
new file mode 100644
index 0000000..ee0f896
--- /dev/null
+++ b/src/pics/RobsTheme/dialog_left.png
Binary files differ
diff --git a/src/pics/RobsTheme/dialog_right.png b/src/pics/RobsTheme/dialog_right.png
new file mode 100644
index 0000000..b1013c1
--- /dev/null
+++ b/src/pics/RobsTheme/dialog_right.png
Binary files differ
diff --git a/src/pics/RobsTheme/k3b.theme b/src/pics/RobsTheme/k3b.theme
new file mode 100644
index 0000000..64b1494
--- /dev/null
+++ b/src/pics/RobsTheme/k3b.theme
@@ -0,0 +1,5 @@
+Author=Robert Wadley
+Backgroundcolor=Window
+Foregroundcolor=WindowText
+Comment=A semitransparent theme that uses your system colors.
+Version=1.0
diff --git a/src/pics/RobsTheme/media_audio.png b/src/pics/RobsTheme/media_audio.png
new file mode 100644
index 0000000..e4aa6e6
--- /dev/null
+++ b/src/pics/RobsTheme/media_audio.png
Binary files differ
diff --git a/src/pics/RobsTheme/media_data.png b/src/pics/RobsTheme/media_data.png
new file mode 100644
index 0000000..0810113
--- /dev/null
+++ b/src/pics/RobsTheme/media_data.png
Binary files differ
diff --git a/src/pics/RobsTheme/media_empty.png b/src/pics/RobsTheme/media_empty.png
new file mode 100644
index 0000000..776eb5e
--- /dev/null
+++ b/src/pics/RobsTheme/media_empty.png
Binary files differ
diff --git a/src/pics/RobsTheme/media_left.png b/src/pics/RobsTheme/media_left.png
new file mode 100644
index 0000000..ee0f896
--- /dev/null
+++ b/src/pics/RobsTheme/media_left.png
Binary files differ
diff --git a/src/pics/RobsTheme/media_mixed.png b/src/pics/RobsTheme/media_mixed.png
new file mode 100644
index 0000000..c17b91b
--- /dev/null
+++ b/src/pics/RobsTheme/media_mixed.png
Binary files differ
diff --git a/src/pics/RobsTheme/media_none.png b/src/pics/RobsTheme/media_none.png
new file mode 100644
index 0000000..4035080
--- /dev/null
+++ b/src/pics/RobsTheme/media_none.png
Binary files differ
diff --git a/src/pics/RobsTheme/media_video.png b/src/pics/RobsTheme/media_video.png
new file mode 100644
index 0000000..4ffb8d9
--- /dev/null
+++ b/src/pics/RobsTheme/media_video.png
Binary files differ
diff --git a/src/pics/RobsTheme/progress_fail.png b/src/pics/RobsTheme/progress_fail.png
new file mode 100644
index 0000000..761da82
--- /dev/null
+++ b/src/pics/RobsTheme/progress_fail.png
Binary files differ
diff --git a/src/pics/RobsTheme/progress_right.png b/src/pics/RobsTheme/progress_right.png
new file mode 100644
index 0000000..973e81a
--- /dev/null
+++ b/src/pics/RobsTheme/progress_right.png
Binary files differ
diff --git a/src/pics/RobsTheme/progress_success.png b/src/pics/RobsTheme/progress_success.png
new file mode 100644
index 0000000..b61daef
--- /dev/null
+++ b/src/pics/RobsTheme/progress_success.png
Binary files differ
diff --git a/src/pics/RobsTheme/progress_working.png b/src/pics/RobsTheme/progress_working.png
new file mode 100644
index 0000000..dd59dce
--- /dev/null
+++ b/src/pics/RobsTheme/progress_working.png
Binary files differ
diff --git a/src/pics/RobsTheme/project_left.png b/src/pics/RobsTheme/project_left.png
new file mode 100644
index 0000000..e114f5e
--- /dev/null
+++ b/src/pics/RobsTheme/project_left.png
Binary files differ
diff --git a/src/pics/RobsTheme/project_right.png b/src/pics/RobsTheme/project_right.png
new file mode 100644
index 0000000..c061b4f
--- /dev/null
+++ b/src/pics/RobsTheme/project_right.png
Binary files differ
diff --git a/src/pics/RobsTheme/splash.png b/src/pics/RobsTheme/splash.png
new file mode 100644
index 0000000..752b51b
--- /dev/null
+++ b/src/pics/RobsTheme/splash.png
Binary files differ
diff --git a/src/pics/RobsTheme/welcome_bg.png b/src/pics/RobsTheme/welcome_bg.png
new file mode 100644
index 0000000..b54c4cd
--- /dev/null
+++ b/src/pics/RobsTheme/welcome_bg.png
Binary files differ
diff --git a/src/pics/crystal/Makefile.am b/src/pics/crystal/Makefile.am
new file mode 100644
index 0000000..a7d58eb
--- /dev/null
+++ b/src/pics/crystal/Makefile.am
@@ -0,0 +1,24 @@
+
+picsdir = $(kde_datadir)/k3b/pics/crystal
+
+pics_DATA = splash.png \
+ project_left.png \
+ project_right.png \
+ probing.png \
+ media_audio.png \
+ media_data.png \
+ media_video.png \
+ media_empty.png \
+ media_left.png \
+ media_mixed.png \
+ media_none.png \
+ progress_working.png \
+ progress_fail.png \
+ progress_success.png \
+ progress_right.png \
+ dialog_left.png \
+ dialog_right.png \
+ welcome_bg.png \
+ k3b.theme
+
+EXTRA_DIST = $(pics_DATA)
diff --git a/src/pics/crystal/dialog_left.png b/src/pics/crystal/dialog_left.png
new file mode 100644
index 0000000..f2e1a08
--- /dev/null
+++ b/src/pics/crystal/dialog_left.png
Binary files differ
diff --git a/src/pics/crystal/dialog_right.png b/src/pics/crystal/dialog_right.png
new file mode 100644
index 0000000..2efac87
--- /dev/null
+++ b/src/pics/crystal/dialog_right.png
Binary files differ
diff --git a/src/pics/crystal/k3b.theme b/src/pics/crystal/k3b.theme
new file mode 100644
index 0000000..1bf94fb
--- /dev/null
+++ b/src/pics/crystal/k3b.theme
@@ -0,0 +1,5 @@
+Author=Everaldo
+Backgroundcolor=139,153,222
+Foregroundcolor=255,255,255
+Comment=The cool crystal theme
+Version=2.0
diff --git a/src/pics/crystal/media_audio.png b/src/pics/crystal/media_audio.png
new file mode 100644
index 0000000..6ce1348
--- /dev/null
+++ b/src/pics/crystal/media_audio.png
Binary files differ
diff --git a/src/pics/crystal/media_data.png b/src/pics/crystal/media_data.png
new file mode 100644
index 0000000..877f7db
--- /dev/null
+++ b/src/pics/crystal/media_data.png
Binary files differ
diff --git a/src/pics/crystal/media_empty.png b/src/pics/crystal/media_empty.png
new file mode 100644
index 0000000..7664557
--- /dev/null
+++ b/src/pics/crystal/media_empty.png
Binary files differ
diff --git a/src/pics/crystal/media_left.png b/src/pics/crystal/media_left.png
new file mode 100644
index 0000000..f2e1a08
--- /dev/null
+++ b/src/pics/crystal/media_left.png
Binary files differ
diff --git a/src/pics/crystal/media_mixed.png b/src/pics/crystal/media_mixed.png
new file mode 100644
index 0000000..6bc8140
--- /dev/null
+++ b/src/pics/crystal/media_mixed.png
Binary files differ
diff --git a/src/pics/crystal/media_none.png b/src/pics/crystal/media_none.png
new file mode 100644
index 0000000..2efac87
--- /dev/null
+++ b/src/pics/crystal/media_none.png
Binary files differ
diff --git a/src/pics/crystal/media_video.png b/src/pics/crystal/media_video.png
new file mode 100644
index 0000000..ca46c9f
--- /dev/null
+++ b/src/pics/crystal/media_video.png
Binary files differ
diff --git a/src/pics/crystal/probing.png b/src/pics/crystal/probing.png
new file mode 100644
index 0000000..fb23fce
--- /dev/null
+++ b/src/pics/crystal/probing.png
Binary files differ
diff --git a/src/pics/crystal/progress_fail.png b/src/pics/crystal/progress_fail.png
new file mode 100644
index 0000000..726e381
--- /dev/null
+++ b/src/pics/crystal/progress_fail.png
Binary files differ
diff --git a/src/pics/crystal/progress_right.png b/src/pics/crystal/progress_right.png
new file mode 100644
index 0000000..dfbd28a
--- /dev/null
+++ b/src/pics/crystal/progress_right.png
Binary files differ
diff --git a/src/pics/crystal/progress_success.png b/src/pics/crystal/progress_success.png
new file mode 100644
index 0000000..f6d174f
--- /dev/null
+++ b/src/pics/crystal/progress_success.png
Binary files differ
diff --git a/src/pics/crystal/progress_working.png b/src/pics/crystal/progress_working.png
new file mode 100644
index 0000000..9990d37
--- /dev/null
+++ b/src/pics/crystal/progress_working.png
Binary files differ
diff --git a/src/pics/crystal/project_left.png b/src/pics/crystal/project_left.png
new file mode 100644
index 0000000..e3b3e3e
--- /dev/null
+++ b/src/pics/crystal/project_left.png
Binary files differ
diff --git a/src/pics/crystal/project_right.png b/src/pics/crystal/project_right.png
new file mode 100644
index 0000000..dfbd28a
--- /dev/null
+++ b/src/pics/crystal/project_right.png
Binary files differ
diff --git a/src/pics/crystal/splash.png b/src/pics/crystal/splash.png
new file mode 100644
index 0000000..699424f
--- /dev/null
+++ b/src/pics/crystal/splash.png
Binary files differ
diff --git a/src/pics/crystal/welcome_bg.png b/src/pics/crystal/welcome_bg.png
new file mode 100644
index 0000000..4224f61
--- /dev/null
+++ b/src/pics/crystal/welcome_bg.png
Binary files differ
diff --git a/src/pics/quant/Makefile.am b/src/pics/quant/Makefile.am
new file mode 100644
index 0000000..1b5ca07
--- /dev/null
+++ b/src/pics/quant/Makefile.am
@@ -0,0 +1,23 @@
+
+picsdir = $(kde_datadir)/k3b/pics/quant
+
+pics_DATA = splash.png \
+ project_left.png \
+ project_right.png \
+ media_audio.png \
+ media_data.png \
+ media_video.png \
+ media_empty.png \
+ media_left.png \
+ media_mixed.png \
+ media_none.png \
+ progress_working.png \
+ progress_fail.png \
+ progress_success.png \
+ progress_right.png \
+ dialog_left.png \
+ dialog_right.png \
+ welcome_bg.png \
+ k3b.theme
+
+EXTRA_DIST = $(pics_DATA)
diff --git a/src/pics/quant/dialog_left.png b/src/pics/quant/dialog_left.png
new file mode 100644
index 0000000..ea5173e
--- /dev/null
+++ b/src/pics/quant/dialog_left.png
Binary files differ
diff --git a/src/pics/quant/dialog_right.png b/src/pics/quant/dialog_right.png
new file mode 100644
index 0000000..cbf12a8
--- /dev/null
+++ b/src/pics/quant/dialog_right.png
Binary files differ
diff --git a/src/pics/quant/k3b.theme b/src/pics/quant/k3b.theme
new file mode 100644
index 0000000..c5c173e
--- /dev/null
+++ b/src/pics/quant/k3b.theme
@@ -0,0 +1,6 @@
+Author=Dmitry Novikov (quant@trktvs.ru)
+Backgroundcolor=Window
+Foregroundcolor=WindowText
+Comment=New official theme for K3b. Enjoy!
+Version=0.1
+BackgroundMode=Scaled
diff --git a/src/pics/quant/media_audio.png b/src/pics/quant/media_audio.png
new file mode 100644
index 0000000..c2a068a
--- /dev/null
+++ b/src/pics/quant/media_audio.png
Binary files differ
diff --git a/src/pics/quant/media_data.png b/src/pics/quant/media_data.png
new file mode 100644
index 0000000..4e4876b
--- /dev/null
+++ b/src/pics/quant/media_data.png
Binary files differ
diff --git a/src/pics/quant/media_empty.png b/src/pics/quant/media_empty.png
new file mode 100644
index 0000000..d4c2e70
--- /dev/null
+++ b/src/pics/quant/media_empty.png
Binary files differ
diff --git a/src/pics/quant/media_left.png b/src/pics/quant/media_left.png
new file mode 100644
index 0000000..c0211f8
--- /dev/null
+++ b/src/pics/quant/media_left.png
Binary files differ
diff --git a/src/pics/quant/media_mixed.png b/src/pics/quant/media_mixed.png
new file mode 100644
index 0000000..1f04083
--- /dev/null
+++ b/src/pics/quant/media_mixed.png
Binary files differ
diff --git a/src/pics/quant/media_none.png b/src/pics/quant/media_none.png
new file mode 100644
index 0000000..8f47198
--- /dev/null
+++ b/src/pics/quant/media_none.png
Binary files differ
diff --git a/src/pics/quant/media_video.png b/src/pics/quant/media_video.png
new file mode 100644
index 0000000..93e8a20
--- /dev/null
+++ b/src/pics/quant/media_video.png
Binary files differ
diff --git a/src/pics/quant/progress_fail.png b/src/pics/quant/progress_fail.png
new file mode 100644
index 0000000..b8c1276
--- /dev/null
+++ b/src/pics/quant/progress_fail.png
Binary files differ
diff --git a/src/pics/quant/progress_right.png b/src/pics/quant/progress_right.png
new file mode 100644
index 0000000..2dfa665
--- /dev/null
+++ b/src/pics/quant/progress_right.png
Binary files differ
diff --git a/src/pics/quant/progress_success.png b/src/pics/quant/progress_success.png
new file mode 100644
index 0000000..36145f1
--- /dev/null
+++ b/src/pics/quant/progress_success.png
Binary files differ
diff --git a/src/pics/quant/progress_working.png b/src/pics/quant/progress_working.png
new file mode 100644
index 0000000..6215897
--- /dev/null
+++ b/src/pics/quant/progress_working.png
Binary files differ
diff --git a/src/pics/quant/project_left.png b/src/pics/quant/project_left.png
new file mode 100644
index 0000000..bcc7ff2
--- /dev/null
+++ b/src/pics/quant/project_left.png
Binary files differ
diff --git a/src/pics/quant/project_right.png b/src/pics/quant/project_right.png
new file mode 100644
index 0000000..0db8e25
--- /dev/null
+++ b/src/pics/quant/project_right.png
Binary files differ
diff --git a/src/pics/quant/splash.png b/src/pics/quant/splash.png
new file mode 100644
index 0000000..25a7c4c
--- /dev/null
+++ b/src/pics/quant/splash.png
Binary files differ
diff --git a/src/pics/quant/welcome_bg.png b/src/pics/quant/welcome_bg.png
new file mode 100644
index 0000000..a53e597
--- /dev/null
+++ b/src/pics/quant/welcome_bg.png
Binary files differ
diff --git a/src/projects/Makefile.am b/src/projects/Makefile.am
new file mode 100644
index 0000000..751eb71
--- /dev/null
+++ b/src/projects/Makefile.am
@@ -0,0 +1,86 @@
+AM_CPPFLAGS= -I$(srcdir)/../../libk3b/core \
+ -I$(srcdir)/../../libk3bdevice \
+ -I$(srcdir)/../../libk3b/projects \
+ -I$(srcdir)/../../libk3b/projects/audiocd \
+ -I$(srcdir)/../../libk3b/projects/datacd \
+ -I$(srcdir)/../../libk3b/projects/mixedcd \
+ -I$(srcdir)/../../libk3b/projects/movixcd \
+ -I$(srcdir)/../../libk3b/projects/datadvd \
+ -I$(srcdir)/../../libk3b/projects/videocd \
+ -I$(srcdir)/../../libk3b/projects/videodvd \
+ -I$(srcdir)/../../libk3b/projects/movixdvd \
+ -I$(srcdir)/../../libk3b/cddb \
+ -I$(srcdir)/../../libk3b/tools \
+ -I$(srcdir)/../../libk3b/plugin \
+ -I$(srcdir)/../rip \
+ -I$(srcdir)/.. \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+SUBDIRS = kostore
+
+noinst_LTLIBRARIES = libprojects.la
+
+libprojects_la_LIBADD = ../rip/librip.la ./kostore/libkostore.la
+
+libprojects_la_SOURCES = k3baudioburndialog.cpp \
+ k3baudiocdtextwidget.cpp \
+ k3baudiodatasourceviewitem.cpp \
+ k3baudioeditorwidget.cpp \
+ k3baudiotrackdialog.cpp \
+ k3baudiotrackwidget.cpp \
+ k3baudiotrackplayer.cpp \
+ k3baudiotracksplitdialog.cpp \
+ k3baudiotrackview.cpp \
+ k3baudiotrackviewitem.cpp \
+ k3baudioview.cpp \
+ base_k3baudiocdtextwidget.ui \
+ base_k3baudiocdtextallfieldswidget.ui \
+ base_k3baudiotrackwidget.ui \
+ k3bmixedburndialog.cpp \
+ k3bmixeddirtreeview.cpp \
+ k3bmixedview.cpp \
+ base_k3badvanceddataimagesettings.ui \
+ base_k3bbootimageview.ui \
+ base_k3bdataimagesettings.ui \
+ base_k3bdatavolumedescwidget.ui \
+ k3bdataadvancedimagesettingswidget.cpp \
+ k3bdatadirtreeview.cpp \
+ k3bdatafileview.cpp \
+ k3bdataimagesettingswidget.cpp \
+ k3bdatapropertiesdialog.cpp \
+ k3bdataview.cpp \
+ k3bdataviewitem.cpp \
+ k3bdatavolumedescwidget.cpp \
+ k3bdataburndialog.cpp \
+ k3bbootimagedialog.cpp \
+ k3bbootimageview.cpp \
+ k3bdvdburndialog.cpp \
+ k3bdvdview.cpp \
+ base_k3bmovixoptionswidget.ui \
+ k3bmovixburndialog.cpp \
+ k3bmovixlistview.cpp \
+ k3bmovixoptionswidget.cpp \
+ k3bmovixview.cpp \
+ k3bmovixdvdburndialog.cpp \
+ k3bmovixdvdview.cpp \
+ k3bvideodvdburndialog.cpp \
+ k3bvideodvdview.cpp \
+ k3bvcdburndialog.cpp \
+ k3bvcdlistview.cpp \
+ k3bvcdlistviewitem.cpp \
+ k3bvcdtrackdialog.cpp \
+ k3bvcdview.cpp \
+ k3bfillstatusdisplay.cpp \
+ k3bview.cpp \
+ k3bprojectburndialog.cpp \
+ k3bprojectplugindialog.cpp \
+ k3baudiotracktrmlookupdialog.cpp \
+ k3bdatamultisessioncombobox.cpp \
+ k3bmusicbrainzjob.cpp \
+ k3bdataurladdingdialog.cpp \
+ k3bdatasessionimportdialog.cpp \
+ k3baudiodatasourceeditwidget.cpp \
+ k3baudiotrackaddingdialog.cpp \
+ k3bencodingconverter.cpp \ No newline at end of file
diff --git a/src/projects/base_k3badvanceddataimagesettings.ui b/src/projects/base_k3badvanceddataimagesettings.ui
new file mode 100644
index 0000000..593b404
--- /dev/null
+++ b/src/projects/base_k3badvanceddataimagesettings.ui
@@ -0,0 +1,193 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bAdvancedDataImageSettings</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bDataCustomFilesystemsWidget</cstring>
+ </property>
+ <property name="caption">
+ <string>Custom Data Filesystems</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>groupIsoSettings</cstring>
+ </property>
+ <property name="title">
+ <string>File System Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>ISO9660 Filesystem</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_viewIsoSettings</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>File Systems</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkRockRidge</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Generate Rock Ridge extensions</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Add Rock Ridge extensions to the file system</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked, K3b will generate the System Use Sharing Protocol records (SUSP) specified by the Rock Ridge Interchange Protocol (IEEE-P1282).
+&lt;p&gt;Rock Ridge extends the ISO-9660 filesystem by features equal to the UNIX filesystems (permissions, symbolic links, very long filenames, ...). It uses ISO-8859 or UTF-16 based characters and allows 255 octets.
+&lt;p&gt;Rock Ridge extensions are located at the end of each ISO-9660 directory record. This makes the Rock Ridge tree closely coupled to the ISO-9660 tree.
+&lt;p&gt;&lt;b&gt;It is highly recommended to use Rock Ridge extensions on every data CD or DVD.&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkJoliet</cstring>
+ </property>
+ <property name="text">
+ <string>Generate &amp;Joliet extensions</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Add Joliet extensions to the file system</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked, K3b will add additional Joliet extensions to the ISO-9660 file system.
+&lt;p&gt;Joliet is not an accepted independent international standard like ISO-9660 or Rock Ridge. It is mainly used on Windows systems.
+&lt;p&gt;Joliet does not allow all characters, so the Joliet filenames are not identical to the filenames on disk (as compared to Rock Ridge). Joliet has a filename length limitation of 64 chars (independent from the character coding and type e.g. European vs. Japanese). This is annoying, as modern file systems all allow 255 characters per path name component.
+&lt;p&gt;Joliet uses UTF-16 coding.
+&lt;p&gt;&lt;b&gt;Caution:&lt;/b&gt; With the exception of Linux and FreeBSD, there is no POSIX-like OS that supports Joliet. So &lt;b&gt;never create Joliet-only CDs or DVDs&lt;/b&gt; for that reason.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkUdf</cstring>
+ </property>
+ <property name="text">
+ <string>Generate &amp;UDF structures</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Add UDF structures to the file system</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will create UDF filesystem structures in addition to the ISO9660 filesystem.
+&lt;p&gt;The UDF (&lt;em&gt;&lt;b&gt;U&lt;/b&gt;niversal &lt;b&gt;D&lt;/b&gt;isk &lt;b&gt;F&lt;/b&gt;ormat&lt;/em&gt;) is mainly used for DVDs.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="0" column="1">
+ <property name="name">
+ <cstring>groupBox5</cstring>
+ </property>
+ <property name="title">
+ <string>Other Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkForceInputCharset</cstring>
+ </property>
+ <property name="text">
+ <string>F&amp;orce input charset:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>m_comboInputCharset</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkPreservePermissions</cstring>
+ </property>
+ <property name="text">
+ <string>Preserve file permissions (bac&amp;kup)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked, all files in the resulting file system will have exactly the same permissions as the source files. (Otherwise, all files will have equal permissions and be owned by root).
+&lt;p&gt;This is mainly useful for backups.&lt;p&gt;&lt;b&gt;Caution:&lt;/b&gt; The permissions may not make much sense on other file systems; for example, if a user that owns a file on the CD or DVD does not exist.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>m_checkForceInputCharset</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_comboInputCharset</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_checkRockRidge</tabstop>
+ <tabstop>m_checkJoliet</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/src/projects/base_k3baudiocdtextallfieldswidget.ui b/src/projects/base_k3baudiocdtextallfieldswidget.ui
new file mode 100644
index 0000000..e178d1f
--- /dev/null
+++ b/src/projects/base_k3baudiocdtextallfieldswidget.ui
@@ -0,0 +1,275 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bAudioCdTextAllFieldsWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bAudioCdTextAllFieldsWidget</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="8" column="0">
+ <property name="name">
+ <cstring>textLabel8</cstring>
+ </property>
+ <property name="text">
+ <string>Messa&amp;ge:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editMessage</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="1">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editSongwriter</cstring>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonCopySongwriter</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Copy to all tracks</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="6" column="0">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;UPC EAN:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editUpc_ean</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="5" column="1">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editComposer</cstring>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonCopyComposer</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Copy to all tracks</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>So&amp;ngwriter:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editSongwriter</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Composer:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editComposer</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="7" column="0">
+ <property name="name">
+ <cstring>textLabel7</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Disk id:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editDisc_id</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="1">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editArranger</cstring>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonCopyArranger</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Copy to all tracks</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Arranger:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editArranger</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="6" column="1">
+ <property name="name">
+ <cstring>m_editUpc_ean</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="7" column="1">
+ <property name="name">
+ <cstring>m_editDisc_id</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="8" column="1">
+ <property name="name">
+ <cstring>m_editMessage</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Performer:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editPerformer</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editTitle</cstring>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonCopyTitle</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Copy to all tracks</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Title:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editTitle</cstring>
+ </property>
+ </widget>
+ <widget class="Line" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>line4</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editPerformer</cstring>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonCopyPerformer</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Copy to all tracks</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/src/projects/base_k3baudiocdtextwidget.ui b/src/projects/base_k3baudiocdtextwidget.ui
new file mode 100644
index 0000000..50daff2
--- /dev/null
+++ b/src/projects/base_k3baudiocdtextwidget.ui
@@ -0,0 +1,222 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bAudioCdTextWidget</class>
+<comment>Widget to edit the global CD-Text in a K3b audio project.</comment>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>K3bAudioCDTextWidget</cstring>
+ </property>
+ <property name="caption">
+ <string>K3bAudioCDTextWidget</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupCdText</cstring>
+ </property>
+ <property name="title">
+ <string>Write CD-Text</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;&lt;b&gt;CD-Text&lt;/b&gt;
+&lt;p&gt;If this option is checked K3b uses some otherwise unused space on the Audio CD to store additional information, like the artist or the CD title.
+&lt;p&gt;CD-Text is an extension to the audio CD standard introduced by Sony.
+&lt;p&gt;CD-Text will only be usable on CD players that support this extension (mostly car CD players) and software like K3b, of course.
+&lt;p&gt;Since a CD-Text-enhanced Audio CD will work in any Hifi CD or DVD player even if the player does not support CD-Text explicitly, enabling it is never a bad idea (just remember to fill in the CD-Text information).</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Perf&amp;ormer:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editPerformer</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="1">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editPerformer</cstring>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonCopyPerformer</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Copy to all tracks</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editTitle</cstring>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonCopyTitle</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Copy to all tracks</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Title:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editTitle</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonMoreFields</cstring>
+ </property>
+ <property name="text">
+ <string>More Fiel&amp;ds...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_buttonCopyTitle</sender>
+ <signal>clicked()</signal>
+ <receiver>K3bAudioCDTextWidget</receiver>
+ <slot>slotCopyTitle()</slot>
+ </connection>
+ <connection>
+ <sender>m_buttonCopyPerformer</sender>
+ <signal>clicked()</signal>
+ <receiver>K3bAudioCDTextWidget</receiver>
+ <slot>slotCopyPerformer()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_editTitle</tabstop>
+ <tabstop>m_editPerformer</tabstop>
+</tabstops>
+<slots>
+ <slot access="protected" specifier="pure virtual">slotCopyTitle()</slot>
+ <slot access="protected" specifier="pure virtual">slotCopyPerformer()</slot>
+ <slot access="protected" specifier="pure virtual">slotCopyArranger()</slot>
+ <slot access="protected" specifier="pure virtual">slotCopyComposer()</slot>
+ <slot access="protected" specifier="pure virtual">slotCopySongwriter()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/src/projects/base_k3baudiotrackwidget.ui b/src/projects/base_k3baudiotrackwidget.ui
new file mode 100644
index 0000000..813b042
--- /dev/null
+++ b/src/projects/base_k3baudiotrackwidget.ui
@@ -0,0 +1,336 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bAudioTrackWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>K3bAudioTrackWidget</cstring>
+ </property>
+ <property name="caption">
+ <string>K3bAudioTrackWidget</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>m_mainTab</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>C&amp;D-Text</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit" row="4" column="1">
+ <property name="name">
+ <cstring>m_editSongwriter</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>So&amp;ngwriter:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editSongwriter</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="3" column="1">
+ <property name="name">
+ <cstring>m_editArranger</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="3" column="3">
+ <property name="name">
+ <cstring>m_editComposer</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="5" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>m_editMessage</cstring>
+ </property>
+ </widget>
+ <widget class="Line" row="1" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>line2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Arranger:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editArranger</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="2" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Composer:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editComposer</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel8</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Message:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editMessage</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>m_editTitle</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Performer:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editPerformer</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="2">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;ISRC:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editIsrc</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Title:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editTitle</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="4" column="3">
+ <property name="name">
+ <cstring>m_editIsrc</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="3">
+ <property name="name">
+ <cstring>m_editPerformer</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>350</width>
+ <height>50</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Options</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkPreemphasis</cstring>
+ </property>
+ <property name="text">
+ <string>Preemph&amp;asis</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Preemphasis is mainly used in audio processing. Higher frequencies in audio signals usually have lower amplitudes. This can lead to bad signal quality on noisy transmission because the high frequencies might become too weak. To avoid this effect, high frequencies are amplified before transmission (preemphasis); the receiver will then weaken them accordingly for playback.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkCopyPermitted</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Copy permitted</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_labelPostGap</cstring>
+ </property>
+ <property name="text">
+ <string>Post-Gap:</string>
+ </property>
+ </widget>
+ <widget class="K3bMsfEdit">
+ <property name="name">
+ <cstring>m_editPostGap</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Set the length of the track's post-gap</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;On an audio CD each track (except for the last) can have a post-gap.
+This does not mean that K3b adds an additional gap of silence to the track. This setting simply influences the display on a Hifi audio CD player. The part of an audio track that is marked as post-gap is counted backwards.
+&lt;p&gt;This setting is irrelevant for most users as todays CD burners can put arbitrary audio data in the post-gap when burning in DAO mode.
+&lt;p&gt;&lt;i&gt;In other CD-burning applications the post-gap might be called the pre-gap. The pre-gap of track 2 is the same as the post-gap of track 1.
+&lt;p&gt;&lt;b&gt;Changing the post-gap does not change the length of the track!&lt;/b&gt;
+&lt;p&gt;&lt;b&gt;When writing in TAO writing mode (not recommended for Audio CDs) the post-gap will most likely be muted and on some burners forced to 2 seconds.&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>161</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <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>41</width>
+ <height>80</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ </hbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>K3bMsfEdit</class>
+ <header location="global">k3bmsfedit.h</header>
+ <sizehint>
+ <width>100</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>7</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>m_editTitle</tabstop>
+ <tabstop>m_editPerformer</tabstop>
+ <tabstop>m_editArranger</tabstop>
+ <tabstop>m_editComposer</tabstop>
+ <tabstop>m_editSongwriter</tabstop>
+ <tabstop>m_editIsrc</tabstop>
+ <tabstop>m_editMessage</tabstop>
+ <tabstop>m_checkPreemphasis</tabstop>
+ <tabstop>m_checkCopyPermitted</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>k3bmsfedit.h</includehint>
+</includehints>
+</UI>
diff --git a/src/projects/base_k3bbootimageview.ui b/src/projects/base_k3bbootimageview.ui
new file mode 100644
index 0000000..6ba21f6
--- /dev/null
+++ b/src/projects/base_k3bbootimageview.ui
@@ -0,0 +1,394 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bBootImageView</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bBootImageView</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Boot images:</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonNew</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;New...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Add new boot image</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonDelete</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Remove selected boot image</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Emulation Type</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Size</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Local Path</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_viewImages</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_groupImageType</cstring>
+ </property>
+ <property name="title">
+ <string>Emulation Type</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioFloppy</cstring>
+ </property>
+ <property name="text">
+ <string>Flopp&amp;y</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Emulate a 1440/2880 kb floppy</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioHarddisk</cstring>
+ </property>
+ <property name="text">
+ <string>Harddisk</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Emulate a harddisk</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioNoEmulation</cstring>
+ </property>
+ <property name="text">
+ <string>None</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>No emulation at all</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupOptions</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkNoBoot</cstring>
+ </property>
+ <property name="text">
+ <string>No boot image</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Do not boot from the emulated floppy/harddisk</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkInfoTable</cstring>
+ </property>
+ <property name="text">
+ <string>Boot-info-table</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>m_editLoadSegment</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>m_editLoadSize</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Boot load segment:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Boot load size:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout16</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonToggleOptions</cstring>
+ </property>
+ <property name="text">
+ <string>Show Advanced Op&amp;tions</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer16</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>261</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout18</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Boot catalog:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_editBootCataloge</cstring>
+ </property>
+ <property name="text">
+ <string>boot/boot.catalog</string>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_radioFloppy</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>base_K3bBootImageView</receiver>
+ <slot>slotOptionsChanged()</slot>
+ </connection>
+ <connection>
+ <sender>m_radioHarddisk</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>base_K3bBootImageView</receiver>
+ <slot>slotOptionsChanged()</slot>
+ </connection>
+ <connection>
+ <sender>m_checkNoBoot</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>base_K3bBootImageView</receiver>
+ <slot>slotOptionsChanged()</slot>
+ </connection>
+ <connection>
+ <sender>m_checkInfoTable</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>base_K3bBootImageView</receiver>
+ <slot>slotOptionsChanged()</slot>
+ </connection>
+ <connection>
+ <sender>m_editLoadSegment</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>base_K3bBootImageView</receiver>
+ <slot>slotOptionsChanged()</slot>
+ </connection>
+ <connection>
+ <sender>m_editLoadSize</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>base_K3bBootImageView</receiver>
+ <slot>slotOptionsChanged()</slot>
+ </connection>
+ <connection>
+ <sender>m_radioNoEmulation</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textLabel2_2</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioNoEmulation</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textLabel3</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioNoEmulation</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_editLoadSegment</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioNoEmulation</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_editLoadSize</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioNoEmulation</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_checkNoBoot</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioNoEmulation</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>base_K3bBootImageView</receiver>
+ <slot>slotOptionsChanged()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot access="protected">slotOptionsChanged()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/src/projects/base_k3bdataimagesettings.ui b/src/projects/base_k3bdataimagesettings.ui
new file mode 100644
index 0000000..3427ab7
--- /dev/null
+++ b/src/projects/base_k3bdataimagesettings.ui
@@ -0,0 +1,274 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bDataImageSettings</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bDataImageSetings</cstring>
+ </property>
+ <property name="caption">
+ <string>Data Image Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupVolumeName</cstring>
+ </property>
+ <property name="title">
+ <string>Volume Name</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_editVolumeName</cstring>
+ </property>
+ <property name="maxLength">
+ <number>32</number>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonMoreVolDescFields</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;More fields...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupFileSystem</cstring>
+ </property>
+ <property name="title">
+ <string>File System</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_comboFilesystems</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>File system presets</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonCustomFilesystems</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Custom...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupSymlinks</cstring>
+ </property>
+ <property name="title">
+ <string>Symbolic Links</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>No Change</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Discard broken symlinks</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Discard all symlinks</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Follow symlinks</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_comboSymlinkHandling</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Symbolic link handling in the project</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;K3b can create ISO9660 filesystems that contain symlinks if the Rock Ridge extensions are enabled (they are by default). You can change the way symlinks are handled in a K3b project.
+
+&lt;p&gt;&lt;b&gt;No Change&lt;/b&gt;&lt;br&gt;
+Symlinks are used as they have been added to the project.
+
+&lt;p&gt;&lt;b&gt;Discard broken symlinks&lt;/b&gt;&lt;br&gt;
+K3b will discard all symbolic links that do not point to a file inside the project. That includes all links to absolute paths like '/home/myhome/testfile'.
+
+&lt;p&gt;&lt;b&gt;Discard all symlinks&lt;/b&gt;&lt;br&gt;
+K3b will discard all symbolic links that have been added to the project; meaning that the resulting file system will have no links at all.
+
+&lt;p&gt;&lt;b&gt;Follow symlinks&lt;/b&gt;&lt;br&gt;
+Each symbolic link in the project will be replaced with the contents of the file it is pointing to. Thus, the resulting filesystem will not contain any symbolic links.&lt;br&gt;
+Be aware that in case Rock Ridge extensions are disabled (which is not recommended) symbolic links are always followed because ISO9660 does not support symbolic links.
+
+&lt;p&gt;&lt;b&gt;Caution:&lt;/b&gt; Symbolic links require Rock Ridge extensions.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupWhitespace</cstring>
+ </property>
+ <property name="title">
+ <string>White space handling</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>No Change</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Strip</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Extended Strip</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Replace</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_comboSpaceHandling</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Handling of spaces in filenames</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;&lt;b&gt;No Change&lt;/b&gt;&lt;br&gt;
+If this option is checked, K3b will leave all spaces in filenames as they are.
+&lt;p&gt;&lt;b&gt;Strip&lt;/b&gt;&lt;br&gt;
+If this option is checked, K3b will remove all spaces from all filenames.&lt;br&gt;
+Example: 'my good file.ext' becomes 'mygoodfile.ext'
+&lt;p&gt;&lt;b&gt;Extended Strip&lt;/b&gt;&lt;br&gt;
+If this option is checked K3b will remove all spaces in all filenames and capitalize all letters following a space.&lt;br&gt;
+Example: 'my good file.ext' becomes 'myGoodFile.ext'
+&lt;p&gt;&lt;b&gt;Replace&lt;/b&gt;&lt;br&gt;
+If this option is checked, K3b will replace all spaces in all filenames with the specified characters.&lt;br&gt;
+Example: 'my good file.ext' becomes 'my_good_file.ext'</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_editReplace</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>_</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>The string to replace spaces with</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>m_editReplace</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/src/projects/base_k3bdatavolumedescwidget.ui b/src/projects/base_k3bdatavolumedescwidget.ui
new file mode 100644
index 0000000..ce31be9
--- /dev/null
+++ b/src/projects/base_k3bdatavolumedescwidget.ui
@@ -0,0 +1,370 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bDataVolumeDescWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bDataVolumeDescWidget</cstring>
+ </property>
+ <property name="caption">
+ <string>Volume Descriptor</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>m_editVolumeName</cstring>
+ </property>
+ <property name="maxLength">
+ <number>32</number>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>m_editVolumeSetName</cstring>
+ </property>
+ <property name="maxLength">
+ <number>128</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>V&amp;olume set name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editVolumeSetName</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Volume name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editVolumeName</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="3" column="1">
+ <property name="name">
+ <cstring>m_editPublisher</cstring>
+ </property>
+ <property name="maxLength">
+ <number>128</number>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="4" column="1">
+ <property name="name">
+ <cstring>m_editPreparer</cstring>
+ </property>
+ <property name="maxLength">
+ <number>128</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>P&amp;reparer:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editPreparer</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>P&amp;ublisher:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editPublisher</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Volu&amp;me set size:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_spinVolumeSetSize</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="1">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_spinVolumeSetSize</cstring>
+ </property>
+ <property name="specialValueText">
+ <string></string>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Volume set &amp;number:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_spinVolumeSetNumber</cstring>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_spinVolumeSetNumber</cstring>
+ </property>
+ <property name="specialValueText">
+ <string></string>
+ </property>
+ <property name="maxValue">
+ <number>2</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="6" column="0">
+ <property name="name">
+ <cstring>TextLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>S&amp;ystem:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editSystem</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="6" column="1">
+ <property name="name">
+ <cstring>m_editSystem</cstring>
+ </property>
+ <property name="maxLength">
+ <number>32</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="7" column="0">
+ <property name="name">
+ <cstring>TextLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Application:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_editApplication</cstring>
+ </property>
+ </widget>
+ <spacer row="12" column="1">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="Line" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="7" column="1">
+ <property name="name">
+ <cstring>m_editApplication</cstring>
+ </property>
+ <property name="maxLength">
+ <number>128</number>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="11" column="1">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_editBiblio</cstring>
+ </property>
+ <property name="maxLength">
+ <number>37</number>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonFindBiblio</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select a bibliographic file from the project</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="9" column="1">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_editAbstract</cstring>
+ </property>
+ <property name="maxLength">
+ <number>37</number>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonFindAbstract</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select an abstract file from the project</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="10" column="1">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_editCopyright</cstring>
+ </property>
+ <property name="maxLength">
+ <number>37</number>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonFindCopyright</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select a copyright file from the project</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="9" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Abstract file:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="10" column="0">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Copyright file:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="11" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Bibliographic file:</string>
+ </property>
+ </widget>
+ <widget class="Line" row="8" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>line1_2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>m_editVolumeName</tabstop>
+ <tabstop>m_editVolumeSetName</tabstop>
+ <tabstop>m_spinVolumeSetSize</tabstop>
+ <tabstop>m_spinVolumeSetNumber</tabstop>
+ <tabstop>m_editPublisher</tabstop>
+ <tabstop>m_editPreparer</tabstop>
+ <tabstop>m_editSystem</tabstop>
+ <tabstop>m_editApplication</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/src/projects/base_k3bmovixoptionswidget.ui b/src/projects/base_k3bmovixoptionswidget.ui
new file mode 100644
index 0000000..973dd11
--- /dev/null
+++ b/src/projects/base_k3bmovixoptionswidget.ui
@@ -0,0 +1,337 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bMovixOptionsWidget</class>
+<author>Sebastian trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Playback Settings</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>MPlayer subtitle fontset:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_comboSubtitleFontset</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the font to be used to render subtitles</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel7</cstring>
+ </property>
+ <property name="text">
+ <string>Unwanted MPlayer options:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkRandomPlay</cstring>
+ </property>
+ <property name="text">
+ <string>Pla&amp;y files randomly</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>The files are played in random order</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked the order in which the files are played is determined randomly every time it is played.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkNoDma</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Do not use DMA</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Do not use DMA for media access</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked the resulting eMovix CD/DVD will not use DMA for accessing the drive. This will slow down reading from the CD/DVD but may be necessary on some systems that do not support DMA.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLineEdit" row="5" column="1">
+ <property name="name">
+ <cstring>m_editUnwantedMplayerOptions</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>MPlayer options you want to be sure MPlayer will not use</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Here one can specify MPlayer options that should never be used.
+&lt;p&gt;They have to be separated by spaces:
+&lt;pre&gt;opt1 opt2 opt3&lt;/pre&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="4" column="1">
+ <property name="name">
+ <cstring>m_editAdditionalMplayerOptions</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Additional MPlayer options</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;MPlayer options that should be used in any case.
+&lt;p&gt;They have to be separated by spaces:
+&lt;pre&gt;opt1 opt2 opt3&lt;/pre&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>Additional MPlayer options:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Loop playlist:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="2" column="1">
+ <property name="name">
+ <cstring>m_spinLoop</cstring>
+ </property>
+ <property name="suffix">
+ <string> time(s)</string>
+ </property>
+ <property name="specialValueText">
+ <string>infinity</string>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>How many times should the playlist be looped</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>m_labelAudioBackground</cstring>
+ </property>
+ <property name="text">
+ <string>Audio Player Background:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>m_comboAudioBackground</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Background video to show during audio playback</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;&lt;b&gt;Audio Player Background&lt;/b&gt;
+&lt;p&gt;During audio playback normally the screen would be black. However, if a background movie has been selected, eMovix will display it during playback.
+&lt;p&gt;Additional background movies can be installed. However, this is not as simple as a few mouse clicks. The background movies are stored in the emovix shared data folder (mostly &lt;i&gt;/usr/share/emovix&lt;/i&gt; or &lt;i&gt;/usr/local/share/emovix&lt;/i&gt;) under &lt;em&gt;backgrounds&lt;/em&gt;. So to add a background one has to copy the file to that folder.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Startup Behavior</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>m_labelKeyboardLayout</cstring>
+ </property>
+ <property name="text">
+ <string>Keyboard Layout:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>eMovix boot messages language:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_comboBootMessageLanguage</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the language of the eMovix help screens</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Default boot label:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="1">
+ <property name="name">
+ <cstring>m_comboDefaultBootLabel</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the default Linux kernel configuration</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;&lt;b&gt;eMovix Boot Labels&lt;/b&gt;
+&lt;p&gt;eMovix provides are variety or different boot configurations which can be selected at boot time via a boot label (compare Lilo or Grub). The many different boot configurations mainly influence the Video output.
+&lt;p&gt;The &lt;b&gt;default&lt;/b&gt;, &lt;b&gt;movix&lt;/b&gt;, or &lt;b&gt;MoviX&lt;/b&gt; labels start a general Vesa video driver.
+&lt;p&gt;The &lt;b&gt;TV&lt;/b&gt; labels can be used to direct video to the TV output of the graphic board. eMovix provides TVout drivers for different brands of graphic boards.
+&lt;p&gt;The &lt;b&gt;FB&lt;/b&gt; labels refer to configurations that start a Frame Buffer driver in different screen resolutions.
+&lt;p&gt;The &lt;b&gt;AA&lt;/b&gt; labels make eMovix output the video through the Ascii-Art library which displays the picture in text mode through the usage of simple Acsii characters.
+&lt;p&gt;The &lt;b&gt;hd&lt;/b&gt; label makes eMovix boot from the local harddisk instead of the medium. This can be used to prevent accidental starting of an eMovix medium.
+&lt;p&gt;The &lt;b&gt;floppy&lt;/b&gt; label makes eMovix boot from the local floppy drive instead of the medium.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>m_comboKeyboardLayout</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the layout of the keyboard</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;The keyboard layout selected here will be used for the eMovix commands like controlling the media player.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Behavior After Playing</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkEject</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;ject disk</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Eject the disk after playing has finished</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked the disk will be ejected after MPlayer has finished.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkShutdown</cstring>
+ </property>
+ <property name="text">
+ <string>Sh&amp;utdown</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Shutdown after playing has finished</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked the PC will be shut down after MPlayer has finished playing.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkReboot</cstring>
+ </property>
+ <property name="text">
+ <string>Re&amp;boot</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Reboot after playing has finished</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked the PC will be rebooted after MPlayer has finished playing.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_checkShutdown</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_checkReboot</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkReboot</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_checkShutdown</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/src/projects/k3baudioburndialog.cpp b/src/projects/k3baudioburndialog.cpp
new file mode 100644
index 0000000..97bf318
--- /dev/null
+++ b/src/projects/k3baudioburndialog.cpp
@@ -0,0 +1,341 @@
+/*
+ *
+ * $Id: k3baudioburndialog.cpp 623768 2007-01-15 13:33:55Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3baudioburndialog.h"
+#include "k3baudioview.h"
+#include "k3baudiotrackplayer.h"
+#include "k3baudiotrack.h"
+#include "k3baudiocdtracksource.h"
+#include <k3bcore.h>
+#include "k3baudiodoc.h"
+#include <k3bdevice.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include "k3baudiocdtextwidget.h"
+#include <k3bglobals.h>
+#include <k3bstdguiitems.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bexternalbinmanager.h>
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qgrid.h>
+#include <qtoolbutton.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qpoint.h>
+#include <qhbox.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+
+
+K3bAudioBurnDialog::K3bAudioBurnDialog(K3bAudioDoc* _doc, QWidget *parent, const char *name, bool modal )
+ : K3bProjectBurnDialog( _doc, parent, name, modal ),
+ m_doc(_doc)
+{
+ prepareGui();
+
+ setTitle( i18n("Audio Project"),
+ i18n("1 track (%1 minutes)", "%n tracks (%1 minutes)",
+ m_doc->numOfTracks() ).arg(m_doc->length().toString()) );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ // create cd-text page
+ m_cdtextWidget = new K3bAudioCdTextWidget( this );
+ addPage( m_cdtextWidget, i18n("CD-Text") );
+
+ // create advanced tab
+ // ----------------------------------------------------------
+ QWidget* advancedTab = new QWidget( this );
+ QGridLayout* advancedTabGrid = new QGridLayout( advancedTab );
+ advancedTabGrid->setSpacing( spacingHint() );
+ advancedTabGrid->setMargin( marginHint() );
+
+ QGroupBox* advancedSettingsGroup = new QGroupBox( 1, Qt::Vertical, i18n("Settings"), advancedTab );
+ m_checkNormalize = K3bStdGuiItems::normalizeCheckBox( advancedSettingsGroup );
+
+ QGroupBox* advancedGimmickGroup = new QGroupBox( 1, Qt::Vertical, i18n("Gimmicks"), advancedTab );
+ m_checkHideFirstTrack = new QCheckBox( i18n( "Hide first track" ), advancedGimmickGroup, "m_checkHideFirstTrack" );
+
+ m_audioRippingGroup = new QGroupBox( 3, Qt::Vertical, i18n("Audio Ripping"), advancedTab );
+ QHBox* box = new QHBox( m_audioRippingGroup );
+ box->setSpacing( spacingHint() );
+ box->setStretchFactor(new QLabel( i18n("Paranoia mode:"), box ), 1 );
+ m_comboParanoiaMode = K3bStdGuiItems::paranoiaModeComboBox( box );
+ box = new QHBox( m_audioRippingGroup );
+ box->setSpacing( spacingHint() );
+ box->setStretchFactor( new QLabel( i18n("Read retries:"), box ), 1 );
+ m_spinAudioRippingReadRetries = new QSpinBox( 1, 128, 1, box );
+ m_checkAudioRippingIgnoreReadErrors = new QCheckBox( i18n("Ignore read errors"), m_audioRippingGroup );
+
+ advancedTabGrid->addWidget( advancedSettingsGroup, 0, 0 );
+ advancedTabGrid->addWidget( advancedGimmickGroup, 1, 0 );
+ advancedTabGrid->addWidget( m_audioRippingGroup, 2, 0 );
+ advancedTabGrid->setRowStretch( 3, 1 );
+
+ addPage( advancedTab, i18n("Advanced") );
+
+ connect( m_writerSelectionWidget, SIGNAL(writingAppChanged(int)), this, SLOT(slotToggleAll()) );
+ connect( m_checkNormalize, SIGNAL(toggled(bool)), this, SLOT(slotNormalizeToggled(bool)) );
+ connect( m_checkCacheImage, SIGNAL(toggled(bool)), this, SLOT(slotCacheImageToggled(bool)) );
+ connect( m_writingModeWidget, SIGNAL(writingModeChanged(int)), this, SLOT(slotToggleAll()) );
+
+ // ToolTips
+ // -------------------------------------------------------------------------
+ QToolTip::add( m_checkHideFirstTrack, i18n("Hide the first track in the first pregap") );
+
+ // What's This info
+ // -------------------------------------------------------------------------
+ QWhatsThis::add( m_checkHideFirstTrack,
+ i18n("<p>If this option is checked K3b will <em>hide</em> the first track."
+ "<p>The audio CD standard uses pregaps before every track on the CD. "
+ "By default these last for 2 seconds and are silent. In DAO mode it "
+ "is possible to have longer pregaps that contain some audio. In this case "
+ "the first pregap will contain the complete first track."
+ "<p>You will need to seek back from the beginning of the CD to listen to "
+ "the first track. Try it, it is quite amusing."
+ "<p><b>This feature is only available in DAO mode when writing with cdrdao.") );
+}
+
+K3bAudioBurnDialog::~K3bAudioBurnDialog(){
+}
+
+
+void K3bAudioBurnDialog::slotStartClicked()
+{
+ static_cast<K3bAudioView*>(m_doc->view())->player()->stop();
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+
+void K3bAudioBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ m_doc->setTempDir( m_tempDirSelectionWidget->tempPath() );
+ m_doc->setHideFirstTrack( m_checkHideFirstTrack->isChecked() );
+ m_doc->setNormalize( m_checkNormalize->isChecked() );
+
+ // -- save Cd-Text ------------------------------------------------
+ m_cdtextWidget->save( m_doc );
+
+ // audio ripping
+ m_doc->setAudioRippingParanoiaMode( m_comboParanoiaMode->currentText().toInt() );
+ m_doc->setAudioRippingRetries( m_spinAudioRippingReadRetries->value() );
+ m_doc->setAudioRippingIgnoreReadErrors( m_checkAudioRippingIgnoreReadErrors->isChecked() );
+
+ doc()->setTempDir( m_tempDirSelectionWidget->tempPath() );
+}
+
+
+void K3bAudioBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ m_checkHideFirstTrack->setChecked( m_doc->hideFirstTrack() );
+ m_checkNormalize->setChecked( m_doc->normalize() );
+
+ // read CD-Text ------------------------------------------------------------
+ m_cdtextWidget->load( m_doc );
+
+ // audio ripping
+ m_comboParanoiaMode->setCurrentItem( m_doc->audioRippingParanoiaMode() );
+ m_checkAudioRippingIgnoreReadErrors->setChecked( m_doc->audioRippingIgnoreReadErrors() );
+ m_spinAudioRippingReadRetries->setValue( m_doc->audioRippingRetries() );
+
+ if( !doc()->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( doc()->tempDir() );
+
+ toggleAll();
+}
+
+
+void K3bAudioBurnDialog::loadK3bDefaults()
+{
+ K3bProjectBurnDialog::loadK3bDefaults();
+
+ m_cdtextWidget->setChecked( true );
+ m_checkHideFirstTrack->setChecked( false );
+ m_checkNormalize->setChecked(false);
+
+ m_comboParanoiaMode->setCurrentItem( 0 );
+ m_checkAudioRippingIgnoreReadErrors->setChecked( true );
+ m_spinAudioRippingReadRetries->setValue( 5 );
+
+ toggleAll();
+}
+
+
+void K3bAudioBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults( c );
+
+ m_cdtextWidget->setChecked( c->readBoolEntry( "cd_text", true ) );
+ m_checkHideFirstTrack->setChecked( c->readBoolEntry( "hide_first_track", false ) );
+ m_checkNormalize->setChecked( c->readBoolEntry( "normalize", false ) );
+
+ m_comboParanoiaMode->setCurrentItem( c->readNumEntry( "paranoia mode", 0 ) );
+ m_checkAudioRippingIgnoreReadErrors->setChecked( c->readBoolEntry( "ignore read errors", true ) );
+ m_spinAudioRippingReadRetries->setValue( c->readNumEntry( "read retries", 5 ) );
+
+ toggleAll();
+}
+
+
+void K3bAudioBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults( c );
+
+ c->writeEntry( "cd_text", m_cdtextWidget->isChecked() );
+ c->writeEntry( "hide_first_track", m_checkHideFirstTrack->isChecked() );
+ c->writeEntry( "normalize", m_checkNormalize->isChecked() );
+
+ c->writeEntry( "paranoia mode", m_comboParanoiaMode->currentText() );
+ c->writeEntry( "ignore read errors", m_checkAudioRippingIgnoreReadErrors->isChecked() );
+ c->writeEntry( "read retries", m_spinAudioRippingReadRetries->value() );
+}
+
+void K3bAudioBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ bool cdrecordOnTheFly = false;
+ bool cdrecordCdText = false;
+ if ( k3bcore->externalBinManager()->binObject("cdrecord") ) {
+ cdrecordOnTheFly = k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "audio-stdin" );
+ cdrecordCdText = k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "cdtext" );
+ }
+
+ // cdrdao always knows onthefly and cdtext
+ bool onTheFly = true;
+ bool cdText = true;
+ if( m_writingModeWidget->writingMode() == K3b::TAO ||
+ m_writingModeWidget->writingMode() == K3b::RAW ||
+ m_writerSelectionWidget->writingApp() == K3b::CDRECORD ) {
+ onTheFly = cdrecordOnTheFly;
+ cdText = cdrecordCdText;
+ m_checkHideFirstTrack->setChecked(false);
+ m_checkHideFirstTrack->setEnabled(false);
+ }
+ else {
+ m_checkHideFirstTrack->setEnabled( !m_checkOnlyCreateImage->isChecked() );
+ m_cdtextWidget->setEnabled( !m_checkOnlyCreateImage->isChecked() );
+ }
+
+ m_checkCacheImage->setEnabled( !m_checkOnlyCreateImage->isChecked() &&
+ onTheFly );
+ if( !onTheFly )
+ m_checkCacheImage->setChecked( true );
+ m_cdtextWidget->setEnabled( !m_checkOnlyCreateImage->isChecked() &&
+ cdText &&
+ m_writingModeWidget->writingMode() != K3b::TAO );
+ if( !cdText || m_writingModeWidget->writingMode() == K3b::TAO )
+ m_cdtextWidget->setChecked(false);
+}
+
+
+void K3bAudioBurnDialog::showEvent( QShowEvent* e )
+{
+ // we only show the audio ripping options when there are audio cd track sources
+ bool showRipOptions = false;
+ if( m_doc->firstTrack() ) {
+ K3bAudioTrack* track = m_doc->firstTrack();
+ K3bAudioDataSource* source = track->firstSource();
+
+ while( source ) {
+
+ if( dynamic_cast<K3bAudioCdTrackSource*>(source) ) {
+ showRipOptions = true;
+ break;
+ }
+
+ // next source
+ source = source->next();
+ if( !source ) {
+ track = track->next();
+ if( track )
+ source = track->firstSource();
+ }
+ }
+ }
+
+ m_audioRippingGroup->setShown( showRipOptions );
+
+ K3bProjectBurnDialog::showEvent(e);
+}
+
+
+void K3bAudioBurnDialog::slotNormalizeToggled( bool on )
+{
+ if( on ) {
+ // we are not able to normalize in on-the-fly mode
+ if( !k3bcore->externalBinManager()->foundBin( "normalize-audio" ) ) {
+ KMessageBox::sorry( this, i18n("<p><b>External program <em>normalize-audio</em> is not installed.</b>"
+ "<p>K3b uses <em>normalize-audio</em> (http://www1.cs.columbia.edu/~cvaill/normalize/) "
+ "to normalize audio tracks. In order to "
+ "use this functionality, please install it first. (sudo apt-get install normalize-audio)") );
+ m_checkNormalize->setChecked( false );
+ }
+ else if( !m_checkCacheImage->isChecked() && !m_checkOnlyCreateImage->isChecked() ) {
+ if( KMessageBox::warningYesNo( this, i18n("<p>K3b is not able to normalize audio tracks when burning on-the-fly. "
+ "The external program used for this task only supports normalizing a set "
+ "of audio files."),
+ QString::null,
+ i18n("Disable normalization"),
+ i18n("Disable on-the-fly burning"),
+ "audioProjectNormalizeOrOnTheFly" ) == KMessageBox::Yes )
+ m_checkNormalize->setChecked( false );
+ else
+ m_checkCacheImage->setChecked( true );
+ }
+ }
+}
+
+
+void K3bAudioBurnDialog::slotCacheImageToggled( bool on )
+{
+ if( !on ) {
+ if( m_checkNormalize->isChecked() ) {
+ if( KMessageBox::warningYesNo( this, i18n("<p>K3b is not able to normalize audio tracks when burning on-the-fly. "
+ "The external program used for this task only supports normalizing a set "
+ "of audio files."),
+ QString::null,
+ i18n("Disable normalization"),
+ i18n("Disable on-the-fly burning"),
+ "audioProjectNormalizeOrOnTheFly" ) == KMessageBox::Yes )
+ m_checkNormalize->setChecked( false );
+ else
+ m_checkCacheImage->setChecked( true );
+ }
+ }
+}
+
+#include "k3baudioburndialog.moc"
diff --git a/src/projects/k3baudioburndialog.h b/src/projects/k3baudioburndialog.h
new file mode 100644
index 0000000..47be09f
--- /dev/null
+++ b/src/projects/k3baudioburndialog.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * $Id: k3baudioburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BAUDIOBURNDIALOG_H
+#define K3BAUDIOBURNDIALOG_H
+
+
+#include "k3bprojectburndialog.h"
+
+#include <qvariant.h>
+#include <qwidget.h>
+
+class QCheckBox;
+class QComboBox;
+class QGroupBox;
+class QLabel;
+class QLineEdit;
+class QSpinBox;
+class K3bWriterSelectionWidget;
+class K3bTempDirSelectionWidget;
+class K3bAudioDoc;
+class K3bAudioCdTextWidget;
+class QShowEvent;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bAudioBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioBurnDialog(K3bAudioDoc* doc, QWidget *parent=0, const char *name=0, bool modal = true );
+ ~K3bAudioBurnDialog();
+
+ protected:
+ void saveSettings();
+ void readSettings();
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void showEvent( QShowEvent* );
+ void toggleAll();
+
+ protected slots:
+ /**
+ * Reimplemented for internal reasons (shut down the audio player)
+ */
+ void slotStartClicked();
+ void slotCacheImageToggled( bool on );
+ void slotNormalizeToggled( bool on );
+
+ private:
+ /**
+ * We need this here to be able to hide/show the group
+ */
+ QGroupBox* m_audioRippingGroup;
+ QCheckBox* m_checkHideFirstTrack;
+ QCheckBox* m_checkNormalize;
+ QCheckBox* m_checkAudioRippingIgnoreReadErrors;
+ QSpinBox* m_spinAudioRippingReadRetries;
+ QComboBox* m_comboParanoiaMode;
+ K3bAudioCdTextWidget* m_cdtextWidget;
+ K3bAudioDoc* m_doc;
+};
+
+#endif
diff --git a/src/projects/k3baudiocdtextwidget.cpp b/src/projects/k3baudiocdtextwidget.cpp
new file mode 100644
index 0000000..8ee5543
--- /dev/null
+++ b/src/projects/k3baudiocdtextwidget.cpp
@@ -0,0 +1,236 @@
+/*
+ *
+ * $Id: k3baudiocdtextwidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiocdtextwidget.h"
+#include "base_k3baudiocdtextallfieldswidget.h"
+
+#include "k3baudiodoc.h"
+#include "k3baudiotrack.h"
+#include <k3bcdtextvalidator.h>
+
+#include <qcheckbox.h>
+#include <qtoolbutton.h>
+#include <qpushbutton.h>
+#include <qptrlist.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+
+#include <klineedit.h>
+#include <klocale.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+
+
+class K3bAudioCdTextWidget::AllFieldsDialog : public KDialogBase
+{
+public:
+ AllFieldsDialog( QWidget* parent )
+ : KDialogBase( parent,
+ "cdtext_allfields_dialog",
+ true,
+ i18n("CD-Text"),
+ Ok|Cancel,
+ Ok,
+ true ) {
+ w = new base_K3bAudioCdTextAllFieldsWidget( this );
+ setMainWidget( w );
+ }
+
+ base_K3bAudioCdTextAllFieldsWidget* w;
+};
+
+
+K3bAudioCdTextWidget::K3bAudioCdTextWidget( QWidget* parent, const char* name )
+ : base_K3bAudioCdTextWidget( parent, name ),
+ m_doc(0)
+{
+ m_allFieldsDlg = new AllFieldsDialog( this );
+
+ m_buttonCopyTitle->setPixmap( SmallIcon( "editcopy" ) );
+ m_buttonCopyPerformer->setPixmap( SmallIcon( "editcopy" ) );
+
+ m_allFieldsDlg->w->m_buttonCopyTitle->setPixmap( SmallIcon( "editcopy" ) );
+ m_allFieldsDlg->w->m_buttonCopyPerformer->setPixmap( SmallIcon( "editcopy" ) );
+ m_allFieldsDlg->w->m_buttonCopySongwriter->setPixmap( SmallIcon( "editcopy" ) );
+ m_allFieldsDlg->w->m_buttonCopyComposer->setPixmap( SmallIcon( "editcopy" ) );
+ m_allFieldsDlg->w->m_buttonCopyArranger->setPixmap( SmallIcon( "editcopy" ) );
+
+ QValidator* cdTextVal = new K3bCdTextValidator( this );
+ m_editTitle->setValidator( cdTextVal );
+ m_editPerformer->setValidator( cdTextVal );
+
+ m_allFieldsDlg->w->m_editTitle->setValidator( cdTextVal );
+ m_allFieldsDlg->w->m_editPerformer->setValidator( cdTextVal );
+ m_allFieldsDlg->w->m_editDisc_id->setValidator( cdTextVal );
+ m_allFieldsDlg->w->m_editUpc_ean->setValidator( cdTextVal );
+ m_allFieldsDlg->w->m_editMessage->setValidator( cdTextVal );
+ m_allFieldsDlg->w->m_editArranger->setValidator( cdTextVal );
+ m_allFieldsDlg->w->m_editSongwriter->setValidator( cdTextVal );
+ m_allFieldsDlg->w->m_editComposer->setValidator( cdTextVal );
+
+ connect( m_allFieldsDlg->w->m_buttonCopyTitle, SIGNAL(clicked()),
+ this, SLOT(slotCopyTitle()) );
+ connect( m_allFieldsDlg->w->m_buttonCopyPerformer, SIGNAL(clicked()),
+ this, SLOT(slotCopyPerformer()) );
+ connect( m_allFieldsDlg->w->m_buttonCopyArranger, SIGNAL(clicked()),
+ this, SLOT(slotCopyArranger()) );
+ connect( m_allFieldsDlg->w->m_buttonCopySongwriter, SIGNAL(clicked()),
+ this, SLOT(slotCopySongwriter()) );
+ connect( m_allFieldsDlg->w->m_buttonCopyComposer, SIGNAL(clicked()),
+ this, SLOT(slotCopyComposer()) );
+
+ connect( m_buttonMoreFields, SIGNAL(clicked()),
+ this, SLOT(slotMoreFields()) );
+}
+
+
+K3bAudioCdTextWidget::~K3bAudioCdTextWidget()
+{
+}
+
+void K3bAudioCdTextWidget::load( K3bAudioDoc* doc )
+{
+ m_doc = doc;
+ m_groupCdText->setChecked( doc->cdText() );
+
+ m_editTitle->setText( doc->title() );
+ m_editPerformer->setText( doc->artist() );
+
+ m_allFieldsDlg->w->m_editTitle->setText( doc->title() );
+ m_allFieldsDlg->w->m_editPerformer->setText( doc->artist() );
+ m_allFieldsDlg->w->m_editDisc_id->setText( doc->disc_id() );
+ m_allFieldsDlg->w->m_editUpc_ean->setText( doc->upc_ean() );
+ m_allFieldsDlg->w->m_editArranger->setText( doc->arranger() );
+ m_allFieldsDlg->w->m_editSongwriter->setText( doc->songwriter() );
+ m_allFieldsDlg->w->m_editComposer->setText( doc->composer() );
+ m_allFieldsDlg->w->m_editMessage->setText( doc->cdTextMessage() );
+}
+
+void K3bAudioCdTextWidget::save( K3bAudioDoc* doc )
+{
+ m_doc = doc;
+ doc->writeCdText( m_groupCdText->isChecked() );
+
+ // we save the title and artist values from the main view since
+ // the dialog is only updated before it is shown
+ doc->setTitle( m_editTitle->text() );
+ doc->setArtist( m_editPerformer->text() );
+ doc->setDisc_id( m_allFieldsDlg->w->m_editDisc_id->text() );
+ doc->setUpc_ean( m_allFieldsDlg->w->m_editUpc_ean->text() );
+ doc->setArranger( m_allFieldsDlg->w->m_editArranger->text() );
+ doc->setSongwriter( m_allFieldsDlg->w->m_editSongwriter->text() );
+ doc->setComposer( m_allFieldsDlg->w->m_editComposer->text() );
+ doc->setCdTextMessage( m_allFieldsDlg->w->m_editMessage->text() );
+}
+
+
+void K3bAudioCdTextWidget::slotMoreFields()
+{
+ // update dlg to current state
+ m_allFieldsDlg->w->m_editTitle->setText( m_editTitle->text() );
+ m_allFieldsDlg->w->m_editPerformer->setText( m_editPerformer->text() );
+
+ // save old settings
+ QString title = m_allFieldsDlg->w->m_editTitle->text();
+ QString performer = m_allFieldsDlg->w->m_editPerformer->text();
+ QString disc_id = m_allFieldsDlg->w->m_editDisc_id->text();
+ QString upc_ean = m_allFieldsDlg->w->m_editUpc_ean->text();
+ QString arranger = m_allFieldsDlg->w->m_editArranger->text();
+ QString songwriter = m_allFieldsDlg->w->m_editSongwriter->text();
+ QString composer = m_allFieldsDlg->w->m_editComposer->text();
+ QString message = m_allFieldsDlg->w->m_editMessage->text();
+
+ // exec dlg
+ if( m_allFieldsDlg->exec() == QDialog::Accepted ) {
+ // accept new entries
+ m_editTitle->setText( m_allFieldsDlg->w->m_editTitle->text() );
+ m_editPerformer->setText( m_allFieldsDlg->w->m_editPerformer->text() );
+ }
+ else {
+ // reset
+ m_allFieldsDlg->w->m_editTitle->setText( title );
+ m_allFieldsDlg->w->m_editPerformer->setText( performer );
+ m_allFieldsDlg->w->m_editDisc_id->setText( disc_id );
+ m_allFieldsDlg->w->m_editUpc_ean->setText( upc_ean );
+ m_allFieldsDlg->w->m_editArranger->setText( arranger );
+ m_allFieldsDlg->w->m_editSongwriter->setText( songwriter );
+ m_allFieldsDlg->w->m_editComposer->setText( composer );
+ m_allFieldsDlg->w->m_editMessage->setText( message );
+ }
+}
+
+
+void K3bAudioCdTextWidget::setChecked( bool b )
+{
+ m_groupCdText->setChecked( b );
+}
+
+bool K3bAudioCdTextWidget::isChecked() const
+{
+ return m_groupCdText->isChecked();
+}
+
+
+void K3bAudioCdTextWidget::slotCopyTitle()
+{
+ K3bAudioTrack* track = m_doc->firstTrack();
+ while( track ) {
+ track->setTitle( m_allFieldsDlg->isVisible()
+ ? m_allFieldsDlg->w->m_editTitle->text()
+ : m_editTitle->text() );
+ track = track->next();
+ }
+}
+
+void K3bAudioCdTextWidget::slotCopyPerformer()
+{
+ K3bAudioTrack* track = m_doc->firstTrack();
+ while( track ) {
+ track->setPerformer( m_allFieldsDlg->isVisible()
+ ? m_allFieldsDlg->w->m_editPerformer->text()
+ : m_editPerformer->text() );
+ track = track->next();
+ }
+}
+
+void K3bAudioCdTextWidget::slotCopyArranger()
+{
+ K3bAudioTrack* track = m_doc->firstTrack();
+ while( track ) {
+ track->setArranger( m_allFieldsDlg->w->m_editArranger->text() );
+ track = track->next();
+ }
+}
+
+void K3bAudioCdTextWidget::slotCopySongwriter()
+{
+ K3bAudioTrack* track = m_doc->firstTrack();
+ while( track ) {
+ track->setSongwriter( m_allFieldsDlg->w->m_editSongwriter->text() );
+ track = track->next();
+ }
+}
+
+void K3bAudioCdTextWidget::slotCopyComposer()
+{
+ K3bAudioTrack* track = m_doc->firstTrack();
+ while( track ) {
+ track->setComposer( m_allFieldsDlg->w->m_editComposer->text() );
+ track = track->next();
+ }
+}
+
+
+#include "k3baudiocdtextwidget.moc"
diff --git a/src/projects/k3baudiocdtextwidget.h b/src/projects/k3baudiocdtextwidget.h
new file mode 100644
index 0000000..49b579f
--- /dev/null
+++ b/src/projects/k3baudiocdtextwidget.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id: k3baudiocdtextwidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3B_AUDIO_CDTEXT_WIDGET_H
+#define K3B_AUDIO_CDTEXT_WIDGET_H
+
+#include "base_k3baudiocdtextwidget.h"
+
+
+class K3bAudioDoc;
+
+
+class K3bAudioCdTextWidget : public base_K3bAudioCdTextWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioCdTextWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioCdTextWidget();
+
+ bool isChecked() const;
+
+ public slots:
+ void setChecked( bool );
+ void load( K3bAudioDoc* );
+ void save( K3bAudioDoc* );
+
+ private slots:
+ void slotCopyTitle();
+ void slotCopyPerformer();
+ void slotCopyArranger();
+ void slotCopySongwriter();
+ void slotCopyComposer();
+ void slotMoreFields();
+
+ private:
+ K3bAudioDoc* m_doc;
+
+ class AllFieldsDialog;
+ AllFieldsDialog* m_allFieldsDlg;
+};
+
+#endif
diff --git a/src/projects/k3baudiodatasourceeditwidget.cpp b/src/projects/k3baudiodatasourceeditwidget.cpp
new file mode 100644
index 0000000..d54bb5d
--- /dev/null
+++ b/src/projects/k3baudiodatasourceeditwidget.cpp
@@ -0,0 +1,166 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiodatasourceeditwidget.h"
+#include "k3baudioeditorwidget.h"
+#include <k3bmsfedit.h>
+
+#include <k3baudiodatasource.h>
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+
+#include <klocale.h>
+#include <kdialog.h>
+
+
+K3bAudioDataSourceEditWidget::K3bAudioDataSourceEditWidget( QWidget* parent, const char* name )
+ : QWidget( parent, name ),
+ m_source(0)
+{
+ m_editor = new K3bAudioEditorWidget( this );
+ m_editStartOffset = new K3bMsfEdit( this );
+ m_editEndOffset = new K3bMsfEdit( this );
+
+ QLabel* startLabel = new QLabel( i18n("Start Offset") + ":", this );
+ QLabel* endLabel = new QLabel( i18n("End Offset") + ":", this );
+ endLabel->setAlignment( Qt::AlignRight );
+
+ QGridLayout* grid = new QGridLayout( this );
+ grid->setMargin( 0 );
+ grid->setSpacing( KDialog::spacingHint() );
+
+ grid->addWidget( startLabel, 0, 0 );
+ grid->addWidget( m_editStartOffset, 1, 0 );
+ grid->addMultiCellWidget( m_editor, 0, 1, 1, 1 );
+ grid->addWidget( endLabel, 0, 2 );
+ grid->addWidget( m_editEndOffset, 1, 2 );
+ grid->setColStretch( 1, 1 );
+
+ // setup connections between the msfedits and the editor
+ connect( m_editor, SIGNAL(rangeChanged(int, const K3b::Msf&, const K3b::Msf&)),
+ this, SLOT(slotRangeModified(int, const K3b::Msf&, const K3b::Msf&)) );
+
+ connect( m_editStartOffset, SIGNAL(valueChanged(const K3b::Msf&)),
+ this, SLOT(slotStartOffsetEdited(const K3b::Msf&)) );
+
+ connect( m_editEndOffset, SIGNAL(valueChanged(const K3b::Msf&)),
+ this, SLOT(slotEndOffsetEdited(const K3b::Msf&)) );
+
+ QToolTip::add( m_editor, i18n("Drag the edges of the highlighted area to define the portion of the "
+ "audio source you want to include in the Audio CD track. "
+ "You can also use the input windows to fine-tune your selection.") );
+}
+
+
+K3bAudioDataSourceEditWidget::~K3bAudioDataSourceEditWidget()
+{
+}
+
+
+K3b::Msf K3bAudioDataSourceEditWidget::startOffset() const
+{
+ return m_editor->rangeStart( m_rangeId );
+}
+
+
+K3b::Msf K3bAudioDataSourceEditWidget::endOffset() const
+{
+ return m_editor->rangeEnd( m_rangeId );
+}
+
+
+void K3bAudioDataSourceEditWidget::loadSource( K3bAudioDataSource* source )
+{
+ m_source = source;
+
+ // remove old range
+ m_editor->removeRange( m_rangeId );
+
+ // and add the proper new range
+ // the source's end offset points after the last sector while
+ // the editor widget returns the last used sector
+ m_editor->setLength( source->originalLength() );
+ m_rangeId = m_editor->addRange( source->startOffset(),
+ source->endOffset() == 0
+ ? source->originalLength()-1
+ : source->endOffset()-1,
+ false,
+ false,
+ i18n("Used part of the audio source"),
+ colorGroup().highlight() );
+
+ m_editStartOffset->setMaxValue( source->originalLength().lba() );
+ m_editEndOffset->setMaxValue( source->originalLength().lba() );
+
+ m_editStartOffset->setMsfValue( startOffset() );
+ m_editEndOffset->setMsfValue( endOffset() );
+}
+
+
+void K3bAudioDataSourceEditWidget::saveSource()
+{
+ if( m_source ) {
+ m_source->setStartOffset( startOffset() );
+ // the source's end offset points after the last sector while
+ // the editor widget returns the last used sector
+ m_source->setEndOffset( endOffset()+1 );
+ }
+}
+
+
+void K3bAudioDataSourceEditWidget::setStartOffset( const K3b::Msf& msf )
+{
+ if( m_source ) {
+ m_editor->modifyRange( m_rangeId,
+ msf,
+ endOffset() );
+ }
+}
+
+
+void K3bAudioDataSourceEditWidget::setEndOffset( const K3b::Msf& msf )
+{
+ if( m_source ) {
+ m_editor->modifyRange( m_rangeId,
+ startOffset(),
+ msf );
+ }
+}
+
+
+void K3bAudioDataSourceEditWidget::slotRangeModified( int, const K3b::Msf& start, const K3b::Msf& end )
+{
+ m_editStartOffset->setMsfValue( start );
+ m_editEndOffset->setMsfValue( end );
+}
+
+void K3bAudioDataSourceEditWidget::slotStartOffsetEdited( const K3b::Msf& msf )
+{
+ if( m_source ) {
+ m_editor->modifyRange( m_rangeId, msf, endOffset() );
+ }
+}
+
+
+void K3bAudioDataSourceEditWidget::slotEndOffsetEdited( const K3b::Msf& msf )
+{
+ if( m_source ) {
+ m_editor->modifyRange( m_rangeId, startOffset(), msf );
+ }
+}
+
+#include "k3baudiodatasourceeditwidget.moc"
diff --git a/src/projects/k3baudiodatasourceeditwidget.h b/src/projects/k3baudiodatasourceeditwidget.h
new file mode 100644
index 0000000..4c9d1cb
--- /dev/null
+++ b/src/projects/k3baudiodatasourceeditwidget.h
@@ -0,0 +1,70 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIODATASOURCE_EDITWIDGET_H_
+#define _K3B_AUDIODATASOURCE_EDITWIDGET_H_
+
+#include <qwidget.h>
+#include <k3bmsf.h>
+
+class K3bAudioDataSource;
+class K3bAudioEditorWidget;
+class K3bMsfEdit;
+
+/**
+ * Widget to modify the start and end offset of a source or simply change
+ * the length of a silence source.
+ */
+class K3bAudioDataSourceEditWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioDataSourceEditWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioDataSourceEditWidget();
+
+ K3b::Msf startOffset() const;
+
+ /**
+ * Highest value (mening to use all the data up to the end of the source)
+ * is source::originalLength().
+ *
+ * Be aware that this differs from K3bAudioDataSource::endOffset() which
+ * points after the last used sector for internal reasons.
+ */
+ K3b::Msf endOffset() const;
+
+ public slots:
+ void loadSource( K3bAudioDataSource* );
+ void saveSource();
+
+ void setStartOffset( const K3b::Msf& );
+ void setEndOffset( const K3b::Msf& );
+
+ private slots:
+ void slotRangeModified( int, const K3b::Msf&, const K3b::Msf& );
+ void slotStartOffsetEdited( const K3b::Msf& );
+ void slotEndOffsetEdited( const K3b::Msf& );
+
+ private:
+ K3bAudioDataSource* m_source;
+ int m_rangeId;
+
+ K3bAudioEditorWidget* m_editor;
+ K3bMsfEdit* m_editStartOffset;
+ K3bMsfEdit* m_editEndOffset;
+};
+
+#endif
diff --git a/src/projects/k3baudiodatasourceviewitem.cpp b/src/projects/k3baudiodatasourceviewitem.cpp
new file mode 100644
index 0000000..6cf3004
--- /dev/null
+++ b/src/projects/k3baudiodatasourceviewitem.cpp
@@ -0,0 +1,111 @@
+/*
+ *
+ * $Id: k3baudiodatasourceviewitem.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiodatasourceviewitem.h"
+#include "k3baudiodatasource.h"
+#include "k3baudiotrackviewitem.h"
+#include "k3baudiozerodata.h"
+
+#include <k3bmsf.h>
+
+#include <kiconloader.h>
+
+
+K3bAudioDataSourceViewItem::K3bAudioDataSourceViewItem( K3bAudioTrackViewItem* parent,
+ K3bAudioDataSourceViewItem* after,
+ K3bAudioDataSource* source )
+ : K3bListViewItem( parent, after ),
+ m_trackViewItem( parent ),
+ m_source( source ),
+ m_animationCounter(1)
+{
+ // italic type
+ QFont f(listView()->font());
+ f.setItalic( true );
+ setFont( 3, f );
+
+ // setMarginVertical( 2 );
+
+ // gray out filename
+ setForegroundColor( 5, listView()->palette().disabled().foreground() );
+
+ // smaller filename
+ f = listView()->font();
+ f.setPointSize( f.pointSize() - 2 );
+ setFont( 5, f );
+
+ // for zero items we make the length editable
+ if( dynamic_cast<K3bAudioZeroData*>( source ) )
+ setEditor( 4, MSF );
+}
+
+
+QString K3bAudioDataSourceViewItem::text( int i ) const
+{
+ switch( i ) {
+ case 3:
+ return m_source->type();
+ case 4:
+ return m_source->length().toString();
+ case 5:
+ return m_source->sourceComment();
+ default:
+ return QString::null;
+ }
+}
+
+
+void K3bAudioDataSourceViewItem::setText( int col, const QString& text )
+{
+ //
+ // See K3bAudioTrackViewItem::setText for an explanation why we have to check if
+ // the value really changed
+ //
+ if( col == 4 ) {
+ if( K3bAudioZeroData* zero = dynamic_cast<K3bAudioZeroData*>( source() ) ) {
+ bool ok;
+ K3b::Msf f = K3b::Msf::fromString( text, &ok );
+ if( ok && f != zero->length() )
+ zero->setLength( f );
+ }
+ }
+ else
+ KListViewItem::setText( col, text );
+}
+
+
+bool K3bAudioDataSourceViewItem::animate()
+{
+ if( source()->length() == 0 && source()->isValid() ) {
+ QString icon = QString( "kde%1" ).arg( m_animationCounter );
+ setPixmap( 4, SmallIcon( icon ) );
+ m_animationCounter++;
+ if ( m_animationCounter > 6 )
+ m_animationCounter = 1;
+ return true;
+ }
+ else {
+ // set status icon
+ setPixmap( 4, ( source()->isValid() ? SmallIcon( "greenled" ) : SmallIcon( "redled" ) ) );
+ return false;
+ }
+}
+
+
+void K3bAudioDataSourceViewItem::setSelected( bool s )
+{
+ if( s || !m_trackViewItem->isSelected() )
+ K3bListViewItem::setSelected(s);
+}
diff --git a/src/projects/k3baudiodatasourceviewitem.h b/src/projects/k3baudiodatasourceviewitem.h
new file mode 100644
index 0000000..14da1de
--- /dev/null
+++ b/src/projects/k3baudiodatasourceviewitem.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * $Id: k3baudiodatasourceviewitem.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_DATA_SOURCE_VIEWITEM_H_
+#define _K3B_AUDIO_DATA_SOURCE_VIEWITEM_H_
+
+#include <k3blistview.h>
+
+class K3bAudioTrack;
+class K3bAudioDataSource;
+class K3bAudioTrackViewItem;
+
+class K3bAudioDataSourceViewItem : public K3bListViewItem
+{
+ public:
+ K3bAudioDataSourceViewItem( K3bAudioTrackViewItem* parent,
+ K3bAudioDataSourceViewItem* after,
+ K3bAudioDataSource* );
+
+ K3bAudioDataSource* source() const { return m_source; }
+ K3bAudioTrackViewItem* trackViewItem() const { return m_trackViewItem; }
+
+ QString text( int i ) const;
+ void setText( int col, const QString& text );
+
+ bool animate();
+
+ void setSelected( bool s );
+
+ /**
+ * Does nothing becasue we don't want no branches here.
+ */
+ void paintBranches( QPainter*, const QColorGroup &,
+ int, int, int ) {}
+
+ private:
+ K3bAudioTrackViewItem* m_trackViewItem;
+ K3bAudioDataSource* m_source;
+ int m_animationCounter;
+};
+
+#endif
diff --git a/src/projects/k3baudioeditorwidget.cpp b/src/projects/k3baudioeditorwidget.cpp
new file mode 100644
index 0000000..453f76f
--- /dev/null
+++ b/src/projects/k3baudioeditorwidget.cpp
@@ -0,0 +1,877 @@
+/*
+ *
+ * $Id: k3baudioeditorwidget.cpp 630444 2007-02-05 12:43:19Z trueg $
+ * Copyright (C) 2004-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudioeditorwidget.h"
+
+#include <qpainter.h>
+#include <qcolor.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qtooltip.h>
+
+
+
+class K3bAudioEditorWidget::Range
+{
+public:
+ Range( int i,
+ const K3b::Msf& s,
+ const K3b::Msf& e,
+ bool sf,
+ bool ef,
+ const QString& t,
+ const QBrush& b )
+ : id(i),
+ start(s),
+ end(e),
+ startFixed(sf),
+ endFixed(ef),
+ brush(b),
+ toolTip(t) {
+ }
+
+ int id;
+ K3b::Msf start;
+ K3b::Msf end;
+ bool startFixed;
+ bool endFixed;
+ QBrush brush;
+ QString toolTip;
+
+ bool operator<( const K3bAudioEditorWidget::Range& r ) {
+ return start < r.start;
+ }
+ bool operator>( const K3bAudioEditorWidget::Range& r ) {
+ return start > r.start;
+ }
+ bool operator==( const K3bAudioEditorWidget::Range& r ) {
+ return start == r.start;
+ }
+};
+
+
+class K3bAudioEditorWidget::Marker
+{
+public:
+ Marker( int i,
+ const K3b::Msf& msf,
+ bool f,
+ const QColor& c,
+ const QString& t )
+ : id(i),
+ pos(msf),
+ fixed(f),
+ color(c),
+ toolTip(t) {
+ }
+
+ int id;
+ K3b::Msf pos;
+ bool fixed;
+ QColor color;
+ QString toolTip;
+
+ operator K3b::Msf& () { return pos; }
+};
+
+
+class K3bAudioEditorWidget::RangeList : public QPtrList<K3bAudioEditorWidget::Range>
+{
+public:
+ RangeList()
+ : QPtrList<Range>() {
+ }
+
+ RangeList( const RangeList& l )
+ : QPtrList<Range>( l ) {
+ }
+
+ int compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 ) {
+ if( *static_cast<Range*>(item1) > *static_cast<Range*>(item2) )
+ return 1;
+ else if( *static_cast<Range*>(item1) < *static_cast<Range*>(item2) )
+ return -1;
+ else
+ return 0;
+ }
+};
+
+class K3bAudioEditorWidget::ToolTip : public QToolTip
+{
+public:
+ ToolTip( K3bAudioEditorWidget* w )
+ : QToolTip( w ),
+ m_editorWidget( w ) {
+ }
+
+protected:
+ void maybeTip( const QPoint& p ) {
+ QRect r = m_editorWidget->contentsRect();
+ Marker* m = m_editorWidget->findMarker( p );
+ if( m ) {
+ r.setLeft( p.x() - 1 );
+ r.setRight( p.x() + 1 );
+ tip( r, m->toolTip.isEmpty() ? m->pos.toString() : QString("%1 (%2)").arg(m->toolTip).arg(m->pos.toString()) );
+ }
+ else {
+ Range* range = m_editorWidget->findRange( p );
+ if( range ) {
+ r.setLeft( m_editorWidget->msfToPos( range->start ) );
+ r.setRight( m_editorWidget->msfToPos( range->end ) );
+ tip( r,
+ range->toolTip.isEmpty()
+ ? QString("%1 - %2").arg(range->start.toString()).arg(range->end.toString())
+ : QString("%1 (%2 - %3)").arg(range->toolTip).arg(range->start.toString()).arg(range->end.toString()) );
+ }
+ }
+ }
+
+private:
+ K3bAudioEditorWidget* m_editorWidget;
+};
+
+
+class K3bAudioEditorWidget::Private
+{
+public:
+ Private()
+ : allowOverlappingRanges(true),
+ rangeSelectionEnabled(false),
+ selectedRange(0),
+ movedRange(0) {
+ }
+
+ QBrush selectedRangeBrush;
+
+ bool allowOverlappingRanges;
+ bool rangeSelectionEnabled;
+
+ Range* selectedRange;
+ Range* movedRange;
+ K3b::Msf lastMovePosition;
+
+ RangeList ranges;
+};
+
+
+K3bAudioEditorWidget::K3bAudioEditorWidget( QWidget* parent, const char* name )
+ : QFrame( parent, name, Qt::WNoAutoErase ),
+ m_maxMarkers(1),
+ m_idCnt(1),
+ m_mouseAt(true),
+ m_draggedRange(0),
+ m_draggedMarker(0)
+{
+ d = new Private;
+ d->selectedRangeBrush = colorGroup().highlight();
+
+ setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
+ setFrameStyle( StyledPanel|Sunken );
+ setMouseTracking(true);
+ setCursor( Qt::PointingHandCursor );
+
+ m_margin = 5;
+
+ m_toolTip = new ToolTip( this );
+}
+
+
+K3bAudioEditorWidget::~K3bAudioEditorWidget()
+{
+ d->ranges.setAutoDelete(true);
+ m_markers.setAutoDelete(true);
+ d->ranges.clear();
+ m_markers.clear();
+
+ delete d;
+}
+
+
+QSize K3bAudioEditorWidget::minimumSizeHint() const
+{
+ constPolish();
+ // some fixed height minimum and enough space for a tickmark every minute
+ // But never exceed 2/3 of the the screen width, otherwise it just looks ugly
+ // FIXME: this is still bad for long sources and there might be 60 minutes sources!
+
+ int maxWidth = QApplication::desktop()->width()*2/3;
+ int wantedWidth = 2*m_margin + 2*frameWidth() + (m_length.totalFrames()/75/60 + 1) * fontMetrics().width( "000" );
+ return QSize( QMIN( maxWidth, wantedWidth ),
+ 2*m_margin + 12 + 6 /*12 for the tickmarks and 6 for the markers */ + fontMetrics().height() + 2*frameWidth() );
+}
+
+
+QSize K3bAudioEditorWidget::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+
+void K3bAudioEditorWidget::setLength( const K3b::Msf& length )
+{
+ m_length = length;
+ // TODO: remove markers beyond length
+ // TODO: shorten ranges if nesseccary
+ update();
+}
+
+
+const K3b::Msf K3bAudioEditorWidget::length() const
+{
+ return m_length;
+}
+
+
+void K3bAudioEditorWidget::setSelectedRangeBrush( const QBrush& b )
+{
+ d->selectedRangeBrush = b;
+}
+
+
+const QBrush& K3bAudioEditorWidget::selectedRangeBrush() const
+{
+ return d->selectedRangeBrush;
+}
+
+
+void K3bAudioEditorWidget::setAllowOverlappingRanges( bool b )
+{
+ d->allowOverlappingRanges = b;
+}
+
+
+bool K3bAudioEditorWidget::allowOverlappingRanges() const
+{
+ return d->allowOverlappingRanges;
+}
+
+
+void K3bAudioEditorWidget::enableRangeSelection( bool b )
+{
+ d->rangeSelectionEnabled = b;
+ repaint( false );
+}
+
+
+bool K3bAudioEditorWidget::rangeSelectedEnabled() const
+{
+ return d->selectedRange;
+}
+
+
+void K3bAudioEditorWidget::setSelectedRange( int id )
+{
+ setSelectedRange( getRange( id ) );
+}
+
+
+void K3bAudioEditorWidget::setSelectedRange( K3bAudioEditorWidget::Range* r )
+{
+ d->selectedRange = r;
+ if( rangeSelectedEnabled() ) {
+ repaint( false );
+ emit selectedRangeChanged( d->selectedRange ? d->selectedRange->id : 0 );
+ }
+}
+
+
+int K3bAudioEditorWidget::selectedRange() const
+{
+ if( d->selectedRange )
+ return d->selectedRange->id;
+ else
+ return 0;
+}
+
+
+int K3bAudioEditorWidget::addRange( const K3b::Msf& start, const K3b::Msf& end,
+ bool startFixed, bool endFixed,
+ const QString& toolTip,
+ const QBrush& brush )
+{
+ if( start > end || end > m_length-1 )
+ return -1;
+
+ Range* r = new Range( m_idCnt++, start, end, startFixed, endFixed, toolTip,
+ brush.style() != QBrush::NoBrush ? brush : QBrush(colorGroup().background()) );
+ d->ranges.inSort( r );
+
+ // only update the changed range
+ QRect rect = contentsRect();
+ rect.setLeft( msfToPos( start ) );
+ rect.setRight( msfToPos( end ) );
+ update( rect );
+
+ return r->id;
+}
+
+
+int K3bAudioEditorWidget::findRange( int pos ) const
+{
+ Range* r = findRange( QPoint( pos, 0 ) );
+ if( r )
+ return r->id;
+ else
+ return 0;
+}
+
+
+int K3bAudioEditorWidget::findRangeEdge( int pos, bool* end ) const
+{
+ Range* r = findRangeEdge( QPoint( pos, 0 ), end );
+ if( r )
+ return r->id;
+ else
+ return 0;
+}
+
+
+bool K3bAudioEditorWidget::modifyRange( int identifier, const K3b::Msf& start, const K3b::Msf& end )
+{
+ Range* range = getRange( identifier );
+ if( range ) {
+ if( start > end )
+ return false;
+
+ if( end > m_length )
+ return false;
+
+ range->start = start;
+ range->end = end;
+
+ if( !d->allowOverlappingRanges )
+ fixupOverlappingRanges( range );
+
+ repaint( false );
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+bool K3bAudioEditorWidget::removeRange( int identifier )
+{
+ if( Range* range = getRange( identifier ) ) {
+ d->ranges.removeRef( range );
+
+ emit rangeRemoved( identifier );
+
+ // repaint only the part of the range
+ QRect rect = contentsRect();
+ rect.setLeft( msfToPos( range->start ) );
+ rect.setRight( msfToPos( range->end ) );
+
+ if( d->selectedRange == range )
+ setSelectedRange( 0 );
+
+ delete range;
+
+ update( rect );
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+K3b::Msf K3bAudioEditorWidget::rangeStart( int identifier ) const
+{
+ if( Range* range = getRange( identifier ) )
+ return range->start;
+ else
+ return 0;
+}
+
+
+K3b::Msf K3bAudioEditorWidget::rangeEnd( int identifier ) const
+{
+ if( Range* range = getRange( identifier ) )
+ return range->end;
+ else
+ return 0;
+}
+
+
+QValueList<int> K3bAudioEditorWidget::allRanges() const
+{
+ QValueList<int> l;
+ d->ranges.sort();
+ for( QPtrListIterator<Range> it( d->ranges ); *it; ++it )
+ l.append( (*it)->id );
+ return l;
+}
+
+
+void K3bAudioEditorWidget::setMaxNumberOfMarkers( int i )
+{
+ m_maxMarkers = i;
+
+ // remove last markers
+ while( m_markers.count() > QMAX( 1, m_maxMarkers ) ) {
+ removeMarker( m_markers.getLast()->id );
+ }
+}
+
+
+int K3bAudioEditorWidget::addMarker( const K3b::Msf& pos, bool fixed, const QString& toolTip, const QColor& color )
+{
+ if( pos < m_length ) {
+ Marker* m = new Marker( m_idCnt++, pos, fixed, color.isValid() ? color : colorGroup().foreground(), toolTip );
+ m_markers.inSort( m );
+ return m->id;
+ }
+ else
+ return -1;
+}
+
+
+bool K3bAudioEditorWidget::removeMarker( int identifier )
+{
+ if( Marker* m = getMarker( identifier ) ) {
+ m_markers.removeRef( m );
+
+ emit markerRemoved( identifier );
+
+ // TODO: in case a marker is bigger than one pixel this needs to be changed
+ QRect rect = contentsRect();
+ rect.setLeft( msfToPos( m->pos ) );
+ rect.setRight( msfToPos( m->pos ) );
+ delete m;
+
+ update( rect );
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+bool K3bAudioEditorWidget::moveMarker( int identifier, const K3b::Msf& pos )
+{
+ if( pos < m_length )
+ if( Marker* m = getMarker( identifier ) ) {
+ QRect rect = contentsRect();
+ rect.setLeft( QMIN( msfToPos( pos ), msfToPos( m->pos ) ) );
+ rect.setRight( QMAX( msfToPos( pos ), msfToPos( m->pos ) ) );
+
+ m->pos = pos;
+
+ // TODO: in case a marker is bigger than one pixel this needs to be changed
+ update( rect );
+
+ return true;
+ }
+
+ return false;
+}
+
+
+void K3bAudioEditorWidget::drawContents( QPainter* p )
+{
+ // double buffering
+ QPixmap pix( contentsRect().size() );
+ pix.fill( colorGroup().base() );
+
+ QPainter pixP;
+ pixP.begin( &pix, this );
+
+ QRect drawRect( contentsRect() );
+ drawRect.setLeft( drawRect.left() + m_margin );
+ drawRect.setRight( drawRect.right() - m_margin );
+
+ // from minimumSizeHint()
+// int neededHeight = fontMetrics().height() + 12 + 6;
+
+// drawRect.setTop( drawRect.top() + (drawRect.height() - neededHeight)/2 );
+// drawRect.setHeight( neededHeight );
+
+ drawRect.setTop( drawRect.top() + m_margin );
+ drawRect.setBottom( drawRect.bottom() - m_margin );
+
+ drawAll( &pixP, drawRect );
+
+ pixP.end();
+
+ QRect rect = p->clipRegion().boundingRect();
+ QRect pixRect = rect;
+ pixRect.moveBy( -1*frameWidth(), -1*frameWidth() );
+ bitBlt( this, rect.topLeft(), &pix, pixRect );
+}
+
+
+void K3bAudioEditorWidget::drawAll( QPainter* p, const QRect& drawRect )
+{
+ // we simply draw the ranges one after the other.
+ for( QPtrListIterator<Range> it( d->ranges ); *it; ++it )
+ drawRange( p, drawRect, *it );
+
+ // Hack to make sure the currently selected range is always on top
+ if( d->selectedRange )
+ drawRange( p, drawRect, d->selectedRange );
+
+ for( QPtrListIterator<Marker> it( m_markers ); *it; ++it )
+ drawMarker( p, drawRect, *it );
+
+
+ // left vline
+ p->drawLine( drawRect.left(), drawRect.top(),
+ drawRect.left(), drawRect.bottom() );
+
+ // timeline
+ p->drawLine( drawRect.left(), drawRect.bottom(),
+ drawRect.right(), drawRect.bottom() );
+
+ // right vline
+ p->drawLine( drawRect.right(), drawRect.top(),
+ drawRect.right(), drawRect.bottom() );
+
+ // draw minute markers every minute
+ int minute = 1;
+ int minuteStep = 1;
+ int markerVPos = drawRect.bottom();
+ int maxMarkerWidth = fontMetrics().width( QString::number(m_length.minutes()) );
+ int minNeededSpace = maxMarkerWidth + 1;
+ int x = 0;
+ while( minute*60*75 < m_length ) {
+ int newX = msfToPos( minute*60*75 );
+
+ // only draw the mark if we have anough space
+ if( newX - x >= minNeededSpace ) {
+ p->drawLine( newX, markerVPos, newX, markerVPos-5 );
+ QRect txtRect( newX-(maxMarkerWidth/2),
+ markerVPos - 6 - fontMetrics().height(),
+ maxMarkerWidth,
+ fontMetrics().height() );
+ p->drawText( txtRect, Qt::AlignCenter, QString::number(minute) );
+
+ // FIXME: draw second markers if we have enough space
+
+ x = newX;
+ }
+ else {
+ minute -= minuteStep;
+ if( minuteStep == 1 )
+ minuteStep = 5;
+ else
+ minuteStep *= 2;
+ }
+
+ minute += minuteStep;
+ }
+}
+
+
+void K3bAudioEditorWidget::drawRange( QPainter* p, const QRect& drawRect, K3bAudioEditorWidget::Range* r )
+{
+ p->save();
+
+ int start = msfToPos( r->start );
+ int end = msfToPos( r->end );
+
+ if( rangeSelectedEnabled() && r == d->selectedRange )
+ p->fillRect( start, drawRect.top() + 6 , end-start+1, drawRect.height() - 6, selectedRangeBrush() );
+ else
+ p->fillRect( start, drawRect.top() + 6 , end-start+1, drawRect.height() - 6, r->brush );
+
+ p->drawRect( start, drawRect.top() + 6 , end-start+1, drawRect.height() - 6 );
+
+ p->restore();
+}
+
+
+void K3bAudioEditorWidget::drawMarker( QPainter* p, const QRect& drawRect, K3bAudioEditorWidget::Marker* m )
+{
+ p->save();
+
+ p->setPen( m->color );
+ p->setBrush( m->color );
+
+ int x = msfToPos( m->pos );
+ p->drawLine( x, drawRect.bottom(), x, drawRect.top() );
+
+ QPointArray points( 3 );
+ points.setPoint( 0, x, drawRect.top() + 6 );
+ points.setPoint( 1, x-3, drawRect.top() );
+ points.setPoint( 2, x+3, drawRect.top() );
+ p->drawPolygon( points );
+
+ p->restore();
+}
+
+
+void K3bAudioEditorWidget::fixupOverlappingRanges( Range* r )
+{
+ // copy the list to avoid problems with the iterator
+ RangeList ranges( d->ranges );
+ for( QPtrListIterator<Range> it( ranges ); *it; ++it ) {
+ Range* range = *it;
+ if( range != r ) {
+ // remove the range if it is covered completely
+ if( range->start >= r->start &&
+ range->end <= r->end ) {
+ d->ranges.removeRef( range );
+ emit rangeRemoved( range->id );
+ if( d->selectedRange == range )
+ setSelectedRange( 0 );
+ delete range;
+ }
+ // split the range if it contains r completely
+ else if( r->start >= range->start &&
+ r->end <= range->end ) {
+ // create a new range that spans the part after r
+ addRange( r->end+1, range->end,
+ range->startFixed, range->endFixed,
+ range->toolTip,
+ range->brush );
+
+ // modify the old range to only span the part before r
+ range->end = r->start-1;
+ emit rangeChanged( range->id, range->start, range->end );
+ }
+ else if( range->start >= r->start && range->start <= r->end ) {
+ range->start = r->end+1;
+ emit rangeChanged( range->id, range->start, range->end );
+ }
+ else if( range->end >= r->start && range->end <= r->end ) {
+ range->end = r->start-1;
+ emit rangeChanged( range->id, range->start, range->end );
+ }
+ }
+ }
+}
+
+
+void K3bAudioEditorWidget::mousePressEvent( QMouseEvent* e )
+{
+ m_draggedRange = 0;
+ m_draggedMarker = 0;
+
+ bool end;
+ if( Range* r = findRangeEdge( e->pos(), &end ) ) {
+ m_draggedRange = r;
+ m_draggingRangeEnd = end;
+ setSelectedRange( r );
+ }
+ else {
+ Range* r = findRange( e->pos() );
+ d->movedRange = r;
+ d->lastMovePosition = posToMsf( e->pos().x() );
+ setSelectedRange( r );
+ m_draggedMarker = findMarker( e->pos() );
+ }
+
+ QFrame::mousePressEvent(e);
+}
+
+
+void K3bAudioEditorWidget::mouseReleaseEvent( QMouseEvent* e )
+{
+ if( !d->allowOverlappingRanges ) {
+ //
+ // modify and even delete ranges that we touched
+ //
+ if( m_draggedRange ) {
+ fixupOverlappingRanges( m_draggedRange );
+ repaint( false );
+ }
+ else if( d->movedRange ) {
+ fixupOverlappingRanges( d->movedRange );
+ repaint( false );
+ }
+ }
+
+ m_draggedRange = 0;
+ m_draggedMarker = 0;
+ d->movedRange = 0;
+
+ QFrame::mouseReleaseEvent(e);
+}
+
+
+void K3bAudioEditorWidget::mouseDoubleClickEvent( QMouseEvent* e )
+{
+ QFrame::mouseDoubleClickEvent(e);
+}
+
+
+void K3bAudioEditorWidget::mouseMoveEvent( QMouseEvent* e )
+{
+ if( m_mouseAt )
+ emit mouseAt( posToMsf( e->pos().x() ) );
+
+ if( e->state() & Qt::LeftButton ) {
+ if( m_draggedRange ) {
+ // determine the position the range's end was dragged to and its other end
+ K3b::Msf msfPos = QMAX( 0, QMIN( posToMsf( e->pos().x() ), m_length-1 ) );
+ K3b::Msf otherEnd = ( m_draggingRangeEnd ? m_draggedRange->start : m_draggedRange->end );
+
+ // move it to the new pos
+ if( m_draggingRangeEnd )
+ m_draggedRange->end = msfPos;
+ else
+ m_draggedRange->start = msfPos;
+
+ // if we pass the other end switch them
+ if( m_draggedRange->start > m_draggedRange->end ) {
+ K3b::Msf buf = m_draggedRange->start;
+ m_draggedRange->start = m_draggedRange->end;
+ m_draggedRange->end = buf;
+ m_draggingRangeEnd = !m_draggingRangeEnd;
+ }
+
+ emit rangeChanged( m_draggedRange->id, m_draggedRange->start, m_draggedRange->end );
+
+ repaint( false );
+ }
+ else if( m_draggedMarker ) {
+ m_draggedMarker->pos = posToMsf( e->pos().x() );
+ emit markerMoved( m_draggedMarker->id, m_draggedMarker->pos );
+
+ repaint( false );
+ }
+ else if( d->movedRange ) {
+ int diff = posToMsf( e->pos().x() ).lba() - d->lastMovePosition.lba();
+ if( d->movedRange->end + diff >= m_length )
+ diff = m_length.lba() - d->movedRange->end.lba() - 1;
+ else if( d->movedRange->start - diff < 0 )
+ diff = -1 * d->movedRange->start.lba();
+ d->movedRange->start += diff;
+ d->movedRange->end += diff;
+
+// if( !d->allowOverlappingRanges )
+// fixupOverlappingRanges( d->movedRange );
+
+ d->lastMovePosition = posToMsf( e->pos().x() );
+
+ emit rangeChanged( d->movedRange->id, d->movedRange->start, d->movedRange->end );
+
+ repaint( false );
+ }
+ }
+ else if( findRangeEdge( e->pos() ) || findMarker( e->pos() ) )
+ setCursor( Qt::SizeHorCursor );
+ else
+ setCursor( Qt::PointingHandCursor );
+
+ QFrame::mouseMoveEvent(e);
+}
+
+
+K3bAudioEditorWidget::Range* K3bAudioEditorWidget::getRange( int i ) const
+{
+ for( QPtrListIterator<Range> it( d->ranges ); *it; ++it )
+ if( (*it)->id == i )
+ return *it;
+
+ return 0;
+}
+
+
+K3bAudioEditorWidget::Range* K3bAudioEditorWidget::findRange( const QPoint& p ) const
+{
+ // TODO: binary search; maybe store start and end positions in sorted lists for quick searching
+ // this might be a stupid approach but we do not have many ranges anyway
+ for( QPtrListIterator<Range> it( d->ranges ); *it; ++it ) {
+ Range* range = *it;
+ int start = msfToPos( range->start );
+ int end = msfToPos( range->end );
+
+ if( p.x() >= start && p.x() <= end ) {
+ return range;
+ }
+ }
+ return 0;
+}
+
+
+K3bAudioEditorWidget::Range* K3bAudioEditorWidget::findRangeEdge( const QPoint& p, bool* isEnd ) const
+{
+ // TODO: binary search
+ // this might be a stupid approach but we do not have many ranges anyway
+ for( QPtrListIterator<Range> it( d->ranges ); *it; ++it ) {
+ Range* range = *it;
+ int start = msfToPos( range->start );
+ int end = msfToPos( range->end );
+
+ //
+ // In case two ranges meet at one point moving the mouse cursor deeper into one
+ // range allows for grabbing that end
+ //
+
+ if( p.x() - 3 <= start && p.x() >= start && !range->startFixed ) {
+ if( isEnd )
+ *isEnd = false;
+ return range;
+ }
+ else if( p.x() <= end && p.x() + 3 >= end && !range->endFixed ) {
+ if( isEnd )
+ *isEnd = true;
+ return range;
+ }
+ }
+ return 0;
+}
+
+
+K3bAudioEditorWidget::Marker* K3bAudioEditorWidget::getMarker( int i ) const
+{
+ for( QPtrListIterator<Marker> it( m_markers ); *it; ++it )
+ if( (*it)->id == i )
+ return *it;
+
+ return 0;
+}
+
+
+K3bAudioEditorWidget::Marker* K3bAudioEditorWidget::findMarker( const QPoint& p ) const
+{
+ // TODO: binary search
+ for( QPtrListIterator<Marker> it( m_markers ); *it; ++it ) {
+ Marker* marker = *it;
+ int start = msfToPos( marker->pos );
+
+ if( p.x() - 1 <= start && p.x() + 1 >= start && !marker->fixed )
+ return marker;
+ }
+
+ return 0;
+}
+
+
+// p is in widget coordinates
+K3b::Msf K3bAudioEditorWidget::posToMsf( int p ) const
+{
+ int w = contentsRect().width() - 2*m_margin;
+ int x = QMIN( p-frameWidth()-m_margin, w );
+ return ( (int)((double)(m_length.lba()-1) / (double)w * (double)x) );
+}
+
+
+// returns widget coordinates
+int K3bAudioEditorWidget::msfToPos( const K3b::Msf& msf ) const
+{
+ int w = contentsRect().width() - 2*m_margin;
+ int pos = (int)((double)w / (double)(m_length.lba()-1) * (double)msf.lba());
+ return frameWidth() + m_margin + QMIN( pos, w-1 );
+}
+
+
+#include "k3baudioeditorwidget.moc"
diff --git a/src/projects/k3baudioeditorwidget.h b/src/projects/k3baudioeditorwidget.h
new file mode 100644
index 0000000..6e939d7
--- /dev/null
+++ b/src/projects/k3baudioeditorwidget.h
@@ -0,0 +1,220 @@
+/*
+ *
+ * $Id: k3baudioeditorwidget.h 620140 2007-01-05 12:02:29Z trueg $
+ * Copyright (C) 2004-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_EDITOR_WIDGET_H_
+#define _K3B_AUDIO_EDITOR_WIDGET_H_
+
+#include <qframe.h>
+#include <qptrlist.h>
+
+#include <k3bmsf.h>
+
+
+class QPainter;
+
+
+class K3bAudioEditorWidget : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioEditorWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioEditorWidget();
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ /**
+ * For now the Editor has only one parameter: the length data.
+ */
+ void setLength( const K3b::Msf& length );
+
+ const K3b::Msf length() const;
+
+ /**
+ * Add a user editable range.
+ * @param startFixed if true the range's start cannot be changed by the user, only with modifyRange
+ * @param endFixed if true the range's end cannot be changed by the user, only with modifyRange
+ * @param brush if not specified or it has the NoBrush style one is chosen automatically.
+ *
+ * @return -1 on error or an identifier on success (be aware that the highest value for end is length-1)
+ */
+ int addRange( const K3b::Msf& start, const K3b::Msf& end,
+ bool startFixed = false, bool endFixed = false,
+ const QString& toolTip = QString::null,
+ const QBrush& brush = QBrush() );
+
+ /**
+ * \returns the identifier of the range which spans over x position \a pos or
+ * 0 if no range is defined in this region.
+ */
+ int findRange( int pos ) const;
+
+ /**
+ * Searches for a range edge at x position \a pos.
+ * \return The ranges identifier if an edge could be found or 0 if there is no
+ * range edge at the position.
+ */
+ int findRangeEdge( int pos, bool* end = 0 ) const;
+
+ /**
+ * @returns false if the range does not exist or end was bigger than start.
+ */
+ bool modifyRange( int identifier, const K3b::Msf& start, const K3b::Msf& end );
+
+ /**
+ * @returns false if the range does not exist.
+ */
+ bool removeRange( int identifier );
+
+ K3b::Msf rangeStart( int identifier ) const;
+ K3b::Msf rangeEnd( int identifier ) const;
+
+ /**
+ * \return A list of all ranges' identifiers sorted ascending by start
+ * offset
+ */
+ QValueList<int> allRanges() const;
+
+ void setMaxNumberOfMarkers( int );
+
+ /**
+ * @param fixed if true the marker cannot be changed by the user, only with moveMarker
+ * @return -1 on error or an identifier on success.
+ */
+ int addMarker( const K3b::Msf& pos, bool fixed = false,
+ const QString& toolTip = QString::null, const QColor& color = QColor() );
+
+ /**
+ * @return false if the marker does not exist.
+ */
+ bool removeMarker( int identifier );
+
+ /**
+ * @return false if the marker does not exist.
+ */
+ bool moveMarker( int identifier, const K3b::Msf& );
+
+ void enableMouseAtSignal( bool b ) { m_mouseAt = b; }
+
+ /**
+ * By default ranges can overlap. If overlapping ranges are not allowed
+ * the editor widget will modify and delete ranges accordingly.
+ *
+ * Caution: So far setting this will not check if ranges already overlap.
+ */
+ void setAllowOverlappingRanges( bool b );
+
+ /**
+ * Range selection is by default disabled. If it is enabled the editor visually
+ * highlights the last clicked range.
+ *
+ * \sa setSelectedRange
+ */
+ void enableRangeSelection( bool b );
+
+ bool allowOverlappingRanges() const;
+ bool rangeSelectedEnabled() const;
+
+ void setSelectedRange( int id );
+
+ /**
+ * \return The identifier of the currently selected range or 0
+ * if none is selected.
+ */
+ int selectedRange() const;
+
+ K3b::Msf posToMsf( int x ) const;
+ int msfToPos( const K3b::Msf& msf ) const;
+
+ /**
+ * Set the brush to paint the selected range. Default is QColorGroup::Highlight
+ */
+ void setSelectedRangeBrush( const QBrush& );
+ const QBrush& selectedRangeBrush() const;
+
+ signals:
+ /**
+ * Emitted when enabled.
+ */
+ void mouseAt( const K3b::Msf& );
+
+ /**
+ * Emitted when the user changed a range.
+ * This signal is not emitted when a range is changed via modifyRange.
+ */
+ void rangeChanged( int identifier, const K3b::Msf& start, const K3b::Msf& end );
+ void rangeRemoved( int );
+
+ void selectedRangeChanged( int );
+
+ /**
+ * Emitted when the user moves a marker.
+ * This signal is not emitted when a marker is changed via moveMarker.
+ */
+ void markerMoved( int identifier, const K3b::Msf& pos );
+ void markerAdded( int identifier, const K3b::Msf& pos );
+ void markerRemoved( int identifier );
+
+ private:
+ class Range;
+ class RangeList;
+ class Marker;
+ class ToolTip;
+
+ class Private;
+ Private* d;
+
+ void mousePressEvent( QMouseEvent* e );
+ void mouseReleaseEvent( QMouseEvent* e );
+ void mouseDoubleClickEvent( QMouseEvent* e );
+ void mouseMoveEvent( QMouseEvent* e );
+ void drawContents( QPainter* );
+ void drawAll( QPainter*, const QRect& );
+ void drawRange( QPainter* p, const QRect&, Range* r );
+ void drawMarker( QPainter* p, const QRect&, Marker* m );
+
+ /**
+ * Makes sure that \a r does not overlap any other range by modifying and
+ * deleting other ranges.
+ */
+ void fixupOverlappingRanges( Range* r );
+
+ Range* getRange( int i ) const;
+ Marker* getMarker( int i ) const;
+ Range* findRange( const QPoint& p ) const;
+ Range* findRangeEdge( const QPoint& p, bool* end = 0 ) const;
+ Marker* findMarker( const QPoint& p ) const;
+ void setSelectedRange( Range* );
+
+ int m_maxMarkers;
+ K3b::Msf m_length;
+ QPtrList<Marker> m_markers;
+ int m_idCnt;
+ bool m_mouseAt;
+
+ /**
+ * Margin around the timethingy
+ */
+ int m_margin;
+
+ Range* m_draggedRange;
+ bool m_draggingRangeEnd;
+ Marker* m_draggedMarker;
+
+ ToolTip* m_toolTip;
+};
+
+#endif
diff --git a/src/projects/k3baudiotrackaddingdialog.cpp b/src/projects/k3baudiotrackaddingdialog.cpp
new file mode 100644
index 0000000..dfbcbb9
--- /dev/null
+++ b/src/projects/k3baudiotrackaddingdialog.cpp
@@ -0,0 +1,302 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiotrackaddingdialog.h"
+
+#include <k3baudiodoc.h>
+#include <k3baudiotrack.h>
+#include <k3baudiofile.h>
+#include <k3baudiodecoder.h>
+#include <k3bbusywidget.h>
+#include <k3bglobals.h>
+#include <k3bthread.h>
+#include <k3bthreadjob.h>
+#include <k3bcuefileparser.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qfileinfo.h>
+#include <qtimer.h>
+#include <qdir.h>
+
+
+class K3bAudioTrackAddingDialog::AnalyserThread : public K3bThread
+{
+public:
+ AnalyserThread()
+ : K3bThread(),
+ m_decoder(0) {
+ }
+
+ void run() {
+ emitStarted();
+ m_decoder->analyseFile();
+ emitFinished( m_decoder->isValid() );
+ }
+
+ K3bAudioDecoder* m_decoder;
+};
+
+
+K3bAudioTrackAddingDialog::K3bAudioTrackAddingDialog( QWidget* parent, const char* name )
+ : KDialogBase( Plain,
+ i18n("Please be patient..."),
+ Cancel,
+ Cancel,
+ parent,
+ name,
+ true,
+ true ),
+ m_bCanceled(false)
+{
+ QWidget* page = plainPage();
+ QGridLayout* grid = new QGridLayout( page );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( marginHint() );
+
+ m_infoLabel = new QLabel( page );
+ m_busyWidget = new K3bBusyWidget( page );
+
+ grid->addWidget( m_infoLabel, 0, 0 );
+ grid->addWidget( m_busyWidget, 1, 0 );
+
+ m_analyserThread = new AnalyserThread();
+ m_analyserJob = new K3bThreadJob( m_analyserThread, this, this );
+ connect( m_analyserJob, SIGNAL(finished(bool)), this, SLOT(slotAnalysingFinished(bool)) );
+}
+
+
+K3bAudioTrackAddingDialog::~K3bAudioTrackAddingDialog()
+{
+ delete m_analyserThread;
+}
+
+
+int K3bAudioTrackAddingDialog::addUrls( const KURL::List& urls,
+ K3bAudioDoc* doc,
+ K3bAudioTrack* afterTrack,
+ K3bAudioTrack* parentTrack,
+ K3bAudioDataSource* afterSource,
+ QWidget* parent )
+{
+ if( urls.isEmpty() )
+ return 0;
+
+ K3bAudioTrackAddingDialog dlg( parent );
+ dlg.m_urls = extractUrlList( urls );
+ dlg.m_doc = doc;
+ dlg.m_trackAfter = afterTrack;
+ dlg.m_parentTrack = parentTrack;
+ dlg.m_sourceAfter = afterSource;
+ dlg.m_infoLabel->setText( i18n("Adding files to project \"%1\"...").arg(doc->URL().fileName()) );
+
+ dlg.m_busyWidget->showBusy(true);
+ QTimer::singleShot( 0, &dlg, SLOT(slotAddUrls()) );
+ int ret = dlg.exec();
+
+ QString message;
+ if( !dlg.m_unreadableFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("Insufficient permissions to read the following files") )
+ .arg( dlg.m_unreadableFiles.join( "<br>" ) );
+ if( !dlg.m_notFoundFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("Unable to find the following files") )
+ .arg( dlg.m_notFoundFiles.join( "<br>" ) );
+ if( !dlg.m_nonLocalFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("No non-local files supported") )
+ .arg( dlg.m_unreadableFiles.join( "<br>" ) );
+ if( !dlg.m_unsupportedFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br><i>%2</i><br>%3")
+ .arg( i18n("Unable to handle the following files due to an unsupported format" ) )
+ .arg( i18n("You may manually convert these audio files to wave using another "
+ "application supporting the audio format and then add the wave files "
+ "to the K3b project.") )
+ .arg( dlg.m_unsupportedFiles.join( "<br>" ) );
+
+ if( !message.isEmpty() )
+ KMessageBox::detailedSorry( parent, i18n("Problems while adding files to the project."), message );
+
+ return ret;
+}
+
+
+
+void K3bAudioTrackAddingDialog::slotAddUrls()
+{
+ if( m_bCanceled )
+ return;
+
+ if( m_urls.isEmpty() ) {
+ accept();
+ return;
+ }
+
+ KURL url = m_urls.first();
+ bool valid = true;
+
+ if( url.path().right(3).lower() == "cue" ) {
+ // see if its a cue file
+ K3bCueFileParser parser( url.path() );
+ if( parser.isValid() && parser.toc().contentType() == K3bDevice::AUDIO ) {
+ // remember cue url and set the new audio file url
+ m_cueUrl = url;
+ url = m_urls[0] = KURL::fromPathOrURL( parser.imageFilename() );
+ }
+ }
+
+ m_infoLabel->setText( i18n("Analysing file '%1'...").arg( url.fileName() ) );
+
+ if( !url.isLocalFile() ) {
+ valid = false;
+ m_nonLocalFiles.append( url.path() );
+ }
+ else {
+ QFileInfo fi( url.path() );
+ if( !fi.exists() ) {
+ valid = false;
+ m_notFoundFiles.append( url.path() );
+ }
+ else if( !fi.isReadable() ) {
+ valid = false;
+ m_unreadableFiles.append( url.path() );
+ }
+ }
+
+ if( valid ) {
+ bool reused;
+ K3bAudioDecoder* dec = m_doc->getDecoderForUrl( url, &reused );
+ if( dec ) {
+ m_analyserThread->m_decoder = dec;
+ if( reused )
+ slotAnalysingFinished( true );
+ else
+ m_analyserJob->start();
+ }
+ else {
+ valid = false;
+ m_unsupportedFiles.append( url.path() );
+ }
+ }
+
+ // invalid file, next url
+ if( !valid ) {
+ m_urls.remove( m_urls.begin() );
+ QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
+ }
+}
+
+
+void K3bAudioTrackAddingDialog::slotAnalysingFinished( bool /*success*/ )
+{
+ if( m_bCanceled ) {
+ // We only started the analyser thread in case the decoder was new
+ // thus, we can safely delete it since no other source needs it.
+ delete m_analyserThread->m_decoder;
+ return;
+ }
+
+ KURL url = m_urls.first();
+ m_urls.remove( m_urls.begin() );
+
+ if( m_cueUrl.isValid() ) {
+ // import the cue file
+ m_doc->importCueFile( m_cueUrl.path(), m_trackAfter, m_analyserThread->m_decoder );
+ m_cueUrl = KURL();
+ }
+ else {
+ // create the track and source items
+ K3bAudioDecoder* dec = m_analyserThread->m_decoder;
+ K3bAudioFile* file = new K3bAudioFile( dec, m_doc );
+ if( m_parentTrack ) {
+ if( m_sourceAfter )
+ file->moveAfter( m_sourceAfter );
+ else
+ file->moveAhead( m_parentTrack->firstSource() );
+ m_sourceAfter = file;
+ }
+ else {
+ K3bAudioTrack* track = new K3bAudioTrack( m_doc );
+ track->setFirstSource( file );
+
+ track->setTitle( dec->metaInfo( K3bAudioDecoder::META_TITLE ) );
+ track->setArtist( dec->metaInfo( K3bAudioDecoder::META_ARTIST ) );
+ track->setSongwriter( dec->metaInfo( K3bAudioDecoder::META_SONGWRITER ) );
+ track->setComposer( dec->metaInfo( K3bAudioDecoder::META_COMPOSER ) );
+ track->setCdTextMessage( dec->metaInfo( K3bAudioDecoder::META_COMMENT ) );
+
+ if( m_trackAfter )
+ track->moveAfter( m_trackAfter );
+ else
+ track->moveAfter( m_doc->lastTrack() );
+
+ m_trackAfter = track;
+ }
+ }
+
+ QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
+}
+
+
+void K3bAudioTrackAddingDialog::slotCancel()
+{
+ m_bCanceled = true;
+ m_analyserJob->cancel();
+ KDialogBase::slotCancel();
+}
+
+
+KURL::List K3bAudioTrackAddingDialog::extractUrlList( const KURL::List& urls )
+{
+ KURL::List allUrls = urls;
+ KURL::List urlsFromPlaylist;
+ KURL::List::iterator it = allUrls.begin();
+ while( it != allUrls.end() ) {
+
+ const KURL& url = *it;
+ QFileInfo fi( url.path() );
+
+ if( fi.isDir() ) {
+ it = allUrls.remove( it );
+ // add all files in the dir
+ QDir dir(fi.filePath());
+ QStringList entries = dir.entryList( QDir::Files );
+ KURL::List::iterator oldIt = it;
+ // add all files into the list after the current item
+ for( QStringList::iterator dirIt = entries.begin();
+ dirIt != entries.end(); ++dirIt )
+ it = allUrls.insert( oldIt, KURL::fromPathOrURL( dir.absPath() + "/" + *dirIt ) );
+ }
+ else if( K3bAudioDoc::readPlaylistFile( url, urlsFromPlaylist ) ) {
+ it = allUrls.remove( it );
+ KURL::List::iterator oldIt = it;
+ // add all files into the list after the current item
+ for( KURL::List::iterator dirIt = urlsFromPlaylist.begin();
+ dirIt != urlsFromPlaylist.end(); ++dirIt )
+ it = allUrls.insert( oldIt, *dirIt );
+ }
+ else
+ ++it;
+ }
+
+ return allUrls;
+}
+
+#include "k3baudiotrackaddingdialog.moc"
diff --git a/src/projects/k3baudiotrackaddingdialog.h b/src/projects/k3baudiotrackaddingdialog.h
new file mode 100644
index 0000000..4590e95
--- /dev/null
+++ b/src/projects/k3baudiotrackaddingdialog.h
@@ -0,0 +1,106 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_TRACK_ADDING_DIALOG_H_
+#define _K3B_AUDIO_TRACK_ADDING_DIALOG_H_
+
+#include <k3bjobhandler.h>
+#include <kdialogbase.h>
+#include <kurl.h>
+#include <qstringlist.h>
+
+
+class K3bBusyWidget;
+class QLabel;
+class K3bAudioTrack;
+class K3bAudioDataSource;
+class K3bThreadJob;
+class K3bAudioDoc;
+
+
+class K3bAudioTrackAddingDialog : public KDialogBase, public K3bJobHandler
+{
+ Q_OBJECT
+
+ public:
+ ~K3bAudioTrackAddingDialog();
+
+ /**
+ * @reimplemented from K3bJobHandler
+ */
+ int waitForMedia( K3bDevice::Device*,
+ int = K3bDevice::STATE_EMPTY,
+ int = K3bDevice::MEDIA_WRITABLE_CD,
+ const QString& = QString::null ) { return 0; }
+
+ /**
+ * @reimplemented from K3bJobHandler
+ */
+ bool questionYesNo( const QString&,
+ const QString& = QString::null,
+ const QString& = QString::null,
+ const QString& = QString::null ) { return false; }
+
+ /**
+ * reimplemented from K3bJobHandler
+ */
+ void blockingInformation( const QString&,
+ const QString& = QString::null ) {}
+
+ /**
+ * \return \see QDialog::exec()
+ */
+ static int addUrls( const KURL::List& urls,
+ K3bAudioDoc* doc,
+ K3bAudioTrack* afterTrack = 0,
+ K3bAudioTrack* parentTrack = 0,
+ K3bAudioDataSource* afterSource = 0,
+ QWidget* parent = 0 );
+
+ private slots:
+ void slotAddUrls();
+ void slotAnalysingFinished( bool );
+ void slotCancel();
+
+ private:
+ K3bAudioTrackAddingDialog( QWidget* parent = 0, const char* name = 0 );
+
+ static KURL::List extractUrlList( const KURL::List& urls );
+
+ K3bBusyWidget* m_busyWidget;
+ QLabel* m_infoLabel;
+
+ QStringList m_unreadableFiles;
+ QStringList m_notFoundFiles;
+ QStringList m_nonLocalFiles;
+ QStringList m_unsupportedFiles;
+
+ KURL::List m_urls;
+
+ K3bAudioDoc* m_doc;
+ K3bAudioTrack* m_trackAfter;
+ K3bAudioTrack* m_parentTrack;
+ K3bAudioDataSource* m_sourceAfter;
+
+ KURL m_cueUrl;
+
+ bool m_bCanceled;
+
+ class AnalyserThread;
+ AnalyserThread* m_analyserThread;
+ K3bThreadJob* m_analyserJob;
+};
+
+#endif
diff --git a/src/projects/k3baudiotrackdialog.cpp b/src/projects/k3baudiotrackdialog.cpp
new file mode 100644
index 0000000..ecb7796
--- /dev/null
+++ b/src/projects/k3baudiotrackdialog.cpp
@@ -0,0 +1,113 @@
+/*
+ *
+ * $Id: k3baudiotrackdialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include <qtextedit.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qframe.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qhbox.h>
+#include <qwhatsthis.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kmimetype.h>
+#include <kurl.h>
+#include <kio/global.h>
+#include <klineedit.h>
+
+#include "k3baudiotrackdialog.h"
+#include "k3baudioeditorwidget.h"
+#include "k3baudiotrackwidget.h"
+#include "k3baudiotrack.h"
+#include <k3bvalidators.h>
+#include <kcutlabel.h>
+#include <k3bmsf.h>
+#include <k3bcdtextvalidator.h>
+#include <k3baudiodecoder.h>
+#include <k3bmsfedit.h>
+
+
+// TODO: three modes:
+// 1. Only one track with only one source
+// show decoder tech info, cdtext, options and the track editor without showing anything
+// about sources
+// 2. Only one track with multible sources
+// like the above but with the possiblity to edit the sources
+// 3. multible tracks
+// do only show cd-text and options (eventuelle index0)
+
+
+K3bAudioTrackDialog::K3bAudioTrackDialog( QPtrList<K3bAudioTrack>& tracks, QWidget *parent, const char *name )
+ : KDialogBase( KDialogBase::Plain, i18n("Audio Track Properties"),
+ KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::Apply,
+ KDialogBase::Ok, parent, name )
+{
+ m_tracks = tracks;
+
+ setupGui();
+ setupConnections();
+}
+
+K3bAudioTrackDialog::~K3bAudioTrackDialog()
+{
+}
+
+
+void K3bAudioTrackDialog::slotOk()
+{
+ slotApply();
+ done(0);
+}
+
+
+void K3bAudioTrackDialog::slotApply()
+{
+ m_audioTrackWidget->save();
+
+}
+
+
+void K3bAudioTrackDialog::setupGui()
+{
+ QFrame* frame = plainPage();
+
+ QGridLayout* mainLayout = new QGridLayout( frame );
+ mainLayout->setSpacing( spacingHint() );
+ mainLayout->setMargin( 0 );
+
+ m_audioTrackWidget = new K3bAudioTrackWidget( m_tracks, frame );
+ mainLayout->addWidget( m_audioTrackWidget, 0, 0 );
+}
+
+void K3bAudioTrackDialog::setupConnections()
+{
+}
+
+
+void K3bAudioTrackDialog::updateTrackLengthDisplay()
+{
+// K3b::Msf len = m_editTrackEnd->msfValue() - m_editTrackStart->msfValue();
+// m_displayLength->setText( len.toString() );
+// m_displaySize->setText( KIO::convertSize(len.audioBytes()) );
+}
+
+
+
+#include "k3baudiotrackdialog.moc"
diff --git a/src/projects/k3baudiotrackdialog.h b/src/projects/k3baudiotrackdialog.h
new file mode 100644
index 0000000..53edc1c
--- /dev/null
+++ b/src/projects/k3baudiotrackdialog.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * $Id: k3baudiotrackdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BAUDIOTRACKDIALOG_H
+#define K3BAUDIOTRACKDIALOG_H
+
+
+#include <kdialogbase.h>
+
+#include <k3bmsf.h>
+
+#include <qptrlist.h>
+
+class K3bAudioTrack;
+class K3bAudioTrackWidget;
+
+/**
+ *@author Sebastian Trueg
+ */
+
+class K3bAudioTrackDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioTrackDialog( QPtrList<K3bAudioTrack>&, QWidget *parent=0, const char *name=0);
+ ~K3bAudioTrackDialog();
+
+ protected slots:
+ void slotOk();
+ void slotApply();
+
+ void updateTrackLengthDisplay();
+
+ private:
+ QPtrList<K3bAudioTrack> m_tracks;
+
+ K3bAudioTrackWidget* m_audioTrackWidget;
+
+ void setupGui();
+ void setupConnections();
+};
+
+#endif
diff --git a/src/projects/k3baudiotrackplayer.cpp b/src/projects/k3baudiotrackplayer.cpp
new file mode 100644
index 0000000..cac2e7a
--- /dev/null
+++ b/src/projects/k3baudiotrackplayer.cpp
@@ -0,0 +1,365 @@
+/*
+ *
+ * $Id: k3baudiotrackplayer.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiotrackplayer.h"
+#include <k3baudiodoc.h>
+#include <k3baudiotrack.h>
+#include <k3baudioserver.h>
+
+#include <kactionclasses.h>
+#include <klocale.h>
+
+#include <qslider.h>
+#include <qtimer.h>
+#include <qmutex.h>
+#include <qtooltip.h>
+
+
+class K3bAudioTrackPlayer::Private
+{
+public:
+ KAction* actionPlay;
+ KAction* actionPause;
+ KAction* actionPlayPause;
+ KAction* actionStop;
+ KAction* actionNext;
+ KAction* actionPrev;
+ KAction* actionSeek;
+
+ // just to handle them easily;
+ KActionCollection* actionCollection;
+
+ QSlider* seekSlider;
+ QTimer sliderTimer;
+
+ // used to make sure that no seek and read operation occur in parallel
+ QMutex mutex;
+
+ bool playing;
+ bool paused;
+};
+
+
+K3bAudioTrackPlayer::K3bAudioTrackPlayer( K3bAudioDoc* doc, QObject* parent, const char* name )
+ : QObject( parent, name ),
+ K3bAudioClient(),
+ m_doc( doc ),
+ m_currentTrack( 0 )
+{
+ d = new Private;
+ d->paused = false;
+ d->playing = false;
+
+ // TODO: handle the shortcuts: pass a widget to the action collection (perhaps the trackview?)
+ d->actionCollection = new KActionCollection( 0, this );
+
+ // create the actions
+ // TODO: create shortcuts (is there a way to let the user change them?)
+ d->actionPlay = new KAction( i18n("Play"),
+ "player_play",
+ KShortcut(),
+ this, SLOT(playPause()),
+ d->actionCollection,
+ "play" );
+ d->actionPause = new KAction( i18n("Pause"),
+ "player_pause",
+ KShortcut(),
+ this, SLOT(playPause()),
+ d->actionCollection,
+ "pause" );
+ d->actionPlayPause = new KAction( i18n("Play/Pause"),
+ "player_play",
+ KShortcut(),
+ this, SLOT(playPause()),
+ d->actionCollection,
+ "play_pause" );
+
+ d->actionStop = new KAction( i18n("Stop"),
+ "player_stop",
+ KShortcut(),
+ this, SLOT(stop()),
+ d->actionCollection,
+ "stop" );
+ d->actionNext = new KAction( i18n("Next"),
+ "player_end",
+ KShortcut(),
+ this, SLOT(next()),
+ d->actionCollection,
+ "next" );
+ d->actionPrev = new KAction( i18n("Prev"),
+ "player_start",
+ KShortcut(),
+ this, SLOT(prev()),
+ d->actionCollection,
+ "prev" );
+
+ d->seekSlider = new QSlider( 0, 100, 1, 0, Qt::Horizontal, 0, "audiotrackplayerslider" );
+ connect( d->seekSlider, SIGNAL(sliderMoved(int)), this, SLOT(slotSeek(int)) );
+ // FIXME: maybe it's not such a good idea to use a KWidgetAction here since this way the player
+ // can only be used once in one widget. If the action would always create a new slider we could plug
+ // the action into several toolboxes and also use it in some resizing or track splitting dialogs.
+ d->actionSeek = new KWidgetAction( d->seekSlider,
+ i18n("Seek"),
+ KShortcut(),
+ 0,
+ 0,
+ d->actionCollection,
+ "seek" );
+ // this should be done in KWidgetAction but is not yet
+ connect( d->actionSeek, SIGNAL(enabled(bool)), d->seekSlider, SLOT(setEnabled(bool)) );
+
+ d->actionStop->setEnabled(false);
+ d->actionPause->setEnabled(false);
+ d->actionNext->setEnabled(false);
+ d->actionPrev->setEnabled(false);
+ d->actionSeek->setEnabled(false);
+
+ connect( m_doc, SIGNAL(changed()),
+ this, SLOT(slotDocChanged()) );
+ connect( m_doc, SIGNAL(trackChanged(K3bAudioTrack*)),
+ this, SLOT(slotTrackChanged(K3bAudioTrack*)) );
+ connect( m_doc, SIGNAL(trackRemoved(K3bAudioTrack*)),
+ this, SLOT(slotTrackRemoved(K3bAudioTrack*)) );
+ connect( &d->sliderTimer, SIGNAL(timeout()),
+ this, SLOT(slotUpdateSlider()) );
+
+ // we just stop the player if the audio server has an error. K3bMainWindow will show the error message
+ // This is all very hacky and has to be improved for K3b 2.0. But then we will probably use Phonon anyway...
+ connect( K3bAudioServer::instance(), SIGNAL(error(const QString&)), this, SLOT(stop()) );
+
+ // tooltips
+ d->actionPlay->setToolTip( i18n("Play") );
+ d->actionStop->setToolTip( i18n("Stop") );
+ d->actionPause->setToolTip( i18n("Pause") );
+ d->actionNext->setToolTip( i18n("Next") );
+ d->actionPrev->setToolTip( i18n("Previous") );
+}
+
+
+K3bAudioTrackPlayer::~K3bAudioTrackPlayer()
+{
+ stop();
+ delete d->seekSlider;
+ delete d;
+}
+
+
+KAction* K3bAudioTrackPlayer::action( int action ) const
+{
+ switch( action ) {
+ case ACTION_PLAY:
+ return d->actionPlay;
+ case ACTION_PAUSE:
+ return d->actionPause;
+ case ACTION_PLAY_PAUSE:
+ return d->actionPlayPause;
+ case ACTION_STOP:
+ return d->actionStop;
+ case ACTION_NEXT:
+ return d->actionNext;
+ case ACTION_PREV:
+ return d->actionPrev;
+ case ACTION_SEEK:
+ return d->actionSeek;
+ default:
+ return 0;
+ }
+}
+
+
+void K3bAudioTrackPlayer::playTrack( K3bAudioTrack* track )
+{
+ if( track ) {
+ // we show the currently playing track as a tooltip on the slider
+ QToolTip::remove( d->seekSlider );
+ QToolTip::add( d->seekSlider, i18n("Playing track %1: %2 - %3")
+ .arg(track->trackNumber())
+ .arg(track->artist())
+ .arg(track->title()) );
+ d->seekSlider->setMaxValue( track->length().totalFrames() );
+ m_currentTrack = track;
+ d->paused = true;
+
+ d->actionNext->setEnabled( m_currentTrack->next() != 0 );
+ d->actionPrev->setEnabled( m_currentTrack->prev() != 0 );
+
+ seek(0);
+ playPause();
+
+ emit playingTrack( track );
+ }
+}
+
+
+void K3bAudioTrackPlayer::playPause()
+{
+ if( !m_currentTrack ) {
+ playTrack( m_doc->firstTrack() );
+ }
+ else {
+ if( !d->playing ) {
+ seek( m_currentPosition );
+ d->playing = true;
+ d->actionPlayPause->setIcon( "player_pause" );
+ d->actionPause->setEnabled(true);
+ d->actionPlay->setEnabled(false);
+ d->actionSeek->setEnabled(true);
+ startStreaming();
+ d->sliderTimer.start(1000);
+ }
+ else if( d->paused ) {
+ d->paused = false;
+ d->actionPlayPause->setIcon( "player_pause" );
+ d->actionPause->setEnabled(true);
+ d->actionPlay->setEnabled(false);
+ startStreaming();
+ d->sliderTimer.start(1000);
+
+ emit paused( false );
+ }
+ else {
+ d->paused = true;
+ d->actionPlayPause->setIcon( "player_play" );
+ d->actionPause->setEnabled(false);
+ d->actionPlay->setEnabled(true);
+ stopStreaming();
+ d->sliderTimer.stop();
+
+ emit paused( true );
+ }
+
+ d->actionStop->setEnabled(true);
+ }
+}
+
+
+void K3bAudioTrackPlayer::stop()
+{
+ m_currentTrack = 0;
+ m_currentPosition = 0;
+ stopStreaming();
+ d->paused = false;
+ d->playing = false;
+ d->actionStop->setEnabled(false);
+ d->actionPause->setEnabled(false);
+ d->actionPlay->setEnabled(true);
+ d->actionSeek->setEnabled(false);
+ d->actionNext->setEnabled(false);
+ d->actionPrev->setEnabled(false);
+
+ d->actionPlayPause->setIcon( "player_play" );
+
+ emit stopped();
+}
+
+
+void K3bAudioTrackPlayer::next()
+{
+ if( m_currentTrack && m_currentTrack->next() ) {
+ playTrack( m_currentTrack->next() );
+ }
+}
+
+
+void K3bAudioTrackPlayer::prev()
+{
+ if( m_currentTrack && m_currentTrack->prev() ) {
+ playTrack( m_currentTrack->prev() );
+ }
+}
+
+
+void K3bAudioTrackPlayer::seek( const K3b::Msf& msf )
+{
+ if( m_currentTrack ) {
+ if( msf < m_currentTrack->length() ) {
+ d->mutex.lock();
+ m_currentTrack->seek( msf );
+ m_currentPosition = msf;
+ slotUpdateSlider();
+ d->mutex.unlock();
+ }
+ else
+ next();
+ }
+}
+
+
+void K3bAudioTrackPlayer::slotSeek( int frames )
+{
+ seek( K3b::Msf( frames ) );
+}
+
+
+int K3bAudioTrackPlayer::read( char* data, int maxlen )
+{
+ if( m_currentTrack ) {
+ d->mutex.lock();
+ int len = m_currentTrack->read( data, maxlen );
+ d->mutex.unlock();
+ if( len > 0 ) {
+ m_currentPosition += (int)( (double)len / 2352.0 + 0.5 );
+ }
+ else if( m_currentTrack->next() ) {
+ // play the next track
+ next();
+ return read( data, maxlen );
+ }
+ else {
+ stop();
+ return -1; // no more tracks
+ }
+
+ return len;
+ }
+ else
+ return -1;
+}
+
+
+void K3bAudioTrackPlayer::slotTrackRemoved( K3bAudioTrack* track )
+{
+ if( m_currentTrack == track ) {
+ stop();
+ m_currentTrack = 0;
+ }
+}
+
+
+void K3bAudioTrackPlayer::slotTrackChanged( K3bAudioTrack* track )
+{
+ if( m_currentTrack == track ) {
+ d->seekSlider->setMaxValue( track->length().totalFrames() );
+ }
+}
+
+
+void K3bAudioTrackPlayer::slotUpdateSlider()
+{
+ d->seekSlider->setValue( m_currentPosition.totalFrames() );
+}
+
+
+void K3bAudioTrackPlayer::slotDocChanged()
+{
+ // update the controls in case a new track has been added before or after
+ // the current one and it has been the first or last track
+ if( m_currentTrack ) {
+ d->actionNext->setEnabled( m_currentTrack->next() != 0 );
+ d->actionPrev->setEnabled( m_currentTrack->prev() != 0 );
+ }
+}
+
+#include "k3baudiotrackplayer.moc"
diff --git a/src/projects/k3baudiotrackplayer.h b/src/projects/k3baudiotrackplayer.h
new file mode 100644
index 0000000..92f4f0a
--- /dev/null
+++ b/src/projects/k3baudiotrackplayer.h
@@ -0,0 +1,87 @@
+/*
+ *
+ * $Id: k3baudiotrackplayer.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_TRACK_PLAYER_H_
+#define _K3B_AUDIO_TRACK_PLAYER_H_
+
+#include <qobject.h>
+
+#include <k3baudioclient.h>
+
+#include <k3bmsf.h>
+
+class K3bAudioDoc;
+class K3bAudioTrack;
+class KAction;
+
+
+class K3bAudioTrackPlayer : public QObject, public K3bAudioClient
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioTrackPlayer( K3bAudioDoc* doc, QObject* parent = 0, const char* name = 0 );
+ ~K3bAudioTrackPlayer();
+
+ K3bAudioTrack* currentPlayingTrack() const { return m_currentTrack; }
+ const K3b::Msf& currentPosition() const { return m_currentPosition; }
+
+ enum Actions {
+ ACTION_PLAY,
+ ACTION_PAUSE,
+ ACTION_PLAY_PAUSE,
+ ACTION_STOP,
+ ACTION_NEXT,
+ ACTION_PREV,
+ ACTION_SEEK
+ };
+
+ KAction* action( int action ) const;
+
+ /**
+ * Reimplemented from K3bAudioClient
+ */
+ int read( char* data, int maxlen );
+
+ public slots:
+ void playTrack( K3bAudioTrack* );
+ void playPause();
+ void stop();
+ void next();
+ void prev();
+ void seek( const K3b::Msf& );
+
+ signals:
+ void playingTrack( K3bAudioTrack* );
+ void paused( bool paused );
+ void stopped();
+
+ private slots:
+ void slotSeek( int );
+ void slotTrackChanged( K3bAudioTrack* track );
+ void slotTrackRemoved( K3bAudioTrack* track );
+ void slotUpdateSlider();
+ void slotDocChanged();
+
+ private:
+ K3bAudioDoc* m_doc;
+ K3bAudioTrack* m_currentTrack;
+ K3b::Msf m_currentPosition;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/projects/k3baudiotracksplitdialog.cpp b/src/projects/k3baudiotracksplitdialog.cpp
new file mode 100644
index 0000000..1acd370
--- /dev/null
+++ b/src/projects/k3baudiotracksplitdialog.cpp
@@ -0,0 +1,232 @@
+/*
+ *
+ * $Id: k3baudiotracksplitdialog.cpp 630444 2007-02-05 12:43:19Z trueg $
+ * Copyright (C) 2004-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiotracksplitdialog.h"
+#include "k3baudiotrack.h"
+#include "k3baudioeditorwidget.h"
+
+#include <k3bmsf.h>
+#include <k3bmsfedit.h>
+
+#include <klocale.h>
+#include <kactioncollection.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+
+#include <qlabel.h>
+#include <qframe.h>
+#include <qlayout.h>
+
+
+K3bAudioTrackSplitDialog::K3bAudioTrackSplitDialog( K3bAudioTrack* track, QWidget* parent, const char* name )
+ : KDialogBase( KDialogBase::Plain, i18n("Split Audio Track"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok, parent, name ),
+ m_track(track)
+{
+ QFrame* frame = plainPage();
+
+ m_editorWidget = new K3bAudioEditorWidget( frame );
+ m_msfEditStart = new K3bMsfEdit( frame );
+ m_msfEditEnd = new K3bMsfEdit( frame );
+
+ QGridLayout* layout = new QGridLayout( frame );
+ layout->setMargin( 0 );
+ layout->setSpacing( spacingHint() );
+
+ // FIXME: After the string freeze replace the text with a better one explaning how to use this dialog
+ layout->addMultiCellWidget( new QLabel( i18n("Please select the position where the track should be split."),
+ frame ), 0, 0, 0, 3 );
+ layout->addMultiCellWidget( m_editorWidget, 1, 1, 0, 3 );
+ layout->addWidget( m_msfEditStart, 2, 1 );
+ layout->addWidget( new QLabel( " - ", frame ), 2, 2 );
+ layout->addWidget( m_msfEditEnd, 2, 3 );
+ layout->addWidget( new QLabel( i18n("Split track at:"), frame ), 2, 0 );
+ layout->setColStretch( 0, 1 );
+
+ m_editorWidget->setAllowOverlappingRanges( false );
+ m_editorWidget->enableRangeSelection( true );
+ m_editorWidget->installEventFilter( this );
+
+ connect( m_editorWidget, SIGNAL(rangeChanged(int, const K3b::Msf&, const K3b::Msf&)),
+ this, SLOT(slotRangeModified(int, const K3b::Msf&, const K3b::Msf&)) );
+ connect( m_editorWidget, SIGNAL(selectedRangeChanged(int)),
+ this, SLOT(slotRangeSelectionChanged(int)) );
+ connect( m_msfEditStart, SIGNAL(valueChanged(const K3b::Msf&)),
+ this, SLOT(slotMsfEditChanged(const K3b::Msf&)) );
+ connect( m_msfEditEnd, SIGNAL(valueChanged(const K3b::Msf&)),
+ this, SLOT(slotMsfEditChanged(const K3b::Msf&)) );
+
+ setupActions();
+
+ // load the track
+ m_editorWidget->setLength( m_track->length() );
+
+ // default split
+ K3b::Msf mid = m_track->length().lba() / 2;
+ m_editorWidget->addRange( 0, mid-1 );
+ m_editorWidget->addRange( mid, m_track->length()-1 );
+
+ slotRangeSelectionChanged( 0 );
+}
+
+
+K3bAudioTrackSplitDialog::~K3bAudioTrackSplitDialog()
+{
+}
+
+
+void K3bAudioTrackSplitDialog::setupActions()
+{
+ m_actionCollection = new KActionCollection( this );
+ m_popupMenu = new KPopupMenu( this );
+
+ KAction* actionSplitHere = new KAction( i18n("Split Here"), 0,
+ KShortcut(), this, SLOT(slotSplitHere()),
+ actionCollection(), "range_split" );
+ // FIXME: after the message freeze give this action a proper name like "Remove track part"
+ KAction* actionRemoveRange = new KAction( i18n("Remove this Range"), 0,
+ KShortcut(), this, SLOT(slotRemoveRange()),
+ actionCollection(), "range_remove" );
+
+ actionSplitHere->plug( m_popupMenu );
+ actionRemoveRange->plug( m_popupMenu );
+}
+
+
+void K3bAudioTrackSplitDialog::slotRangeModified( int id, const K3b::Msf& start, const K3b::Msf& end )
+{
+ if( id == m_editorWidget->selectedRange() ) {
+ m_msfEditStart->blockSignals( true );
+ m_msfEditEnd->blockSignals( true );
+
+ m_msfEditStart->setMsfValue( start );
+ m_msfEditEnd->setMsfValue( end );
+
+ m_msfEditStart->blockSignals( false );
+ m_msfEditEnd->blockSignals( false );
+ }
+}
+
+
+void K3bAudioTrackSplitDialog::slotMsfEditChanged( const K3b::Msf& )
+{
+ m_editorWidget->modifyRange( m_editorWidget->selectedRange(), m_msfEditStart->msfValue(), m_msfEditEnd->msfValue() );
+}
+
+
+void K3bAudioTrackSplitDialog::slotRangeSelectionChanged( int id )
+{
+ if( id > 0 ) {
+ m_msfEditStart->blockSignals( true );
+ m_msfEditEnd->blockSignals( true );
+
+ m_msfEditStart->setMsfValue( m_editorWidget->rangeStart( id ) );
+ m_msfEditEnd->setMsfValue( m_editorWidget->rangeEnd( id ) );
+ m_msfEditStart->setEnabled( true );
+ m_msfEditEnd->setEnabled( true );
+
+ m_msfEditStart->blockSignals( false );
+ m_msfEditEnd->blockSignals( false );
+ }
+ else {
+ m_msfEditStart->setEnabled( false );
+ m_msfEditEnd->setEnabled( false );
+ }
+}
+
+
+void K3bAudioTrackSplitDialog::splitAt( const QPoint& p )
+{
+ int id = m_editorWidget->findRange( p.x() );
+ if( id ) {
+ K3b::Msf msf = m_editorWidget->posToMsf( p.x() );
+ m_editorWidget->addRange( msf+1, m_editorWidget->rangeEnd( id ) );
+ m_editorWidget->modifyRange( id, m_editorWidget->rangeStart( id ), msf );
+ slotRangeSelectionChanged( m_editorWidget->selectedRange() );
+ }
+}
+
+
+bool K3bAudioTrackSplitDialog::eventFilter( QObject* o, QEvent* e )
+{
+ if( o == m_editorWidget ) {
+ if( e->type() == QEvent::MouseButtonDblClick ) {
+ QMouseEvent* me = static_cast<QMouseEvent*>( e );
+ splitAt( me->pos() );
+ }
+ else if( e->type() == QEvent::ContextMenu ) {
+ QContextMenuEvent* ce = static_cast<QContextMenuEvent*>( e );
+ ce->consume();
+ m_lastClickPosition = ce->pos();
+ if( m_editorWidget->findRange( ce->pos().x() ) > 0 )
+ m_popupMenu->popup( ce->globalPos() );
+ }
+ }
+
+ return KDialogBase::eventFilter( o, e );
+}
+
+
+void K3bAudioTrackSplitDialog::slotSplitHere()
+{
+ splitAt( m_lastClickPosition );
+}
+
+
+void K3bAudioTrackSplitDialog::slotRemoveRange()
+{
+ m_editorWidget->removeRange( m_editorWidget->findRange( m_lastClickPosition.x() ) );
+}
+
+
+void K3bAudioTrackSplitDialog::splitTrack( K3bAudioTrack* track,
+ QWidget* parent,
+ const char* name )
+{
+ K3bAudioTrackSplitDialog d( track, parent, name );
+ if( d.exec() == QDialog::Accepted ) {
+ QValueList<int> ranges = d.m_editorWidget->allRanges();
+ // we split the track at all range ends and just delete those that relate to the gaps in between
+ K3b::Msf pos = 0;
+ for( QValueList<int>::const_iterator it = ranges.constBegin();
+ it != ranges.constEnd(); ++it ) {
+
+ // delete the unwanted part
+ if( d.m_editorWidget->rangeStart( *it ) > pos ) {
+ // split so the range's start is the first frame of the new track
+ K3bAudioTrack* nextTrack = track->split( d.m_editorWidget->rangeStart( *it ) - pos );
+ delete track;
+ track = nextTrack;
+ }
+
+ // create a new track part for the range itself
+ pos = d.m_editorWidget->rangeStart( *it );
+ if( d.m_editorWidget->rangeEnd( *it ) < d.m_editorWidget->length()-1 ) {
+ // split so the range's end is the last frame in the old track
+ // and thus, the range's end + 1 the first frame in the new track
+ track = track->split( d.m_editorWidget->rangeEnd( *it ) - pos + 1 );
+ }
+ pos = d.m_editorWidget->rangeEnd( *it )+1;
+ }
+
+ // remove the last unwanted part
+ if( pos < d.m_editorWidget->length() ) {
+ delete track;
+ }
+ }
+}
+
+#include "k3baudiotracksplitdialog.moc"
diff --git a/src/projects/k3baudiotracksplitdialog.h b/src/projects/k3baudiotracksplitdialog.h
new file mode 100644
index 0000000..c4be91a
--- /dev/null
+++ b/src/projects/k3baudiotracksplitdialog.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * $Id: k3baudiotracksplitdialog.h 620140 2007-01-05 12:02:29Z trueg $
+ * Copyright (C) 2004-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_TRACK_SPLIT_DIALOG_H_
+#define _K3B_AUDIO_TRACK_SPLIT_DIALOG_H_
+
+#include <kdialogbase.h>
+
+namespace K3b {
+ class Msf;
+}
+class K3bAudioTrack;
+class K3bAudioEditorWidget;
+class K3bMsfEdit;
+class KActionCollection;
+class KPopupMenu;
+
+
+/**
+ * Internally used by K3bAudioTrackView to get an msf value from the user.
+ */
+class K3bAudioTrackSplitDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioTrackSplitDialog( K3bAudioTrack*, QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioTrackSplitDialog();
+
+ bool eventFilter( QObject* o, QEvent* e );
+
+ KActionCollection* actionCollection() const { return m_actionCollection; }
+
+ /**
+ * if this method returns true val is filled with the user selected value.
+ */
+ static void splitTrack( K3bAudioTrack* track, QWidget* parent = 0, const char* name = 0 );
+
+ private slots:
+ void slotRangeModified( int, const K3b::Msf& start, const K3b::Msf& );
+ void slotMsfEditChanged( const K3b::Msf& msf );
+ void slotRangeSelectionChanged( int );
+ void slotSplitHere();
+ void slotRemoveRange();
+ void splitAt( const QPoint& p );
+
+ private:
+ void setupActions();
+
+ K3bAudioEditorWidget* m_editorWidget;
+ K3bMsfEdit* m_msfEditStart;
+ K3bMsfEdit* m_msfEditEnd;
+ K3bAudioTrack* m_track;
+ KActionCollection* m_actionCollection;
+ KPopupMenu* m_popupMenu;
+ QPoint m_lastClickPosition;
+};
+
+#endif
diff --git a/src/projects/k3baudiotracktrmlookupdialog.cpp b/src/projects/k3baudiotracktrmlookupdialog.cpp
new file mode 100644
index 0000000..b537583
--- /dev/null
+++ b/src/projects/k3baudiotracktrmlookupdialog.cpp
@@ -0,0 +1,131 @@
+/*
+ *
+ * $Id: k3baudiotracktrmlookupdialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_MUSICBRAINZ
+
+#include "k3baudiotracktrmlookupdialog.h"
+#include "k3bmusicbrainzjob.h"
+
+#include <k3bbusywidget.h>
+#include <k3baudiotrack.h>
+#include <k3baudiofile.h>
+#include <k3bpassivepopup.h>
+
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qframe.h>
+#include <qeventloop.h>
+#include <qpushbutton.h>
+#include <qapplication.h>
+
+
+K3bAudioTrackTRMLookupDialog::K3bAudioTrackTRMLookupDialog( QWidget* parent, const char* name )
+ : KDialogBase( KDialogBase::Plain,
+ i18n("MusicBrainz Query"),
+ KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ parent,
+ name,
+ true,
+ true )
+{
+ QGridLayout* grid = new QGridLayout( plainPage() );
+ grid->setMargin( marginHint() );
+ grid->setSpacing( spacingHint() );
+
+ m_infoLabel = new QLabel( plainPage() );
+ QLabel* pixLabel = new QLabel( plainPage() );
+ pixLabel->setPixmap( KGlobal::iconLoader()->loadIcon( "musicbrainz", KIcon::NoGroup, 64 ) );
+ pixLabel->setScaledContents( false );
+
+ m_busyWidget = new K3bBusyWidget( plainPage() );
+
+ grid->addMultiCellWidget( pixLabel, 0, 1, 0, 0 );
+ grid->addWidget( m_infoLabel, 0, 1 );
+ grid->addWidget( m_busyWidget, 1, 1 );
+
+ m_inLoop = false;
+ m_mbJob = new K3bMusicBrainzJob( this );
+ connect( m_mbJob, SIGNAL(infoMessage(const QString&, int)),
+ this, SLOT(slotMbJobInfoMessage(const QString&, int)) );
+ connect( m_mbJob, SIGNAL(finished(bool)), this, SLOT(slotMbJobFinished(bool)) );
+ connect( m_mbJob, SIGNAL(trackFinished(K3bAudioTrack*, bool)),
+ this, SLOT(slotTrackFinished(K3bAudioTrack*, bool)) );
+}
+
+
+K3bAudioTrackTRMLookupDialog::~K3bAudioTrackTRMLookupDialog()
+{
+}
+
+
+int K3bAudioTrackTRMLookupDialog::lookup( const QPtrList<K3bAudioTrack>& tracks )
+{
+ m_mbJob->setTracks( tracks );
+ m_mbJob->start();
+
+ m_busyWidget->showBusy(true);
+ setModal( true );
+ show();
+ m_inLoop = true;
+ QApplication::eventLoop()->enterLoop();
+
+ return 0;
+}
+
+
+void K3bAudioTrackTRMLookupDialog::slotMbJobInfoMessage( const QString& message, int )
+{
+ m_infoLabel->setText( message );
+}
+
+
+void K3bAudioTrackTRMLookupDialog::slotMbJobFinished( bool )
+{
+ m_busyWidget->showBusy(false);
+ hide();
+ if( m_inLoop )
+ QApplication::eventLoop()->exitLoop();
+}
+
+
+void K3bAudioTrackTRMLookupDialog::slotCancel()
+{
+ actionButton( Cancel )->setEnabled( false );
+ m_mbJob->cancel();
+}
+
+
+void K3bAudioTrackTRMLookupDialog::slotTrackFinished( K3bAudioTrack* track, bool success )
+{
+ if( !success )
+ K3bPassivePopup::showPopup( i18n("Track %1 was not found in the MusicBrainz database.")
+ .arg( track->trackNumber()),
+ i18n("Audio Project") );
+}
+
+#include "k3baudiotracktrmlookupdialog.moc"
+
+#endif
diff --git a/src/projects/k3baudiotracktrmlookupdialog.h b/src/projects/k3baudiotracktrmlookupdialog.h
new file mode 100644
index 0000000..10a0f32
--- /dev/null
+++ b/src/projects/k3baudiotracktrmlookupdialog.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * $Id: k3baudiotracktrmlookupdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIOTRACK_TRM_LOOKUP_DIALOG_H_
+#define _K3B_AUDIOTRACK_TRM_LOOKUP_DIALOG_H_
+
+#include <kdialogbase.h>
+#include <qptrlist.h>
+
+class QLabel;
+class K3bAudioTrack;
+class K3bMusicBrainzJob;
+class K3bBusyWidget;
+
+
+class K3bAudioTrackTRMLookupDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioTrackTRMLookupDialog( QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioTrackTRMLookupDialog();
+
+ /**
+ * This will show the dialog and start the lookup
+ */
+ int lookup( const QPtrList<K3bAudioTrack>& tracks );
+
+ private slots:
+ void slotMbJobFinished( bool );
+ void slotMbJobInfoMessage( const QString&, int );
+ void slotTrackFinished( K3bAudioTrack* track, bool success );
+ void slotCancel();
+
+ private:
+ QLabel* m_infoLabel;
+ K3bBusyWidget* m_busyWidget;
+ K3bMusicBrainzJob* m_mbJob;
+ bool m_inLoop;
+};
+
+#endif
diff --git a/src/projects/k3baudiotrackview.cpp b/src/projects/k3baudiotrackview.cpp
new file mode 100644
index 0000000..1af6a5c
--- /dev/null
+++ b/src/projects/k3baudiotrackview.cpp
@@ -0,0 +1,1005 @@
+/*
+ *
+ * $Id: k3baudiotrackview.cpp 689561 2007-07-18 15:19:38Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3baudiotrackview.h"
+#include "k3baudiotrackviewitem.h"
+#include "k3baudiodatasourceviewitem.h"
+#include "k3baudiotrack.h"
+#include "k3baudiodatasource.h"
+#include "k3baudiotrackdialog.h"
+#include "k3baudiodoc.h"
+#include "k3baudiozerodata.h"
+#include "k3baudiotracksplitdialog.h"
+#include "k3baudiofile.h"
+#include "k3baudiotrackplayer.h"
+#include "k3baudiocdtrackdrag.h"
+#include "k3baudiocdtracksource.h"
+#include "k3baudiotracktrmlookupdialog.h"
+#include "k3baudiodatasourceeditwidget.h"
+#include "k3baudiotrackaddingdialog.h"
+
+#include <k3bview.h>
+#include <k3blistviewitemanimator.h>
+#include <k3baudiodecoder.h>
+#include <k3bmsfedit.h>
+
+#include <qheader.h>
+#include <qtimer.h>
+#include <qdragobject.h>
+#include <qpoint.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvaluelist.h>
+
+#include <kurl.h>
+#include <kurldrag.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kdialogbase.h>
+
+
+K3bAudioTrackView::K3bAudioTrackView( K3bAudioDoc* doc, QWidget* parent, const char* name )
+ : K3bListView( parent, name ),
+ m_doc(doc),
+ m_updatingColumnWidths(false),
+ m_currentMouseOverItem(0),
+ m_currentlyPlayingTrack(0)
+{
+ m_player = new K3bAudioTrackPlayer( m_doc, this );
+ connect( m_player, SIGNAL(playingTrack(K3bAudioTrack*)), this,
+ SLOT(showPlayerIndicator(K3bAudioTrack*)) );
+ connect( m_player, SIGNAL(paused(bool)), this, SLOT(togglePauseIndicator(bool)) );
+ connect( m_player, SIGNAL(stopped()), this, SLOT(removePlayerIndicator()) );
+
+ setItemMargin( 5 );
+ setAcceptDrops( true );
+ setDropVisualizer( true );
+ setAllColumnsShowFocus( true );
+ setDragEnabled( true );
+ // setSelectionModeExt( KListView::Konqueror ); // FileManager in KDE3
+ setSelectionModeExt( KListView::Extended );
+ setItemsMovable( false );
+ setAlternateBackground( QColor() ); // disable alternate colors
+
+ setNoItemText( i18n("Use drag'n'drop to add audio files to the project.") + "\n"
+ + i18n("After that press the burn button to write the CD." ) );
+
+ setupColumns();
+ setupActions();
+
+ m_playerItemAnimator = new K3bListViewItemAnimator( this );
+
+ m_animationTimer = new QTimer( this );
+ connect( m_animationTimer, SIGNAL(timeout()), this, SLOT(slotAnimation()) );
+
+ m_autoOpenTrackTimer = new QTimer( this );
+ connect( m_autoOpenTrackTimer, SIGNAL(timeout()), this, SLOT(slotDragTimeout()) );
+
+ connect( this, SIGNAL(dropped(QDropEvent*, QListViewItem*, QListViewItem*)),
+ this, SLOT(slotDropped(QDropEvent*, QListViewItem*, QListViewItem*)) );
+ connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(showPopupMenu(KListView*, QListViewItem*, const QPoint&)) );
+ connect( this, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)),
+ this, SLOT(slotProperties()) );
+
+ connect( doc, SIGNAL(changed()),
+ this, SLOT(slotChanged()) );
+ connect( doc, SIGNAL(trackChanged(K3bAudioTrack*)),
+ this, SLOT(slotTrackChanged(K3bAudioTrack*)) );
+ connect( doc, SIGNAL(trackRemoved(K3bAudioTrack*)),
+ this, SLOT(slotTrackRemoved(K3bAudioTrack*)) );
+
+ slotChanged();
+
+ // a little background pix hack because I am simply incapable of doing it another way. :(
+// static QPixmap s_bgPix("/tmp/trueg/audio_bg.png");
+// setK3bBackgroundPixmap( s_bgPix, TOP_LEFT );
+}
+
+
+K3bAudioTrackView::~K3bAudioTrackView()
+{
+}
+
+
+void K3bAudioTrackView::setupColumns()
+{
+ addColumn( i18n("No.") );
+ addColumn( i18n("Artist (CD-Text)") );
+ addColumn( i18n("Title (CD-Text)") );
+ addColumn( i18n("Type") );
+ addColumn( i18n("Length") );
+ addColumn( i18n("Filename") );
+
+ setColumnAlignment( 3, Qt::AlignHCenter );
+ setColumnAlignment( 4, Qt::AlignHCenter );
+
+ setColumnWidthMode( 1, Manual );
+ setColumnWidthMode( 2, Manual );
+ setColumnWidthMode( 3, Manual );
+ setColumnWidthMode( 4, Manual );
+ setColumnWidthMode( 5, Manual );
+
+ header()->setResizeEnabled( false );
+ header()->setClickEnabled( false );
+ setSorting( -1 );
+}
+
+
+void K3bAudioTrackView::setupActions()
+{
+ m_actionCollection = new KActionCollection( this );
+ m_popupMenu = new KPopupMenu( this );
+
+ m_actionProperties = new KAction( i18n("Properties"), "misc",
+ KShortcut(), this, SLOT(slotProperties()),
+ actionCollection(), "track_properties" );
+ m_actionRemove = new KAction( i18n( "Remove" ), "editdelete",
+ Key_Delete, this, SLOT(slotRemove()),
+ actionCollection(), "track_remove" );
+
+ m_actionAddSilence = new KAction( i18n("Add Silence") + "...", "misc",
+ KShortcut(), this, SLOT(slotAddSilence()),
+ actionCollection(), "track_add_silence" );
+ m_actionMergeTracks = new KAction( i18n("Merge Tracks"), "misc",
+ KShortcut(), this, SLOT(slotMergeTracks()),
+ actionCollection(), "track_merge" );
+ m_actionSplitSource = new KAction( i18n("Source to Track"), "misc",
+ KShortcut(), this, SLOT(slotSplitSource()),
+ actionCollection(), "source_split" );
+ m_actionSplitTrack = new KAction( i18n("Split Track..."), 0,
+ KShortcut(), this, SLOT(slotSplitTrack()),
+ actionCollection(), "track_split" );
+ m_actionEditSource = new KAction( i18n("Edit Source..."), 0,
+ KShortcut(), this, SLOT(slotEditSource()),
+ actionCollection(), "source_edit" );
+ m_actionPlayTrack = new KAction( i18n("Play Track"), "player_play",
+ KShortcut(), this, SLOT(slotPlayTrack()),
+ actionCollection(), "track_play" );
+#ifdef HAVE_MUSICBRAINZ
+ KAction* mbAction = new KAction( i18n("Musicbrainz Lookup"), "musicbrainz", 0, this,
+ SLOT(slotQueryMusicBrainz()),
+ actionCollection(), "project_audio_musicbrainz" );
+ mbAction->setToolTip( i18n("Try to determine meta information over the internet") );
+#endif
+}
+
+
+bool K3bAudioTrackView::acceptDrag(QDropEvent* e) const
+{
+ // the first is for built-in item moving, the second for dropping urls, the third for dropping audio tracks
+ return ( KListView::acceptDrag(e) || KURLDrag::canDecode(e) || K3bAudioCdTrackDrag::canDecode(e) );
+}
+
+
+QDragObject* K3bAudioTrackView::dragObject()
+{
+ QPtrList<QListViewItem> list = selectedItems();
+
+ if( list.isEmpty() )
+ return 0;
+
+ KURL::List urls;
+
+ for( QPtrListIterator<QListViewItem> it(list); it.current(); ++it ) {
+ QListViewItem* item = *it;
+ // we simply ignore open track items to not include files twice
+ // we also don't want the invisible source items
+ QListViewItem* parentItem = K3bListView::parentItem(item);
+ if( !item->isOpen() && ( !parentItem || parentItem->isOpen() ) ) {
+ if( K3bAudioDataSourceViewItem* sourceItem = dynamic_cast<K3bAudioDataSourceViewItem*>( item ) ) {
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( sourceItem->source() ) )
+ urls.append( KURL::fromPathOrURL(file->filename()) );
+ }
+ else {
+ K3bAudioTrackViewItem* trackItem = static_cast<K3bAudioTrackViewItem*>( item );
+ K3bAudioDataSource* source = trackItem->track()->firstSource();
+ while( source ) {
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( source ) )
+ urls.append( KURL::fromPathOrURL(file->filename()) );
+ source = source->next();
+ }
+ }
+ }
+ }
+
+ return new KURLDrag( urls, viewport() );
+}
+
+
+void K3bAudioTrackView::slotDropped( QDropEvent* e, QListViewItem* parent, QListViewItem* after )
+{
+ m_autoOpenTrackTimer->stop();
+
+ if( !e->isAccepted() )
+ return;
+
+ m_dropTrackAfter = 0;
+ m_dropTrackParent = 0;
+ m_dropSourceAfter = 0;
+ if( after ) {
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( after ) ) {
+ m_dropTrackAfter = tv->track();
+ }
+ else if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>( after ) ) {
+ m_dropSourceAfter = sv->source();
+ }
+ }
+
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( parent ) ) {
+ m_dropTrackParent = tv->track();
+ }
+
+ //
+ // In case the sources are not shown we do not want to handle them because the average
+ // user would be confused otherwise
+ //
+ if( m_dropTrackParent && !m_trackItemMap[m_dropTrackParent]->showingSources() ) {
+ kdDebug() << "(K3bAudioTrackView) dropped after track which does not show it's sources." << endl;
+ m_dropTrackAfter = m_dropTrackParent;
+ m_dropTrackParent = 0;
+ }
+
+ if( e->source() == viewport() ) {
+
+ bool copyItems = (e->action() == QDropEvent::Copy);
+
+ // 1. tracks (with some of their sources) -> move complete tracks around
+ // 2. sources (multiple sources) -> move the sources to the destination track
+ // 3. tracks and sources (the latter without their track) -> ignore the latter sources
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ //
+ // remove all sources which belong to one of the selected tracks since they will be
+ // moved along with their tracks
+ //
+ QPtrListIterator<K3bAudioDataSource> srcIt( sources );
+ while( srcIt.current() ) {
+ if( tracks.containsRef( srcIt.current()->track() ) )
+ sources.removeRef( *srcIt );
+ else
+ ++srcIt;
+ }
+
+ //
+ // Now move (or copy) all the tracks
+ //
+ for( QPtrListIterator<K3bAudioTrack> it( tracks ); it.current(); ++it ) {
+ K3bAudioTrack* track = *it;
+ if( m_dropTrackParent ) {
+ m_dropTrackParent->merge( copyItems ? track->copy() : track, m_dropSourceAfter );
+ }
+ else if( m_dropTrackAfter ) {
+ if( copyItems )
+ track->copy()->moveAfter( m_dropTrackAfter );
+ else
+ track->moveAfter( m_dropTrackAfter );
+ }
+ else {
+ if( copyItems )
+ track->copy()->moveAhead( m_doc->firstTrack() );
+ else
+ track->moveAhead( m_doc->firstTrack() );
+ }
+ }
+
+ //
+ // now move (or copy) the sources
+ //
+ for( QPtrListIterator<K3bAudioDataSource> it( sources ); it.current(); ++it ) {
+ K3bAudioDataSource* source = *it;
+ if( m_dropTrackParent ) {
+ if( m_dropSourceAfter ) {
+ if( copyItems )
+ source->copy()->moveAfter( m_dropSourceAfter );
+ else
+ source->moveAfter( m_dropSourceAfter );
+ }
+ else {
+ if( copyItems )
+ source->copy()->moveAhead( m_dropTrackParent->firstSource() );
+ else
+ source->moveAhead( m_dropTrackParent->firstSource() );
+ }
+ }
+ else {
+ // create a new track
+ K3bAudioTrack* track = new K3bAudioTrack( m_doc );
+
+ // special case: the source we remove from the track is the last and the track
+ // will be deleted.
+ if( !copyItems && m_dropTrackAfter == source->track() && m_dropTrackAfter->numberSources() == 1 )
+ m_dropTrackAfter = m_dropTrackAfter->prev();
+
+ if( copyItems )
+ track->addSource( source->copy() );
+ else
+ track->addSource( source );
+
+ if( m_dropTrackAfter ) {
+ track->moveAfter( m_dropTrackAfter );
+ m_dropTrackAfter = track;
+ }
+ else {
+ track->moveAhead( m_doc->firstTrack() );
+ m_dropTrackAfter = track;
+ }
+ }
+ }
+ }
+ else if( K3bAudioCdTrackDrag::canDecode( e ) ) {
+ kdDebug() << "(K3bAudioTrackView) audiocdtrack dropped." << endl;
+ K3bDevice::Toc toc;
+ K3bDevice::Device* dev = 0;
+ K3bCddbResultEntry cddb;
+ QValueList<int> trackNumbers;
+
+ K3bAudioCdTrackDrag::decode( e, toc, trackNumbers, cddb, &dev );
+
+ // for now we just create one source
+ for( QValueList<int>::const_iterator it = trackNumbers.begin();
+ it != trackNumbers.end(); ++it ) {
+ int trackNumber = *it;
+
+ K3bAudioCdTrackSource* source = new K3bAudioCdTrackSource( toc, trackNumber, cddb, dev );
+ if( m_dropTrackParent ) {
+ source->moveAfter( m_dropSourceAfter );
+ if( m_dropSourceAfter )
+ m_dropSourceAfter = source;
+ }
+ else {
+ K3bAudioTrack* track = new K3bAudioTrack();
+ track->setPerformer( cddb.artists[trackNumber-1] );
+ track->setTitle( cddb.titles[trackNumber-1] );
+ track->addSource( source );
+ if( m_dropTrackAfter )
+ track->moveAfter( m_dropTrackAfter );
+ else
+ m_doc->addTrack( track, 0 );
+
+ m_dropTrackAfter = track;
+ }
+ }
+ }
+ else{
+ m_dropUrls.clear();
+ if( KURLDrag::decode( e, m_dropUrls ) ) {
+ //
+ // This is a small (not to ugly) hack to circumvent problems with the
+ // event queues: the url adding dialog will be non-modal regardless of
+ // the settings in case we open it directly.
+ //
+ QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
+ }
+ }
+
+ showAllSources();
+
+ // now grab that focus
+ setFocus();
+}
+
+
+void K3bAudioTrackView::slotAddUrls()
+{
+ K3bAudioTrackAddingDialog::addUrls( m_dropUrls, m_doc, m_dropTrackAfter, m_dropTrackParent, m_dropSourceAfter, this );
+}
+
+
+void K3bAudioTrackView::slotChanged()
+{
+ kdDebug() << "(K3bAudioTrackView::slotChanged)" << endl;
+ // we only need to add new items here. Everything else is done in the
+ // specific slots below
+ K3bAudioTrack* track = m_doc->firstTrack();
+ bool newTracks = false;
+ while( track ) {
+ bool newTrack;
+ getTrackViewItem( track, &newTrack );
+ if( newTrack )
+ newTracks = true;
+ track = track->next();
+ }
+
+ if( newTracks ) {
+ m_animationTimer->start(200);
+ showAllSources();
+ }
+
+ header()->setShown( m_doc->numOfTracks() > 0 );
+
+ kdDebug() << "(K3bAudioTrackView::slotChanged) finished" << endl;
+}
+
+
+K3bAudioTrackViewItem* K3bAudioTrackView::getTrackViewItem( K3bAudioTrack* track, bool* isNewItem )
+{
+ QMap<K3bAudioTrack*, K3bAudioTrackViewItem*>::iterator itemIt = m_trackItemMap.find(track);
+ if( itemIt == m_trackItemMap.end() ) {
+ kdDebug() << "(K3bAudioTrackView) new track " << track << endl;
+ K3bAudioTrackViewItem* prevItem = 0;
+ if( track->prev() && m_trackItemMap.contains( track->prev() ) )
+ prevItem = m_trackItemMap[track->prev()];
+ K3bAudioTrackViewItem* newItem = new K3bAudioTrackViewItem( this, prevItem, track );
+ //
+ // disable the item until the files have been analysed
+ // so the user may not change the cd-text until the one from the
+ // file is loaded.
+ //
+ // Since for some reason QT thinks it's bad to open disabled items
+ // we need to open it before disabling it
+ //
+ newItem->showSources( track->numberSources() != 1 );
+ newItem->setEnabled( false );
+ m_trackItemMap[track] = newItem;
+
+ if( isNewItem )
+ *isNewItem = true;
+ return newItem;
+ }
+ else {
+ if( isNewItem )
+ *isNewItem = false;
+ return *itemIt;
+ }
+}
+
+
+void K3bAudioTrackView::slotTrackChanged( K3bAudioTrack* track )
+{
+ kdDebug() << "(K3bAudioTrackView::slotTrackChanged( " << track << " )" << endl;
+
+ //
+ // There may be some tracks around that have not been added to the list yet
+ // (and might never). We ignore them until they are in the list and then
+ // we create the item in slotChanged
+ //
+ if( track->inList() ) {
+ K3bAudioTrackViewItem* item = getTrackViewItem(track);
+ item->updateSourceItems();
+
+ if( track->numberSources() > 1 )
+ item->showSources(true);
+
+ // the length might have changed
+ item->repaint();
+
+ // FIXME: only do this if the position really changed
+ // move the item if the position has changed
+ if( track->prev() && m_trackItemMap.contains(track->prev()) )
+ item->moveItem( m_trackItemMap[track->prev()] );
+ else if( !track->prev() ) {
+ takeItem( item );
+ insertItem( item );
+ }
+
+ // start the animation in case new sources have been added
+ m_animationTimer->start( 200 );
+
+ showAllSources();
+ }
+ kdDebug() << "(K3bAudioTrackView::slotTrackChanged( " << track << " ) finished" << endl;
+}
+
+
+void K3bAudioTrackView::slotTrackRemoved( K3bAudioTrack* track )
+{
+ kdDebug() << "(K3bAudioTrackView::slotTrackRemoved( " << track << " )" << endl;
+ if ( m_playerItemAnimator->item() == m_trackItemMap[track] ) {
+ m_playerItemAnimator->stop();
+ }
+ delete m_trackItemMap[track];
+ m_trackItemMap.erase(track);
+}
+
+
+void K3bAudioTrackView::showAllSources()
+{
+ // TODO: add an action to show all sources
+
+ QListViewItem* item = firstChild();
+ while( item ) {
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( item ) )
+ tv->showSources( tv->track()->numberSources() != 1 );
+ item = item->nextSibling();
+ }
+}
+
+
+void K3bAudioTrackView::keyPressEvent( QKeyEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::keyPressEvent(e);
+}
+
+
+void K3bAudioTrackView::keyReleaseEvent( QKeyEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::keyReleaseEvent(e);
+}
+
+
+void K3bAudioTrackView::contentsMouseMoveEvent( QMouseEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::contentsMouseMoveEvent( e );
+}
+
+
+void K3bAudioTrackView::focusOutEvent( QFocusEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::focusOutEvent( e );
+}
+
+
+void K3bAudioTrackView::resizeEvent( QResizeEvent* e )
+{
+ K3bListView::resizeEvent(e);
+
+ resizeColumns();
+}
+
+
+void K3bAudioTrackView::contentsDragMoveEvent( QDragMoveEvent* event )
+{
+ K3bAudioTrackViewItem* item = findTrackItem( event->pos() );
+ if( m_currentMouseOverItem != item ) {
+ showAllSources(); // hide previous sources
+ m_currentMouseOverItem = item;
+ }
+ if( m_currentMouseOverItem )
+ m_autoOpenTrackTimer->start( 1000 ); // 1 sec
+
+ K3bListView::contentsDragMoveEvent( event );
+}
+
+
+void K3bAudioTrackView::contentsDragLeaveEvent( QDragLeaveEvent* e )
+{
+ m_autoOpenTrackTimer->stop();
+ K3bListView::contentsDragLeaveEvent( e );
+}
+
+
+K3bAudioTrackViewItem* K3bAudioTrackView::findTrackItem( const QPoint& pos ) const
+{
+ QListViewItem* parent = 0;
+ QListViewItem* after = 0;
+ K3bAudioTrackView* that = const_cast<K3bAudioTrackView*>(this);
+ that->findDrop( pos, parent, after );
+ if( parent )
+ return static_cast<K3bAudioTrackViewItem*>( parent );
+ else if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(after) )
+ return tv;
+ else if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(after) )
+ return sv->trackViewItem();
+ else
+ return 0;
+}
+
+
+void K3bAudioTrackView::resizeColumns()
+{
+ if( m_updatingColumnWidths ) {
+ kdDebug() << "(K3bAudioTrackView) already updating column widths." << endl;
+ return;
+ }
+
+ m_updatingColumnWidths = true;
+
+ // now properly resize the columns
+ // minimal width for type, length, pregap
+ // fixed for filename
+ // expand for cd-text
+ int titleWidth = header()->fontMetrics().width( header()->label(1) );
+ int artistWidth = header()->fontMetrics().width( header()->label(2) );
+ int typeWidth = header()->fontMetrics().width( header()->label(3) );
+ int lengthWidth = header()->fontMetrics().width( header()->label(4) );
+ int filenameWidth = header()->fontMetrics().width( header()->label(5) );
+
+ for( QListViewItemIterator it( this ); it.current(); ++it ) {
+ artistWidth = QMAX( artistWidth, it.current()->width( fontMetrics(), this, 1 ) );
+ titleWidth = QMAX( titleWidth, it.current()->width( fontMetrics(), this, 2 ) );
+ typeWidth = QMAX( typeWidth, it.current()->width( fontMetrics(), this, 3 ) );
+ lengthWidth = QMAX( lengthWidth, it.current()->width( fontMetrics(), this, 4 ) );
+ filenameWidth = QMAX( filenameWidth, it.current()->width( fontMetrics(), this, 5 ) );
+ }
+
+ // add a margin
+ typeWidth += 10;
+ lengthWidth += 10;
+
+ // these always need to be completely visible
+ setColumnWidth( 3, typeWidth );
+ setColumnWidth( 4, lengthWidth );
+
+ int remaining = visibleWidth() - typeWidth - lengthWidth - columnWidth(0);
+
+ // now let's see if there is enough space for all
+ if( remaining >= artistWidth + titleWidth + filenameWidth ) {
+ remaining -= filenameWidth;
+ remaining -= (titleWidth + artistWidth);
+ setColumnWidth( 1, artistWidth + remaining/2 );
+ setColumnWidth( 2, titleWidth + remaining/2 );
+ setColumnWidth( 5, filenameWidth );
+ }
+ else if( remaining >= artistWidth + titleWidth + 20 ) {
+ setColumnWidth( 1, artistWidth );
+ setColumnWidth( 2, titleWidth );
+ setColumnWidth( 5, remaining - artistWidth - titleWidth );
+ }
+ else {
+ setColumnWidth( 1, remaining/3 );
+ setColumnWidth( 2, remaining/3 );
+ setColumnWidth( 5, remaining/3 );
+ }
+
+ triggerUpdate();
+ m_updatingColumnWidths = false;
+}
+
+
+void K3bAudioTrackView::slotAnimation()
+{
+ resizeColumns();
+ QListViewItem* item = firstChild();
+
+ bool animate = false;
+
+ while( item ) {
+ K3bAudioTrackViewItem* trackItem = dynamic_cast<K3bAudioTrackViewItem*>(item);
+ if( trackItem->animate() )
+ animate = true;
+ else
+ trackItem->setEnabled( true ); // files analysed, cd-text loaded
+ item = item->nextSibling();
+ }
+
+ if( !animate ) {
+ m_animationTimer->stop();
+ }
+}
+
+
+void K3bAudioTrackView::slotDragTimeout()
+{
+ m_autoOpenTrackTimer->stop();
+
+ if( m_currentMouseOverItem ) {
+ m_currentMouseOverItem->showSources( true );
+ }
+}
+
+
+void K3bAudioTrackView::getSelectedItems( QPtrList<K3bAudioTrack>& tracks,
+ QPtrList<K3bAudioDataSource>& sources )
+{
+ tracks.clear();
+ sources.clear();
+
+ QPtrList<QListViewItem> items = selectedItems();
+ for( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it ) {
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( *it ) )
+ tracks.append( tv->track() );
+ else {
+ K3bAudioDataSourceViewItem* sv = static_cast<K3bAudioDataSourceViewItem*>( *it );
+ // do not select hidden source items or unfinished source files
+ if( sv->trackViewItem()->showingSources() &&
+ !(sv->source()->isValid() && sv->source()->length() == 0) )
+ sources.append( sv->source() );
+ }
+ }
+}
+
+
+void K3bAudioTrackView::slotRemove()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ //
+ // remove all sources which belong to one of the selected tracks since they will be
+ // deleted along with their tracks
+ //
+ QPtrListIterator<K3bAudioDataSource> srcIt( sources );
+ while( srcIt.current() ) {
+ if( tracks.containsRef( srcIt.current()->track() ) )
+ sources.removeRef( *srcIt );
+ else
+ ++srcIt;
+ }
+
+ //
+ // Now delete all the tracks
+ //
+ for( QPtrListIterator<K3bAudioTrack> it( tracks ); it.current(); ++it )
+ delete *it;
+
+ //
+ // Now delete all the sources
+ //
+ for( QPtrListIterator<K3bAudioDataSource> it( sources ); it.current(); ++it )
+ delete *it;
+}
+
+
+void K3bAudioTrackView::slotAddSilence()
+{
+ QListViewItem* item = selectedItems().first();
+ if( item ) {
+ //
+ // create a simple dialog for asking the length of the silence
+ //
+ KDialogBase dlg( KDialogBase::Plain,
+ i18n("Add Silence"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok,
+ this );
+ QHBoxLayout* dlgLayout = new QHBoxLayout( dlg.plainPage(), 0, KDialog::spacingHint() );
+ dlgLayout->setAutoAdd( true );
+ (void)new QLabel( i18n("Length of silence:"), dlg.plainPage() );
+ K3bMsfEdit* msfEdit = new K3bMsfEdit( dlg.plainPage() );
+ msfEdit->setValue( 150 ); // 2 seconds default
+ msfEdit->setFocus();
+
+ if( dlg.exec() == QDialog::Accepted ) {
+ K3bAudioZeroData* zero = new K3bAudioZeroData( msfEdit->value() );
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) ) {
+ tv->track()->addSource( zero );
+ }
+ else if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(item) ) {
+ zero->moveAfter( sv->source() );
+ }
+ }
+ }
+}
+
+
+void K3bAudioTrackView::slotMergeTracks()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ // we simply merge the selected tracks ignoring any eventually selected sources
+ K3bAudioTrack* firstTrack = tracks.first();
+ tracks.remove();
+ while( K3bAudioTrack* mergeTrack = tracks.first() ) {
+ tracks.remove();
+ firstTrack->merge( mergeTrack, firstTrack->lastSource() );
+ }
+}
+
+
+void K3bAudioTrackView::slotSplitSource()
+{
+ QListViewItem* item = selectedItems().first();
+ if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(item) ) {
+ // create a new track
+ K3bAudioTrack* track = new K3bAudioTrack( m_doc );
+ K3bAudioTrack* trackAfter = sv->source()->track();
+ if( trackAfter->numberSources() == 1 )
+ trackAfter = trackAfter->prev();
+ track->addSource( sv->source()->take() );
+ track->moveAfter( trackAfter );
+
+ // let's see if it's a file because in that case we can reuse the metainfo :)
+ // TODO: maybe add meta data to sources
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( track->firstSource() ) ) {
+ track->setArtist( file->decoder()->metaInfo( K3bAudioDecoder::META_ARTIST ) );
+ track->setTitle( file->decoder()->metaInfo( K3bAudioDecoder::META_TITLE ) );
+ track->setSongwriter( file->decoder()->metaInfo( K3bAudioDecoder::META_SONGWRITER ) );
+ track->setComposer( file->decoder()->metaInfo( K3bAudioDecoder::META_COMPOSER ) );
+ track->setCdTextMessage( file->decoder()->metaInfo( K3bAudioDecoder::META_COMMENT ) );
+ }
+ }
+}
+
+
+void K3bAudioTrackView::slotSplitTrack()
+{
+ QListViewItem* item = selectedItems().first();
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) ) {
+ K3bAudioTrackSplitDialog::splitTrack( tv->track(), this );
+ }
+}
+
+
+void K3bAudioTrackView::slotEditSource()
+{
+ QListViewItem* item = selectedItems().first();
+
+ K3bAudioDataSource* source = 0;
+ if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(item) )
+ source = sv->source();
+ else if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) )
+ source = tv->track()->firstSource();
+
+ if( source ) {
+ KDialogBase dlg( KDialogBase::Plain,
+ i18n("Edit Audio Track Source"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok,
+ this,
+ 0,
+ true,
+ true );
+ QVBoxLayout* lay = new QVBoxLayout( dlg.plainPage() );
+ lay->setMargin( 0 );
+ lay->setSpacing( KDialog::spacingHint() );
+ lay->setAutoAdd( true );
+ K3bAudioDataSourceEditWidget* editW = new K3bAudioDataSourceEditWidget( dlg.plainPage() );
+ editW->loadSource( source );
+ if( dlg.exec() == QDialog::Accepted )
+ editW->saveSource();
+ }
+}
+
+
+void K3bAudioTrackView::showPopupMenu( KListView*, QListViewItem* item, const QPoint& pos )
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ int numTracks = tracks.count();
+ int numSources = sources.count();
+
+ // build the menu
+ m_popupMenu->clear();
+
+ if( numTracks >= 1 ) {
+ m_actionPlayTrack->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ }
+
+ if( item )
+ m_actionRemove->plug( m_popupMenu );
+
+ if( numSources + numTracks == 1 )
+ m_actionAddSilence->plug( m_popupMenu );
+
+ if( numSources == 1 && numTracks == 0 ) {
+ m_popupMenu->insertSeparator();
+ m_actionSplitSource->plug( m_popupMenu );
+ m_actionEditSource->plug( m_popupMenu );
+ }
+ else if( numTracks == 1 && numSources == 0 ) {
+ m_popupMenu->insertSeparator();
+
+
+
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) )
+ if( tv->track()->length().lba() > 60 )
+ m_actionSplitTrack->plug( m_popupMenu );
+
+ m_actionEditSource->plug( m_popupMenu );
+
+ }
+ else if( numTracks > 1 ) {
+ m_popupMenu->insertSeparator();
+ m_actionMergeTracks->plug( m_popupMenu );
+ }
+
+ m_actionProperties->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ static_cast<K3bView*>(m_doc->view())->actionCollection()->action( "project_burn" )->plug( m_popupMenu );
+
+ m_popupMenu->popup( pos );
+}
+
+
+void K3bAudioTrackView::slotProperties()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ // TODO: add tracks from sources to tracks
+
+ if( !tracks.isEmpty() ) {
+ K3bAudioTrackDialog d( tracks, this );
+ d.exec();
+ }
+ else {
+ static_cast<K3bView*>(m_doc->view())->slotProperties();
+ }
+}
+
+
+void K3bAudioTrackView::slotPlayTrack()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+ if( tracks.count() > 0 )
+ m_player->playTrack( tracks.first() );
+}
+
+
+void K3bAudioTrackView::showPlayerIndicator( K3bAudioTrack* track )
+{
+ removePlayerIndicator();
+ m_currentlyPlayingTrack = track;
+ K3bAudioTrackViewItem* item = getTrackViewItem( track );
+ item->setPixmap( 1, SmallIcon( "player_play" ) );
+ m_playerItemAnimator->setItem( item, 1 );
+}
+
+
+void K3bAudioTrackView::togglePauseIndicator( bool b )
+{
+ if( m_currentlyPlayingTrack ) {
+ if( b )
+ m_playerItemAnimator->setPixmap( SmallIcon( "player_pause" ) );
+ else
+ m_playerItemAnimator->setPixmap( SmallIcon( "player_play" ) );
+ }
+}
+
+
+void K3bAudioTrackView::removePlayerIndicator()
+{
+ if( m_currentlyPlayingTrack )
+ getTrackViewItem( m_currentlyPlayingTrack )->setPixmap( 1, QPixmap() );
+ m_playerItemAnimator->stop();
+ m_currentlyPlayingTrack = 0;
+}
+
+
+void K3bAudioTrackView::slotQueryMusicBrainz()
+{
+#ifdef HAVE_MUSICBRAINZ
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ if( tracks.isEmpty() ) {
+ KMessageBox::sorry( this, i18n("Please select an audio track.") );
+ return;
+ }
+
+ // only one may use the tracks at the same time
+ if( m_currentlyPlayingTrack &&
+ tracks.containsRef( m_currentlyPlayingTrack ) )
+ m_player->stop();
+
+ // now do the lookup on the files.
+ K3bAudioTrackTRMLookupDialog dlg( this );
+ dlg.lookup( tracks );
+#endif
+}
+
+#include "k3baudiotrackview.moc"
diff --git a/src/projects/k3baudiotrackview.h b/src/projects/k3baudiotrackview.h
new file mode 100644
index 0000000..07415b6
--- /dev/null
+++ b/src/projects/k3baudiotrackview.h
@@ -0,0 +1,142 @@
+/*
+ *
+ * $Id: k3baudiotrackview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_TRACK_VIEW_H_
+#define _K3B_AUDIO_TRACK_VIEW_H_
+
+#include <k3blistview.h>
+
+#include <qmap.h>
+#include <qptrlist.h>
+#include <kurl.h>
+
+class K3bAudioTrack;
+class K3bAudioTrackViewItem;
+class K3bAudioDataSource;
+class K3bAudioDoc;
+class KActionCollection;
+class KAction;
+class QDropEvent;
+class QKeyEvent;
+class QFocusEvent;
+class QMouseEvent;
+class QDragMoveEvent;
+class QTimer;
+class KPopupMenu;
+class QPainter;
+class K3bListViewItemAnimator;
+class K3bAudioTrackPlayer;
+
+
+class K3bAudioTrackView : public K3bListView
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioTrackView( K3bAudioDoc*, QWidget* parent, const char* name = 0 );
+ ~K3bAudioTrackView();
+
+ KActionCollection* actionCollection() const { return m_actionCollection; }
+
+ K3bAudioTrackPlayer* player() const { return m_player; }
+
+ void getSelectedItems( QPtrList<K3bAudioTrack>& tracks,
+ QPtrList<K3bAudioDataSource>& sources );
+
+ public slots:
+ void showPlayerIndicator( K3bAudioTrack* );
+ void togglePauseIndicator( bool b );
+ void removePlayerIndicator();
+
+ private:
+ void setupColumns();
+ void setupActions();
+ void showAllSources();
+ K3bAudioTrackViewItem* findTrackItem( const QPoint& pos ) const;
+ K3bAudioTrackViewItem* getTrackViewItem( K3bAudioTrack* track, bool* isNew = 0 );
+
+ K3bAudioDoc* m_doc;
+
+ KAction* m_actionProperties;
+ KAction* m_actionRemove;
+ KAction* m_actionAddSilence;
+ KAction* m_actionMergeTracks;
+ KAction* m_actionSplitSource;
+ KAction* m_actionSplitTrack;
+ KAction* m_actionEditSource;
+ KAction* m_actionPlayTrack;
+ KActionCollection* m_actionCollection;
+
+ bool m_updatingColumnWidths;
+
+ QMap<K3bAudioTrack*, K3bAudioTrackViewItem*> m_trackItemMap;
+
+ K3bAudioTrackViewItem* m_currentMouseOverItem;
+ QTimer* m_autoOpenTrackTimer;
+ QTimer* m_animationTimer;
+
+ KPopupMenu* m_popupMenu;
+
+ K3bAudioTrackPlayer* m_player;
+
+ // used for the audiotrackplayer indicator
+ K3bAudioTrack* m_currentlyPlayingTrack;
+
+ // to animate the player icon
+ K3bListViewItemAnimator* m_playerItemAnimator;
+
+ // used for the drop-event hack
+ KURL::List m_dropUrls;
+ K3bAudioTrack* m_dropTrackAfter;
+ K3bAudioTrack* m_dropTrackParent;
+ K3bAudioDataSource* m_dropSourceAfter;
+
+ private slots:
+ void slotAnimation();
+ void slotDropped( QDropEvent* e, QListViewItem* parent, QListViewItem* after );
+ void slotChanged();
+ void slotTrackChanged( K3bAudioTrack* );
+ void slotTrackRemoved( K3bAudioTrack* );
+ void slotDragTimeout();
+
+ // action slots
+ void slotAddSilence();
+ void slotRemove();
+ void slotMergeTracks();
+ void slotSplitSource();
+ void slotSplitTrack();
+ void showPopupMenu( KListView*, QListViewItem* item, const QPoint& pos );
+ void slotProperties();
+ void slotPlayTrack();
+ void slotQueryMusicBrainz();
+ void slotEditSource();
+
+ // drop-event hack slot
+ void slotAddUrls();
+
+ protected:
+ void keyPressEvent( QKeyEvent* e );
+ void keyReleaseEvent( QKeyEvent* e );
+ void focusOutEvent( QFocusEvent* e );
+ void contentsMouseMoveEvent( QMouseEvent* e );
+ void contentsDragMoveEvent( QDragMoveEvent* e );
+ void contentsDragLeaveEvent( QDragLeaveEvent* e );
+ void resizeEvent( QResizeEvent* e );
+ void resizeColumns();
+ bool acceptDrag(QDropEvent* e) const;
+ QDragObject* dragObject();
+};
+
+#endif
diff --git a/src/projects/k3baudiotrackviewitem.cpp b/src/projects/k3baudiotrackviewitem.cpp
new file mode 100644
index 0000000..6918e2a
--- /dev/null
+++ b/src/projects/k3baudiotrackviewitem.cpp
@@ -0,0 +1,229 @@
+/*
+ *
+ * $Id: k3baudiotrackviewitem.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiotrackviewitem.h"
+#include "k3baudiodatasourceviewitem.h"
+#include "k3baudiodatasource.h"
+#include "k3baudiotrackview.h"
+#include "k3baudiotrack.h"
+#include <k3bcdtextvalidator.h>
+
+#include <kiconloader.h>
+
+#include <qpainter.h>
+
+
+K3bAudioTrackViewItem::K3bAudioTrackViewItem( K3bAudioTrackView* parent,
+ K3bAudioTrackViewItem* after,
+ K3bAudioTrack* track )
+ : K3bListViewItem( parent, after ),
+ m_track( track ),
+ m_alreadyRemoved(false),
+ m_showingSources(false),
+ m_animationCounter(1)
+{
+ // columns
+ // 0 - No.
+ // 1 - Artist (CD-Text)
+ // 2 - Title (CD-Text)
+ // 3 - Type
+ // 4 - Pregap
+ // 5 - Length
+ // 6 - Filename
+
+ // animationIconNumber = 1;
+ setEditor( 1, LINE );
+ setEditor( 2, LINE );
+ setValidator( 1, new K3bCdTextValidator() );
+ setValidator( 2, validator(1) );
+
+ // setMarginVertical( 5 );
+
+ // italic type
+ QFont f(listView()->font());
+ f.setItalic( true );
+ setFont( 3, f );
+
+ // gray out filename
+ setForegroundColor( 5, listView()->palette().disabled().foreground() );
+
+ // smaller filename
+ f = listView()->font();
+ f.setPointSize( f.pointSize() - 2 );
+ setFont( 5, f );
+
+ updateSourceItems();
+}
+
+
+K3bAudioTrackViewItem::~K3bAudioTrackViewItem()
+{
+ delete validator(1);
+}
+
+
+void K3bAudioTrackViewItem::paintCell( QPainter* p, const QColorGroup& cg, int col, int width, int align )
+{
+ K3bListViewItem::paintCell( p, cg, col, width, align );
+
+ // draw the separator
+ if( listView()->firstChild() != this ) {
+ p->save();
+ // FIXME: modify the value from palette().disabled().foreground() to be lighter (or darker, depending on the background color )
+ p->setPen( Qt::lightGray );
+ p->drawLine( 0, 0, width, 0 );
+ p->restore();
+ }
+}
+
+
+void K3bAudioTrackViewItem::paintBranches( QPainter* p, const QColorGroup& cg, int w, int, int h )
+{
+ // we just want empty space
+ p->fillRect( QRect( 0, 0, w, h ), cg.base() );
+}
+
+
+QString K3bAudioTrackViewItem::text(int i) const
+{
+ // to avoid crashes when the track has been deleted and this viewitem is still around
+ if( m_alreadyRemoved )
+ return QString::null;
+
+ //
+ // We add two spaces after all strings (except the once renameable)
+ // to increase readability
+ //
+
+ switch( i )
+ {
+ case 0:
+ return QString::number( m_track->trackNumber() ).rightJustify( 2, ' ' );
+ case 1:
+ return m_track->performer();
+ case 2:
+ return m_track->title();
+ case 3:
+ if( m_showingSources )
+ return QString::null;
+ else
+ return m_track->firstSource()->type();
+ case 4:
+ return m_track->length().toString();
+ case 5:
+ if( m_showingSources )
+ return QString::null;
+ else
+ return m_track->firstSource()->sourceComment();
+ default:
+ return KListViewItem::text(i);
+ }
+}
+
+void K3bAudioTrackViewItem::setText( int col, const QString& text )
+{
+ //
+ // Stupid QListViewItem actually calls setText in paintCell. Thus, once a new item
+ // is created setText is called and in turn the doc is marked as modified since
+ // we call setArtist or setPerformer here! :(
+ //
+ // Quick fix: check if the field actually changed
+ //
+ if( col == 1 ) {
+ // this is the cd-text artist field
+ if( text != m_track->performer() )
+ m_track->setPerformer( text );
+ }
+ else if( col == 2 ) {
+ // this is the cd-text title field
+ if( text != m_track->title() )
+ m_track->setTitle( text );
+ }
+
+ KListViewItem::setText( col, text );
+}
+
+
+void K3bAudioTrackViewItem::showSources( bool show )
+{
+ setOpen(show);
+ m_showingSources = show;
+}
+
+
+void K3bAudioTrackViewItem::updateSourceItems()
+{
+ while( firstChild() )
+ delete firstChild();
+
+ K3bAudioDataSource* source = track()->firstSource();
+ K3bAudioDataSourceViewItem* sourceItem = 0;
+ while( source ) {
+ sourceItem = new K3bAudioDataSourceViewItem( this, sourceItem, source );
+ sourceItem->animate();
+ source = source->next();
+ }
+}
+
+
+bool K3bAudioTrackViewItem::animate()
+{
+ //
+ // We animate if one of the sources have length == 0
+ // otherwise we set the led
+ //
+ bool animate = false;
+ bool valid = true;
+ QListViewItem* item = firstChild();
+ while( item ) {
+ K3bAudioDataSourceViewItem* sourceItem = dynamic_cast<K3bAudioDataSourceViewItem*>( item );
+ animate = animate || sourceItem->animate();
+ valid = valid && sourceItem->source()->isValid();
+ item = item->nextSibling();
+ }
+ if( animate ) {
+ QString icon = QString( "kde%1" ).arg( m_animationCounter );
+ setPixmap( 4, SmallIcon( icon ) );
+ m_animationCounter++;
+ if ( m_animationCounter > 6 )
+ m_animationCounter = 1;
+ }
+ else {
+ // set status icon
+ setPixmap( 4, ( valid ? SmallIcon( "greenled" ) : SmallIcon( "redled" ) ) );
+ }
+ return animate;
+}
+
+
+void K3bAudioTrackViewItem::setSelected( bool s )
+{
+ K3bListViewItem::setSelected(s);
+
+ // we also select or unselect all source items
+ QListViewItem* item = firstChild();
+ while( item ) {
+ item->setSelected(s);
+ item = item->nextSibling();
+ }
+}
+
+
+void K3bAudioTrackViewItem::insertItem( QListViewItem* item )
+{
+ K3bListViewItem::insertItem( item );
+ if( isSelected() )
+ item->setSelected(true);
+}
diff --git a/src/projects/k3baudiotrackviewitem.h b/src/projects/k3baudiotrackviewitem.h
new file mode 100644
index 0000000..9eb6065
--- /dev/null
+++ b/src/projects/k3baudiotrackviewitem.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * $Id: k3baudiotrackviewitem.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_TRACK_VIEWITEM_H_
+#define _K3B_AUDIO_TRACK_VIEWITEM_H_
+
+#include <k3blistview.h>
+
+class K3bAudioTrackView;
+class K3bAudioTrack;
+
+
+class K3bAudioTrackViewItem : public K3bListViewItem
+{
+ public:
+ K3bAudioTrackViewItem( K3bAudioTrackView* parent,
+ K3bAudioTrackViewItem* after,
+ K3bAudioTrack* track );
+ ~K3bAudioTrackViewItem();
+
+ /**
+ * If one of the sources still have length 0 we animate.
+ */
+ bool animate();
+
+ K3bAudioTrack* track() const { return m_track; }
+
+ void updateSourceItems();
+ bool showingSources() const { return m_showingSources; }
+ void showSources( bool show );
+ void setText( int col, const QString& text );
+ QString text( int i ) const;
+
+ /**
+ * @reimpl
+ */
+ void setSelected( bool s );
+ /**
+ * @reimpl
+ */
+ void insertItem( QListViewItem* item );
+
+ void paintBranches( QPainter*, const QColorGroup &, int, int, int );
+ void paintCell( QPainter* p, const QColorGroup& cg, int col, int width, int align );
+
+ private:
+ K3bAudioTrack* m_track;
+ bool m_alreadyRemoved;
+ bool m_showingSources;
+
+ int m_animationCounter;
+};
+
+#endif
diff --git a/src/projects/k3baudiotrackwidget.cpp b/src/projects/k3baudiotrackwidget.cpp
new file mode 100644
index 0000000..a5a3971
--- /dev/null
+++ b/src/projects/k3baudiotrackwidget.cpp
@@ -0,0 +1,162 @@
+/*
+ *
+ * $Id: k3baudiotrackwidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiotrackwidget.h"
+#include "k3baudioeditorwidget.h"
+#include "k3baudiotrack.h"
+
+#include <k3bmsfedit.h>
+#include <k3bvalidators.h>
+#include <k3bcdtextvalidator.h>
+
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qwidgetstack.h>
+#include <qgroupbox.h>
+#include <qtabwidget.h>
+
+#include <klineedit.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+
+
+K3bAudioTrackWidget::K3bAudioTrackWidget( const QPtrList<K3bAudioTrack>& tracks,
+ QWidget* parent, const char* name )
+ : base_K3bAudioTrackWidget( parent, name ),
+ m_tracks(tracks)
+{
+ m_labelPostGap->setBuddy( m_editPostGap );
+
+ QToolTip::add( m_labelPostGap, QToolTip::textFor( m_editPostGap ) );
+ QWhatsThis::add( m_labelPostGap, QWhatsThis::textFor( m_editPostGap ) );
+
+ // no post-gap for the last track
+ m_editPostGap->setDisabled( tracks.count() == 1 && !tracks.getFirst()->next() );
+
+ K3bCdTextValidator* val = new K3bCdTextValidator( this );
+ m_editSongwriter->setValidator( val );
+ m_editArranger->setValidator( val );
+ m_editComposer->setValidator( val );
+ m_editMessage->setValidator( val );
+ m_editTitle->setValidator( val );
+ m_editPerformer->setValidator( val );
+ m_editIsrc->setValidator( K3bValidators::isrcValidator( this ) );
+
+ load();
+}
+
+
+K3bAudioTrackWidget::~K3bAudioTrackWidget()
+{
+}
+
+
+void K3bAudioTrackWidget::load()
+{
+ if( !m_tracks.isEmpty() ) {
+
+ K3bAudioTrack* track = m_tracks.first();
+
+ m_editPostGap->setMsfValue( track->postGap() );
+
+ m_editTitle->setText( track->title() );
+ m_editPerformer->setText( track->artist() );
+ m_editArranger->setText( track->arranger() );
+ m_editSongwriter->setText( track->songwriter() );
+ m_editComposer->setText( track->composer() );
+ m_editIsrc->setText( track->isrc() );
+ m_editMessage->setText( track->cdTextMessage() );
+
+ m_checkCopyPermitted->setChecked( !track->copyProtection() );
+ m_checkPreemphasis->setChecked( track->preEmp() );
+
+ // load CD-Text for all other tracks
+ for( track = m_tracks.next(); track != 0; track = m_tracks.next() ) {
+
+ // FIXME: handle different post-gaps
+ // m_editPostGap->setMsfValue( track->postGap() );
+
+ if( track->title() != m_editTitle->text() )
+ m_editTitle->setText( QString::null );
+
+ if( track->artist() != m_editPerformer->text() )
+ m_editPerformer->setText( QString::null );
+
+ if( track->arranger() != m_editArranger->text() )
+ m_editArranger->setText( QString::null );
+
+ if( track->songwriter() != m_editSongwriter->text() )
+ m_editSongwriter->setText( QString::null );
+
+ if( track->composer() != m_editComposer->text() )
+ m_editComposer->setText( QString::null );
+
+ if( track->isrc() != m_editIsrc->text() )
+ m_editIsrc->setText( QString::null );
+
+ if( track->cdTextMessage() != m_editMessage->text() )
+ m_editMessage->setText( QString::null );
+ }
+
+ if( m_tracks.count() > 1 ) {
+ m_checkCopyPermitted->setNoChange();
+ m_checkPreemphasis->setNoChange();
+ }
+ }
+
+ m_editTitle->setFocus();
+}
+
+
+void K3bAudioTrackWidget::save()
+{
+ // save CD-Text, preemphasis, and copy protection for all tracks. no problem
+ for( K3bAudioTrack* track = m_tracks.first(); track != 0; track = m_tracks.next() ) {
+
+ if( m_editTitle->isModified() )
+ track->setTitle( m_editTitle->text() );
+
+ if( m_editPerformer->isModified() )
+ track->setArtist( m_editPerformer->text() );
+
+ if( m_editArranger->isModified() )
+ track->setArranger( m_editArranger->text() );
+
+ if( m_editSongwriter->isModified() )
+ track->setSongwriter( m_editSongwriter->text() );
+
+ if( m_editComposer->isModified() )
+ track->setComposer( m_editComposer->text() );
+
+ if( m_editIsrc->isModified() )
+ track->setIsrc( m_editIsrc->text() );
+
+ if( m_editMessage->isModified() )
+ track->setCdTextMessage( m_editMessage->text() );
+
+ if( m_checkCopyPermitted->state() != QButton::NoChange )
+ track->setCopyProtection( !m_checkCopyPermitted->isChecked() );
+
+ if( m_checkPreemphasis->state() != QButton::NoChange )
+ track->setPreEmp( m_checkPreemphasis->isChecked() );
+
+ track->setIndex0( track->length() - m_editPostGap->msfValue() );
+ }
+}
+
+#include "k3baudiotrackwidget.moc"
diff --git a/src/projects/k3baudiotrackwidget.h b/src/projects/k3baudiotrackwidget.h
new file mode 100644
index 0000000..8f02fbb
--- /dev/null
+++ b/src/projects/k3baudiotrackwidget.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * $Id: k3baudiotrackwidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_TRACK_WIDGET_H_
+#define _K3B_AUDIO_TRACK_WIDGET_H_
+
+#include "base_k3baudiotrackwidget.h"
+
+#include <k3bmsf.h>
+
+#include <qptrlist.h>
+
+
+class K3bAudioTrack;
+
+
+/**
+ * This class is used internally by K3bAudioTrackDialog.
+ */
+class K3bAudioTrackWidget : public base_K3bAudioTrackWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioTrackWidget( const QPtrList<K3bAudioTrack>& tracks,
+ QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioTrackWidget();
+
+ public slots:
+ void save();
+ void load();
+
+ QPtrList<K3bAudioTrack> m_tracks;
+};
+
+#endif
diff --git a/src/projects/k3baudioview.cpp b/src/projects/k3baudioview.cpp
new file mode 100644
index 0000000..3cfe0c0
--- /dev/null
+++ b/src/projects/k3baudioview.cpp
@@ -0,0 +1,136 @@
+/*
+ *
+ * $Id: k3baudioview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3baudioview.h"
+#include "k3baudiotrackview.h"
+#include "k3baudioburndialog.h"
+#include "k3baudiotrackplayer.h"
+#include "k3baudioburndialog.h"
+#include "k3baudiotrackaddingdialog.h"
+#include <k3bapplication.h>
+
+#include <k3baudiodoc.h>
+#include <k3baudiotrack.h>
+#include <k3baudiofile.h>
+#include <k3bpluginmanager.h>
+
+// this is not here becasue of base_*.ui troubles
+#include "../rip/k3baudioprojectconvertingdialog.h"
+
+#include <k3bfillstatusdisplay.h>
+#include <k3bmsf.h>
+#include <k3btoolbox.h>
+#include <kactionclasses.h>
+#include <k3bprojectplugin.h>
+
+// QT-includes
+#include <qlayout.h>
+#include <qstring.h>
+
+// KDE-includes
+#include <klocale.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+
+
+K3bAudioView::K3bAudioView( K3bAudioDoc* pDoc, QWidget* parent, const char *name )
+ : K3bView( pDoc, parent, name )
+{
+ m_doc = pDoc;
+
+ m_songlist = new K3bAudioTrackView( m_doc, this );
+ setMainWidget( m_songlist );
+ fillStatusDisplay()->showTime();
+
+ // add button for the audio conversion
+ KAction* conversionAction = new KAction( i18n("Convert Tracks"), "redo", 0, this, SLOT(slotAudioConversion()),
+ actionCollection(), "project_audio_convert" );
+ conversionAction->setToolTip( i18n("Convert audio tracks to other audio formats." ) );
+
+ toolBox()->addButton( conversionAction );
+ toolBox()->addSeparator();
+
+ toolBox()->addButton( m_songlist->player()->action( K3bAudioTrackPlayer::ACTION_PLAY ) );
+ toolBox()->addButton( m_songlist->player()->action( K3bAudioTrackPlayer::ACTION_PAUSE ) );
+ toolBox()->addButton( m_songlist->player()->action( K3bAudioTrackPlayer::ACTION_STOP ) );
+ toolBox()->addSpacing();
+ toolBox()->addButton( m_songlist->player()->action( K3bAudioTrackPlayer::ACTION_PREV ) );
+ toolBox()->addButton( m_songlist->player()->action( K3bAudioTrackPlayer::ACTION_NEXT ) );
+ toolBox()->addSpacing();
+ toolBox()->addWidgetAction( static_cast<KWidgetAction*>(m_songlist->player()->action( K3bAudioTrackPlayer::ACTION_SEEK )) );
+ toolBox()->addSeparator();
+
+#ifdef HAVE_MUSICBRAINZ
+ kdDebug() << "(K3bAudioView) m_songlist->actionCollection()->actions().count() " << m_songlist->actionCollection()->actions().count() << endl;
+ toolBox()->addButton( m_songlist->actionCollection()->action( "project_audio_musicbrainz" ) );
+ toolBox()->addSeparator();
+#endif
+
+ addPluginButtons( K3bProjectPlugin::AUDIO_CD );
+
+ toolBox()->addStretch();
+
+ // this is just for testing (or not?)
+ // most likely every project type will have it's rc file in the future
+ // we only add the additional actions since K3bView already added the default actions
+ setXML( "<!DOCTYPE kpartgui SYSTEM \"kpartgui.dtd\">"
+ "<kpartgui name=\"k3bproject\" version=\"1\">"
+ "<MenuBar>"
+ " <Menu name=\"project\"><text>&amp;Project</text>"
+ " <Action name=\"project_audio_convert\"/>"
+#ifdef HAVE_MUSICBRAINZ
+ " <Action name=\"project_audio_musicbrainz\"/>"
+#endif
+ " </Menu>"
+ "</MenuBar>"
+ "</kpartgui>", true );
+}
+
+K3bAudioView::~K3bAudioView()
+{
+}
+
+
+void K3bAudioView::init()
+{
+ if( k3bcore->pluginManager()->plugins( "AudioDecoder" ).isEmpty() )
+ KMessageBox::error( this, i18n("No audio decoder plugins found. You will not be able to add any files "
+ "to the audio project!") );
+}
+
+
+K3bProjectBurnDialog* K3bAudioView::newBurnDialog( QWidget* parent, const char* name )
+{
+ return new K3bAudioBurnDialog( m_doc, parent, name, true );
+}
+
+
+void K3bAudioView::slotAudioConversion()
+{
+ K3bAudioProjectConvertingDialog dlg( m_doc, this );
+ dlg.exec();
+}
+
+
+void K3bAudioView::addUrls( const KURL::List& urls )
+{
+ K3bAudioTrackAddingDialog::addUrls( urls, m_doc, 0, 0, 0, this );
+}
+
+#include "k3baudioview.moc"
diff --git a/src/projects/k3baudioview.h b/src/projects/k3baudioview.h
new file mode 100644
index 0000000..99740a3
--- /dev/null
+++ b/src/projects/k3baudioview.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * $Id: k3baudioview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BAUDIOVIEW_H
+#define K3BAUDIOVIEW_H
+
+#include <k3bview.h>
+#include "k3baudiotrackview.h"
+
+#include <qstringlist.h>
+
+
+class K3bAudioDoc;
+class K3bAudioTrack;
+class K3bAudioTrackView;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bAudioView : public K3bView
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioView( K3bAudioDoc* pDoc, QWidget* parent, const char *name = 0 );
+ ~K3bAudioView();
+
+ K3bAudioTrackPlayer* player() const { return m_songlist->player(); }
+
+ public slots:
+ void addUrls( const KURL::List& );
+
+ protected:
+ K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ void init();
+
+ private slots:
+ void slotAudioConversion();
+
+ private:
+ K3bAudioDoc* m_doc;
+
+ K3bAudioTrackView* m_songlist;
+};
+
+#endif
diff --git a/src/projects/k3bbootimagedialog.cpp b/src/projects/k3bbootimagedialog.cpp
new file mode 100644
index 0000000..c311082
--- /dev/null
+++ b/src/projects/k3bbootimagedialog.cpp
@@ -0,0 +1,45 @@
+/*
+ *
+ * $Id: k3bbootimagedialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bbootimagedialog.h"
+#include "k3bbootimageview.h"
+
+#include <klocale.h>
+
+
+K3bBootImageDialog::K3bBootImageDialog( K3bDataDoc* doc,
+ QWidget* parent,
+ const char* name,
+ bool modal )
+ : KDialogBase( parent, name, modal, i18n("Boot Images"), Ok )
+{
+ m_bootImageView = new K3bBootImageView( doc, this );
+ setMainWidget( m_bootImageView );
+}
+
+
+K3bBootImageDialog::~K3bBootImageDialog()
+{
+}
+
+
+void K3bBootImageDialog::slotOk()
+{
+ // m_bootImageView->save();
+ done( Ok );
+}
+
+#include "k3bbootimagedialog.moc"
diff --git a/src/projects/k3bbootimagedialog.h b/src/projects/k3bbootimagedialog.h
new file mode 100644
index 0000000..161c4b5
--- /dev/null
+++ b/src/projects/k3bbootimagedialog.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * $Id: k3bbootimagedialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BBOOTIMAGE_DIALOG_H
+#define K3BBOOTIMAGE_DIALOG_H
+
+#include <kdialogbase.h>
+
+class K3bBootImageView;
+class K3bDataDoc;
+
+
+class K3bBootImageDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bBootImageDialog( K3bDataDoc*,
+ QWidget* parent = 0,
+ const char* name = 0,
+ bool modal = true );
+ ~K3bBootImageDialog();
+
+ private slots:
+ void slotOk();
+
+ private:
+ K3bBootImageView* m_bootImageView;
+};
+
+#endif
diff --git a/src/projects/k3bbootimageview.cpp b/src/projects/k3bbootimageview.cpp
new file mode 100644
index 0000000..22907df
--- /dev/null
+++ b/src/projects/k3bbootimageview.cpp
@@ -0,0 +1,273 @@
+/*
+ *
+ * $Id: k3bbootimageview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bbootimageview.h"
+
+#include "k3bdatadoc.h"
+#include "k3bbootitem.h"
+#include <k3bintvalidator.h>
+
+#include <klocale.h>
+#include <klistview.h>
+#include <kfiledialog.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+#include <qpushbutton.h>
+#include <qstring.h>
+#include <qgroupbox.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qregexp.h>
+
+
+
+class K3bBootImageView::PrivateBootImageViewItem : public KListViewItem
+{
+public:
+ PrivateBootImageViewItem( K3bBootItem* image, QListView* parent )
+ : KListViewItem( parent ),
+ m_image( image ) {
+
+ }
+
+ PrivateBootImageViewItem( K3bBootItem* image, QListView* parent, QListViewItem* after )
+ : KListViewItem( parent, after ),
+ m_image( image ) {
+
+ }
+
+ QString text( int col ) const {
+ if( col == 0 ) {
+ if( m_image->imageType() == K3bBootItem::FLOPPY )
+ return i18n("Floppy");
+ else if( m_image->imageType() == K3bBootItem::HARDDISK )
+ return i18n("Harddisk");
+ else
+ return i18n("None");
+ }
+ else if( col == 1 )
+ return QString( "%1 KB" ).arg( m_image->size()/1024 );
+ else if( col == 2 )
+ return m_image->localPath();
+ else
+ return QString::null;
+ }
+
+ K3bBootItem* bootImage() const { return m_image; }
+
+private:
+ K3bBootItem* m_image;
+};
+
+
+K3bBootImageView::K3bBootImageView( K3bDataDoc* doc, QWidget* parent, const char* name )
+ : base_K3bBootImageView( parent, name ),
+ m_doc(doc)
+{
+ connect( m_buttonNew, SIGNAL(clicked()),
+ this, SLOT(slotNewBootImage()) );
+ connect( m_buttonDelete, SIGNAL(clicked()),
+ this, SLOT(slotDeleteBootImage()) );
+ connect( m_buttonToggleOptions, SIGNAL(clicked()),
+ this, SLOT(slotToggleOptions()) );
+ connect( m_viewImages, SIGNAL(selectionChanged()),
+ this, SLOT(slotSelectionChanged()) );
+ connect( m_radioNoEmulation, SIGNAL(toggled(bool)),
+ this, SLOT(slotNoEmulationToggled(bool)) );
+
+ K3bIntValidator* v = new K3bIntValidator( this );
+ m_editLoadSegment->setValidator( v );
+ m_editLoadSize->setValidator( v );
+
+ updateBootImages();
+
+ showAdvancedOptions( false );
+ loadBootItemSettings(0);
+}
+
+K3bBootImageView::~K3bBootImageView()
+{
+}
+
+
+void K3bBootImageView::slotToggleOptions()
+{
+ showAdvancedOptions( !m_groupOptions->isVisible() );
+}
+
+
+void K3bBootImageView::showAdvancedOptions( bool show )
+{
+ if( show ) {
+ m_groupOptions->show();
+ m_buttonToggleOptions->setText( i18n("Hide Advanced Options") );
+ }
+ else {
+ m_groupOptions->hide();
+ m_buttonToggleOptions->setText( i18n("Show Advanced Options") );
+ }
+}
+
+
+void K3bBootImageView::slotNewBootImage()
+{
+ QString file = KFileDialog::getOpenFileName( QString::null, QString::null, this, i18n("Please Choose Boot Image") );
+ if( !file.isEmpty() ) {
+ KIO::filesize_t fsize = K3b::filesize( file );
+ int boottype = K3bBootItem::FLOPPY;
+ if( fsize != 1200*1024 &&
+ fsize != 1440*1024 &&
+ fsize != 2880*1024 ) {
+ switch( KMessageBox::warningYesNoCancel( this,
+ i18n("<p>The file you selected is not a floppy image (floppy images are "
+ "of size 1200 KB, 1440 KB, or 2880 KB). You may still use boot images "
+ "of other sizes by emulating a harddisk or disabling emulation completely. "
+ "<p>If you are not familiar with terms like 'harddisk emulation' you most "
+ "likely want to use a floppy image here. Floppy images can be created by "
+ "directly extracting them from a real floppy disk:"
+ "<pre>dd if=/dev/floppy of=/tmp/floppy.img</pre>"
+ "or by using one of the many boot floppy generators that can be found on "
+ "<a href=\"http://www.google.com/search?q=linux+boot+floppy&ie=UTF-8&oe=UTF-8\">the internet</a>."),
+ i18n("No Floppy image selected"),
+ i18n("Use harddisk emulation"),
+ i18n("Use no emulation"),
+ QString::null,
+ KMessageBox::AllowLink ) ) {
+ case KMessageBox::Yes:
+ boottype = K3bBootItem::HARDDISK;
+ break;
+ case KMessageBox::No:
+ boottype = K3bBootItem::NONE;
+ break;
+ default:
+ return;
+ }
+ }
+
+ m_doc->createBootItem( file )->setImageType( boottype );
+ updateBootImages();
+ }
+}
+
+
+void K3bBootImageView::slotDeleteBootImage()
+{
+ QListViewItem* item = m_viewImages->selectedItem();
+ if( item ) {
+ K3bBootItem* i = ((PrivateBootImageViewItem*)item)->bootImage();
+ delete item;
+ m_doc->removeItem( i );
+ }
+}
+
+
+void K3bBootImageView::slotSelectionChanged()
+{
+ QListViewItem* item = m_viewImages->selectedItem();
+ if( item )
+ loadBootItemSettings( ((PrivateBootImageViewItem*)item)->bootImage() );
+ else
+ loadBootItemSettings( 0 );
+}
+
+
+void K3bBootImageView::updateBootImages()
+{
+ m_viewImages->clear();
+ for( QPtrListIterator<K3bBootItem> it( m_doc->bootImages() ); it.current(); ++it ) {
+ (void)new PrivateBootImageViewItem( *it, m_viewImages,
+ m_viewImages->lastItem() );
+ }
+}
+
+
+void K3bBootImageView::loadBootItemSettings( K3bBootItem* item )
+{
+ // this is needed to prevent the slots to change stuff
+ m_loadingItem = true;
+
+ if( item ) {
+ m_groupOptions->setEnabled(true);
+ m_groupImageType->setEnabled(true);
+
+ m_checkNoBoot->setChecked( item->noBoot() );
+ m_checkInfoTable->setChecked( item->bootInfoTable() );
+ m_editLoadSegment->setText( "0x" + QString::number( item->loadSegment(), 16 ) );
+ m_editLoadSize->setText( "0x" + QString::number( item->loadSize(), 16 ) );
+
+ if( item->imageType() == K3bBootItem::FLOPPY )
+ m_radioFloppy->setChecked(true);
+ else if( item->imageType() == K3bBootItem::HARDDISK )
+ m_radioHarddisk->setChecked(true);
+ else
+ m_radioNoEmulation->setChecked(true);
+
+ // force floppy size
+ KIO::filesize_t fsize = K3b::filesize( item->localPath() );
+ m_radioFloppy->setDisabled( fsize != 1200*1024 &&
+ fsize != 1440*1024 &&
+ fsize != 2880*1024 );
+ }
+ else {
+ m_groupOptions->setEnabled(false);
+ m_groupImageType->setEnabled(false);
+ }
+
+ m_loadingItem = false;
+}
+
+
+void K3bBootImageView::slotOptionsChanged()
+{
+ if( !m_loadingItem ) {
+ QListViewItem* item = m_viewImages->selectedItem();
+ if( item ) {
+ K3bBootItem* i = ((PrivateBootImageViewItem*)item)->bootImage();
+
+ i->setNoBoot( m_checkNoBoot->isChecked() );
+ i->setBootInfoTable( m_checkInfoTable->isChecked() );
+
+ // TODO: create some class K3bIntEdit : public QLineEdit
+ bool ok = true;
+ i->setLoadSegment( K3bIntValidator::toInt( m_editLoadSegment->text(), &ok ) );
+ if( !ok )
+ kdDebug() << "(K3bBootImageView) parsing number failed: " << m_editLoadSegment->text().lower() << endl;
+ i->setLoadSize( K3bIntValidator::toInt( m_editLoadSize->text(), &ok ) );
+ if( !ok )
+ kdDebug() << "(K3bBootImageView) parsing number failed: " << m_editLoadSize->text().lower() << endl;
+
+ if( m_radioFloppy->isChecked() )
+ i->setImageType( K3bBootItem::FLOPPY );
+ else if( m_radioHarddisk->isChecked() )
+ i->setImageType( K3bBootItem::HARDDISK );
+ else
+ i->setImageType( K3bBootItem::NONE );
+ }
+ }
+}
+
+
+void K3bBootImageView::slotNoEmulationToggled( bool on )
+{
+ // it makes no sense to combine no emulation and no boot!
+ // the base_widget takes care of the disabling
+ if( on )
+ m_checkNoBoot->setChecked(false);
+}
+
+#include "k3bbootimageview.moc"
diff --git a/src/projects/k3bbootimageview.h b/src/projects/k3bbootimageview.h
new file mode 100644
index 0000000..cf41de1
--- /dev/null
+++ b/src/projects/k3bbootimageview.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * $Id: k3bbootimageview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_BOOTIMAGEVIEW_H
+#define K3B_BOOTIMAGEVIEW_H
+
+#include "base_k3bbootimageview.h"
+
+class K3bDataDoc;
+class K3bBootItem;
+
+
+class K3bBootImageView : public base_K3bBootImageView
+{
+ Q_OBJECT
+
+public:
+ K3bBootImageView( K3bDataDoc* doc, QWidget* parent = 0, const char* name = 0 );
+ ~K3bBootImageView();
+
+ private slots:
+ void slotNewBootImage();
+ void slotDeleteBootImage();
+ void slotToggleOptions();
+ void slotSelectionChanged();
+
+ /* reimplemeted from base_...*/
+ void slotOptionsChanged();
+
+ void slotNoEmulationToggled( bool );
+
+ private:
+ void updateBootImages();
+ void showAdvancedOptions( bool );
+ void loadBootItemSettings( K3bBootItem* );
+
+ class PrivateBootImageViewItem;
+
+ K3bDataDoc* m_doc;
+
+ bool m_loadingItem;
+};
+
+#endif
diff --git a/src/projects/k3bdataadvancedimagesettingswidget.cpp b/src/projects/k3bdataadvancedimagesettingswidget.cpp
new file mode 100644
index 0000000..ac24813
--- /dev/null
+++ b/src/projects/k3bdataadvancedimagesettingswidget.cpp
@@ -0,0 +1,352 @@
+/*
+ *
+ * $Id: k3bdataadvancedimagesettingswidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdataadvancedimagesettingswidget.h"
+
+#include "k3bisooptions.h"
+
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qheader.h>
+#include <qwhatsthis.h>
+#include <qpoint.h>
+#include <qpainter.h>
+#include <qpalette.h>
+#include <qvalidator.h>
+#include <qregexp.h>
+
+#include <klistview.h>
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+
+static const char * mkisofsCharacterSets[] = { "cp10081",
+ "cp10079",
+ "cp10029",
+ "cp10007",
+ "cp10006",
+ "cp10000",
+ "koi8-u",
+ "koi8-r",
+ "cp1251",
+ "cp1250",
+ "cp874",
+ "cp869",
+ "cp866",
+ "cp865",
+ "cp864",
+ "cp863",
+ "cp862",
+ "cp861",
+ "cp860",
+ "cp857",
+ "cp855",
+ "cp852",
+ "cp850",
+ "cp775",
+ "cp737",
+ "cp437",
+ "iso8859-15",
+ "iso8859-14",
+ "iso8859-9",
+ "iso8859-8",
+ "iso8859-7",
+ "iso8859-6",
+ "iso8859-5",
+ "iso8859-4",
+ "iso8859-3",
+ "iso8859-2",
+ "iso8859-1",
+ 0 }; // terminating zero
+
+
+
+class K3bDataAdvancedImageSettingsWidget::PrivateIsoWhatsThis : public QWhatsThis
+{
+public:
+ PrivateIsoWhatsThis( K3bDataAdvancedImageSettingsWidget* w )
+ : QWhatsThis( w->m_viewIsoSettings->viewport() ) {
+ this->w = w;
+ }
+
+ QString text( const QPoint& p ) {
+ QListViewItem* i = w->m_viewIsoSettings->selectedItem(); // dies funktioniert nur bei rechtsklick
+ QListViewItem* i2 = w->m_viewIsoSettings->itemAt( p ); // dies funktioniert nur bei action whatsthis
+
+ if( i2 != 0 )
+ kdDebug() << "at p " << i2->text(0) << endl;
+
+ if( i == w->m_checkAllowUntranslatedFilenames )
+ return i18n( "Force all options below" );
+ else if( i == w->m_radioIsoLevel1 ||
+ i == w->m_radioIsoLevel2 ||
+ i == w->m_radioIsoLevel3 ||
+ i == w->m_isoLevelController )
+ return i18n( "<p>Set the ISO-9660 conformance level.\n"
+ "<ul>\n"
+ "<li>Level 1: Files may only consist of one section and filenames are restricted "
+ "to 8.3 characters.</li>\n"
+ "<li>Level 2: Files may only consist of one section.</li>\n"
+ "<li>Level 3: No restrictions.</li>\n"
+ "</ul>\n"
+ "<p>With all ISO-9660 levels, all filenames are restricted to upper case letters, "
+ "numbers and the underscore (_). The maximum filename length is 31 characters, the "
+ "directory nesting level is restricted to 8 and the maximum path length is limited "
+ "to 255 characters. (These restrictions may be violated with the additional ISO-9660 K3b offers)." );
+ else
+ return i18n("Set special ISO9660 Filesystem preferences.");
+ }
+
+private:
+ K3bDataAdvancedImageSettingsWidget* w;
+};
+
+
+
+class K3bDataAdvancedImageSettingsWidget::PrivateCheckViewItem : public QCheckListItem
+{
+public:
+ PrivateCheckViewItem( QListView* parent, const QString& text, Type tt = Controller )
+ : QCheckListItem( parent, text, tt ) {
+ }
+
+ PrivateCheckViewItem( QListViewItem* parent, const QString& text, Type tt = Controller )
+ : QCheckListItem( parent, text, tt ) {
+ }
+
+protected:
+ void stateChange( bool on ) {
+ // enable or disable all children
+ QListViewItem* item = firstChild();
+ while( item ) {
+ if( PrivateCheckViewItem* pi = dynamic_cast<PrivateCheckViewItem*>(item) )
+ pi->setEnabled( !on );
+ item = item->nextSibling();
+ }
+ }
+};
+
+
+K3bDataAdvancedImageSettingsWidget::K3bDataAdvancedImageSettingsWidget( QWidget* parent, const char* name )
+ : base_K3bAdvancedDataImageSettings( parent, name )
+{
+ m_viewIsoSettings->header()->hide();
+ m_viewIsoSettings->setSorting( -1 );
+
+ // create WhatsThis for the isoSettings view
+ (void)new PrivateIsoWhatsThis( this );
+
+ // create all the view items
+ QCheckListItem* iso9660Root = new QCheckListItem( m_viewIsoSettings,
+ i18n("IS09660 Settings"),
+ QCheckListItem::Controller );
+ QCheckListItem* rrRoot = new QCheckListItem( m_viewIsoSettings,
+ iso9660Root,
+ i18n("Rock Ridge Settings"),
+ QCheckListItem::Controller );
+ QCheckListItem* jolietRoot = new QCheckListItem( m_viewIsoSettings,
+ rrRoot,
+ i18n("Joliet Settings"),
+ QCheckListItem::Controller );
+ QCheckListItem* miscRoot = new QCheckListItem( m_viewIsoSettings,
+ jolietRoot,
+ i18n("Misc Settings"),
+ QCheckListItem::Controller );
+
+ // ISO9660 settings
+ m_checkAllowUntranslatedFilenames = new PrivateCheckViewItem( iso9660Root,
+ i18n( "Allow untranslated ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkAllowMaxLengthFilenames = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Allow max length ISO9660 filenames (37 characters)" ),
+ QCheckListItem::CheckBox );
+ m_checkAllowFullAscii = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Allow full ASCII charset for ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkAllowOther = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Allow ~ and # in ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkAllowLowercaseCharacters = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Allow lowercase characters in ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkAllowMultiDot = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Allow multiple dots in ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkAllow31CharFilenames = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Allow 31 character ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkAllowBeginningPeriod = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Allow leading period in ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkOmitVersionNumbers = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Omit version numbers in ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+ m_checkOmitTrailingPeriod = new PrivateCheckViewItem( m_checkAllowUntranslatedFilenames,
+ i18n( "Omit trailing period in ISO9660 filenames" ),
+ QCheckListItem::CheckBox );
+
+ m_checkAllowUntranslatedFilenames->setOpen(true);
+ m_isoLevelController = new QCheckListItem( iso9660Root,
+ m_checkAllowUntranslatedFilenames,
+ i18n("ISO Level") );
+
+ m_radioIsoLevel3 = new QCheckListItem( m_isoLevelController,
+ i18n("Level %1").arg(3),
+ QCheckListItem::RadioButton );
+ m_radioIsoLevel2 = new QCheckListItem( m_isoLevelController,
+ i18n("Level %1").arg(2),
+ QCheckListItem::RadioButton );
+ m_radioIsoLevel1 = new QCheckListItem( m_isoLevelController,
+ i18n("Level %1").arg(1),
+ QCheckListItem::RadioButton );
+
+ m_isoLevelController->setOpen(true);
+
+ // Joliet Settings
+ m_checkJolietLong = new QCheckListItem( jolietRoot,
+ i18n("Allow 103 character Joliet filenames"),
+ QCheckListItem::CheckBox );
+
+ // Rock Ridge Settings
+ m_checkCreateTransTbl = new QCheckListItem( rrRoot,
+ i18n( "Create TRANS.TBL files" ),
+ QCheckListItem::CheckBox );
+ m_checkHideTransTbl = new QCheckListItem( rrRoot, m_checkCreateTransTbl,
+ i18n( "Hide TRANS.TBL files in Joliet" ),
+ QCheckListItem::CheckBox );
+
+ // Misc Settings
+// m_checkFollowSymbolicLinks = new QCheckListItem( m_viewIsoSettings,
+// i18n( "Follow symbolic links" ),
+// QCheckListItem::CheckBox );
+
+ m_checkDoNotCacheInodes = new QCheckListItem( miscRoot,
+ i18n("Do not cache inodes" ),
+ QCheckListItem::CheckBox );
+
+ iso9660Root->setOpen( true );
+ jolietRoot->setOpen( true );
+ rrRoot->setOpen( true );
+ miscRoot->setOpen( true );
+
+
+ m_comboInputCharset->setValidator( new QRegExpValidator( QRegExp("[\\w_-]*"), this ) );
+
+ // fill charset combo
+ for( int i = 0; mkisofsCharacterSets[i]; i++ ) {
+ m_comboInputCharset->insertItem( QString( mkisofsCharacterSets[i] ) );
+ }
+
+ connect( m_checkJoliet, SIGNAL(toggled(bool)), this, SLOT(slotJolietToggled(bool)) );
+}
+
+
+K3bDataAdvancedImageSettingsWidget::~K3bDataAdvancedImageSettingsWidget()
+{
+}
+
+
+void K3bDataAdvancedImageSettingsWidget::load( const K3bIsoOptions& o )
+{
+ m_checkRockRidge->setChecked( o.createRockRidge() );
+ m_checkJoliet->setChecked( o.createJoliet() );
+ m_checkUdf->setChecked( o.createUdf() );
+
+ switch( o.ISOLevel() ) {
+ case 1:
+ m_radioIsoLevel1->setOn(true);
+ break;
+ case 2:
+ m_radioIsoLevel2->setOn(true);
+ break;
+ case 3:
+ m_radioIsoLevel3->setOn(true);
+ break;
+ }
+
+ m_checkForceInputCharset->setChecked( o.forceInputCharset() );
+ m_comboInputCharset->setEditText( o.inputCharset() );
+ m_checkPreservePermissions->setChecked( o.preserveFilePermissions() );
+
+ // RR settings
+ m_checkCreateTransTbl->setOn( o.createTRANS_TBL() );
+ m_checkHideTransTbl->setOn( o.hideTRANS_TBL() );
+
+ // iso9660 settings
+ m_checkAllowUntranslatedFilenames->setOn( o.ISOuntranslatedFilenames() );
+ m_checkAllow31CharFilenames->setOn( o.ISOallow31charFilenames() );
+ m_checkAllowMaxLengthFilenames->setOn( o.ISOmaxFilenameLength() );
+ m_checkAllowBeginningPeriod->setOn( o.ISOallowPeriodAtBegin() );
+ m_checkAllowFullAscii->setOn( o.ISOrelaxedFilenames() );
+ m_checkOmitVersionNumbers->setOn( o.ISOomitVersionNumbers() );
+ m_checkOmitTrailingPeriod->setOn( o.ISOomitTrailingPeriod() );
+ m_checkAllowOther->setOn( o.ISOnoIsoTranslate() );
+ m_checkAllowMultiDot->setOn( o.ISOallowMultiDot() );
+ m_checkAllowLowercaseCharacters->setOn( o.ISOallowLowercase() );
+
+ // joliet settings
+ m_checkJolietLong->setOn( o.jolietLong() );
+
+ // misc (FIXME: should not be here)
+ m_checkDoNotCacheInodes->setOn( o.doNotCacheInodes() );
+
+ slotJolietToggled( m_checkJoliet->isChecked() );
+}
+
+
+void K3bDataAdvancedImageSettingsWidget::save( K3bIsoOptions& o )
+{
+ o.setCreateRockRidge( m_checkRockRidge->isChecked() );
+ o.setCreateJoliet( m_checkJoliet->isChecked() );
+ o.setCreateUdf( m_checkUdf->isChecked() );
+
+ // save iso-level
+ if( m_radioIsoLevel3->isOn() )
+ o.setISOLevel( 3 );
+ else if( m_radioIsoLevel2->isOn() )
+ o.setISOLevel( 2 );
+ else
+ o.setISOLevel( 1 );
+
+ o.setForceInputCharset( m_checkForceInputCharset->isChecked() );
+ o.setInputCharset( m_comboInputCharset->currentText() );
+ o.setPreserveFilePermissions( m_checkPreservePermissions->isChecked() );
+
+ o.setCreateTRANS_TBL( m_checkCreateTransTbl->isOn() );
+ o.setHideTRANS_TBL( m_checkHideTransTbl->isOn() );
+ o.setISOuntranslatedFilenames( m_checkAllowUntranslatedFilenames->isOn() );
+ o.setISOallow31charFilenames( m_checkAllow31CharFilenames->isOn() );
+ o.setISOmaxFilenameLength( m_checkAllowMaxLengthFilenames->isOn() );
+ o.setISOallowPeriodAtBegin( m_checkAllowBeginningPeriod->isOn() );
+ o.setISOrelaxedFilenames( m_checkAllowFullAscii->isOn() );
+ o.setISOomitVersionNumbers( m_checkOmitVersionNumbers->isOn() );
+ o.setISOomitTrailingPeriod( m_checkOmitTrailingPeriod->isOn() );
+ o.setISOnoIsoTranslate( m_checkAllowOther->isOn() );
+ o.setISOallowMultiDot( m_checkAllowMultiDot->isOn() );
+ o.setISOallowLowercase( m_checkAllowLowercaseCharacters->isOn() );
+ // o.setFollowSymbolicLinks( m_checkFollowSymbolicLinks->isOn() );
+ o.setJolietLong( m_checkJolietLong->isOn() );
+ o.setDoNotCacheInodes( m_checkDoNotCacheInodes->isOn() );
+}
+
+
+void K3bDataAdvancedImageSettingsWidget::slotJolietToggled( bool on )
+{
+ m_checkJolietLong->setEnabled( on );
+}
+
+#include "k3bdataadvancedimagesettingswidget.moc"
diff --git a/src/projects/k3bdataadvancedimagesettingswidget.h b/src/projects/k3bdataadvancedimagesettingswidget.h
new file mode 100644
index 0000000..eb442e3
--- /dev/null
+++ b/src/projects/k3bdataadvancedimagesettingswidget.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * $Id: k3bdataadvancedimagesettingswidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3B_DATA_ADVANCED_IMAGE_SETTINGS_WIDGET_H
+#define K3B_DATA_ADVANCED_IMAGE_SETTINGS_WIDGET_H
+
+
+#include "base_k3badvanceddataimagesettings.h"
+
+class K3bIsoOptions;
+class QCheckListItem;
+
+
+class K3bDataAdvancedImageSettingsWidget : public base_K3bAdvancedDataImageSettings
+{
+ Q_OBJECT
+
+ public:
+ K3bDataAdvancedImageSettingsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bDataAdvancedImageSettingsWidget();
+
+ void load( const K3bIsoOptions& );
+ void save( K3bIsoOptions& );
+
+ private slots:
+ void slotJolietToggled( bool on );
+
+ private:
+ QCheckListItem* m_checkAllowUntranslatedFilenames;
+ QCheckListItem* m_checkAllowMaxLengthFilenames;
+ QCheckListItem* m_checkAllowFullAscii;
+ QCheckListItem* m_checkAllowOther;
+ QCheckListItem* m_checkAllowLowercaseCharacters;
+ QCheckListItem* m_checkAllowMultiDot;
+ QCheckListItem* m_checkOmitVersionNumbers;
+ QCheckListItem* m_checkOmitTrailingPeriod;
+ QCheckListItem* m_checkCreateTransTbl;
+ QCheckListItem* m_checkHideTransTbl;
+ QCheckListItem* m_checkFollowSymbolicLinks;
+ QCheckListItem* m_checkAllow31CharFilenames;
+ QCheckListItem* m_checkAllowBeginningPeriod;
+ QCheckListItem* m_checkJolietLong;
+ QCheckListItem* m_checkDoNotCacheInodes;
+
+ QCheckListItem* m_isoLevelController;
+ QCheckListItem* m_radioIsoLevel1;
+ QCheckListItem* m_radioIsoLevel2;
+ QCheckListItem* m_radioIsoLevel3;
+
+ class PrivateCheckViewItem;
+ class PrivateIsoWhatsThis;
+
+ friend class PrivateIsoWhatsThis;
+};
+
+
+#endif
diff --git a/src/projects/k3bdataburndialog.cpp b/src/projects/k3bdataburndialog.cpp
new file mode 100644
index 0000000..d920fd4
--- /dev/null
+++ b/src/projects/k3bdataburndialog.cpp
@@ -0,0 +1,289 @@
+/*
+ *
+ * $Id: k3bdataburndialog.cpp 690207 2007-07-20 10:40:19Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdataburndialog.h"
+#include "k3bdataimagesettingswidget.h"
+#include "k3bdatavolumedescwidget.h"
+#include "k3bdatamultisessioncombobox.h"
+#include "k3bdataview.h"
+
+#include <k3bisooptions.h>
+#include <k3bdatadoc.h>
+#include <k3bdevice.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bjob.h>
+#include <k3bcore.h>
+#include <k3bstdguiitems.h>
+#include <k3bdatamodewidget.h>
+#include <k3bglobals.h>
+#include <k3bwritingmodewidget.h>
+
+#include <qcheckbox.h>
+#include <qframe.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qpoint.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qfileinfo.h>
+#include <qtabwidget.h>
+#include <qspinbox.h>
+#include <qfile.h>
+
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kfiledialog.h>
+#include <kcombobox.h>
+#include <kio/global.h>
+
+
+#include "k3bfilecompilationsizehandler.h"
+
+
+K3bDataBurnDialog::K3bDataBurnDialog(K3bDataDoc* _doc, QWidget *parent, const char *name, bool modal )
+ : K3bProjectBurnDialog( _doc, parent, name, modal )
+{
+ prepareGui();
+
+ setTitle( i18n("Data Project"), i18n("Size: %1").arg( KIO::convertSize(_doc->size()) ) );
+
+ // for now we just put the verify checkbox on the main page...
+ m_checkVerify = K3bStdGuiItems::verifyCheckBox( m_optionGroup );
+ m_optionGroupLayout->addWidget( m_checkVerify );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ // create image settings tab
+ m_imageSettingsWidget = new K3bDataImageSettingsWidget( this );
+ addPage( m_imageSettingsWidget, i18n("Filesystem") );
+
+ setupSettingsTab();
+
+ connect( m_comboMultisession, SIGNAL(activated(int)),
+ this, SLOT(slotMultiSessionModeChanged()) );
+
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY|K3bDevice::STATE_INCOMPLETE );
+
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+ QString path = _doc->tempDir();
+ if( !path.isEmpty() ) {
+ m_tempDirSelectionWidget->setTempPath( path );
+ }
+ if( !_doc->isoOptions().volumeID().isEmpty() ) {
+ m_tempDirSelectionWidget->setDefaultImageFileName( _doc->isoOptions().volumeID() + ".iso" );
+ }
+
+ connect( m_imageSettingsWidget->m_editVolumeName, SIGNAL(textChanged(const QString&)),
+ m_tempDirSelectionWidget, SLOT(setDefaultImageFileName(const QString&)) );
+}
+
+K3bDataBurnDialog::~K3bDataBurnDialog()
+{
+}
+
+
+void K3bDataBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ // save iso image settings
+ K3bIsoOptions o = ((K3bDataDoc*)doc())->isoOptions();
+ m_imageSettingsWidget->save( o );
+ ((K3bDataDoc*)doc())->setIsoOptions( o );
+
+ // save image file path
+ ((K3bDataDoc*)doc())->setTempDir( m_tempDirSelectionWidget->tempPath() );
+
+ // save multisession settings
+ ((K3bDataDoc*)doc())->setMultiSessionMode( m_comboMultisession->multiSessionMode() );
+
+ ((K3bDataDoc*)doc())->setDataMode( m_dataModeWidget->dataMode() );
+
+ ((K3bDataDoc*)doc())->setVerifyData( m_checkVerify->isChecked() );
+}
+
+
+void K3bDataBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ // read multisession
+ m_comboMultisession->setMultiSessionMode( ((K3bDataDoc*)doc())->multiSessionMode() );
+
+ if( !doc()->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( doc()->tempDir() );
+ else
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() + doc()->name() + ".iso" );
+
+ m_checkVerify->setChecked( ((K3bDataDoc*)doc())->verifyData() );
+
+ m_imageSettingsWidget->load( ((K3bDataDoc*)doc())->isoOptions() );
+
+ m_dataModeWidget->setDataMode( ((K3bDataDoc*)doc())->dataMode() );
+
+ toggleAll();
+}
+
+
+void K3bDataBurnDialog::setupSettingsTab()
+{
+ QWidget* frame = new QWidget( this );
+ QGridLayout* frameLayout = new QGridLayout( frame );
+ frameLayout->setSpacing( spacingHint() );
+ frameLayout->setMargin( marginHint() );
+
+ m_groupDataMode = new QGroupBox( 1, Qt::Vertical, i18n("Datatrack Mode"), frame );
+ m_dataModeWidget = new K3bDataModeWidget( m_groupDataMode );
+
+ QGroupBox* groupMultiSession = new QGroupBox( 1, Qt::Vertical, i18n("Multisession Mode"), frame );
+ m_comboMultisession = new K3bDataMultiSessionCombobox( groupMultiSession );
+
+ frameLayout->addWidget( m_groupDataMode, 0, 0 );
+ frameLayout->addWidget( groupMultiSession, 1, 0 );
+ frameLayout->setRowStretch( 2, 1 );
+
+ addPage( frame, i18n("Misc") );
+}
+
+
+void K3bDataBurnDialog::slotStartClicked()
+{
+ if( m_checkOnlyCreateImage->isChecked() ||
+ m_checkCacheImage->isChecked() ) {
+ QFileInfo fi( m_tempDirSelectionWidget->tempPath() );
+ if( fi.isDir() )
+ m_tempDirSelectionWidget->setTempPath( fi.filePath() + "/image.iso" );
+
+ if( QFile::exists( m_tempDirSelectionWidget->tempPath() ) ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(m_tempDirSelectionWidget->tempPath()),
+ i18n("File Exists"), i18n("Overwrite") )
+ == KMessageBox::Continue ) {
+ // delete the file here to avoid problems with free space in K3bProjectBurnDialog::slotStartClicked
+ QFile::remove( m_tempDirSelectionWidget->tempPath() );
+ }
+ else
+ return;
+ }
+ }
+
+ if( m_writingModeWidget->writingMode() == K3b::DAO &&
+ m_comboMultisession->multiSessionMode() != K3bDataDoc::NONE &&
+ m_writerSelectionWidget->writingApp() == K3b::CDRECORD )
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Most writers do not support writing "
+ "multisession CDs in DAO mode.") )
+ == KMessageBox::Cancel )
+ return;
+
+
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+
+void K3bDataBurnDialog::loadK3bDefaults()
+{
+ K3bProjectBurnDialog::loadK3bDefaults();
+
+ m_dataModeWidget->setDataMode( K3b::DATA_MODE_AUTO );
+
+ m_imageSettingsWidget->load( K3bIsoOptions::defaults() );
+ m_comboMultisession->setMultiSessionMode( K3bDataDoc::AUTO );
+ m_checkVerify->setChecked( false );
+
+ toggleAll();
+}
+
+
+void K3bDataBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults(c);
+
+ m_dataModeWidget->loadConfig(c);
+ m_comboMultisession->loadConfig( c );
+
+ K3bIsoOptions o = K3bIsoOptions::load( c );
+ m_imageSettingsWidget->load( o );
+
+ m_checkVerify->setChecked( c->readBoolEntry( "verify data", false ) );
+
+ toggleAll();
+}
+
+
+void K3bDataBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults(c);
+
+ m_dataModeWidget->saveConfig(c);
+ m_comboMultisession->saveConfig( c );
+
+ K3bIsoOptions o;
+ m_imageSettingsWidget->save( o );
+ o.save( c );
+
+ c->writeEntry( "verify data", m_checkVerify->isChecked() );
+}
+
+
+void K3bDataBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ if( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() ) {
+ m_checkVerify->setChecked(false);
+ m_checkVerify->setEnabled(false);
+ }
+ else
+ m_checkVerify->setEnabled(true);
+
+ m_comboMultisession->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_dataModeWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+}
+
+
+void K3bDataBurnDialog::slotMultiSessionModeChanged()
+{
+ if( m_comboMultisession->multiSessionMode() == K3bDataDoc::CONTINUE ||
+ m_comboMultisession->multiSessionMode() == K3bDataDoc::FINISH )
+ m_spinCopies->setEnabled(false);
+
+ // wait for the proper medium
+ // we have to do this in another slot than toggleAll to avoid an endless loop
+ // FIXME: K3bInteractionDialog::slotToggleAll is endless loop protected
+ if( m_comboMultisession->multiSessionMode() == K3bDataDoc::NONE )
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY );
+ else if( m_comboMultisession->multiSessionMode() == K3bDataDoc::CONTINUE ||
+ m_comboMultisession->multiSessionMode() == K3bDataDoc::FINISH )
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_INCOMPLETE );
+ else
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY|K3bDevice::STATE_INCOMPLETE );
+}
+
+
+#include "k3bdataburndialog.moc"
diff --git a/src/projects/k3bdataburndialog.h b/src/projects/k3bdataburndialog.h
new file mode 100644
index 0000000..1d1e994
--- /dev/null
+++ b/src/projects/k3bdataburndialog.h
@@ -0,0 +1,75 @@
+/*
+ *
+ * $Id: k3bdataburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDATABURNDIALOG_H
+#define K3BDATABURNDIALOG_H
+
+#include "k3bprojectburndialog.h"
+
+class QCheckBox;
+class KComboBox;
+class QGroupBox;
+class QLabel;
+class QToolButton;
+class QRadioButton;
+class QButtonGroup;
+class K3bWriterSelectionWidget;
+class K3bTempDirSelectionWidget;
+class K3bDataDoc;
+class KLineEdit;
+class K3bDataImageSettingsWidget;
+class K3bDataModeWidget;
+class K3bDataMultiSessionCombobox;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+
+class K3bDataBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bDataBurnDialog(K3bDataDoc*, QWidget *parent=0, const char *name=0, bool modal = true );
+ ~K3bDataBurnDialog();
+
+ protected:
+ void setupSettingsTab();
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void toggleAll();
+
+ // --- settings tab ---------------------------
+ K3bDataImageSettingsWidget* m_imageSettingsWidget;
+ // ----------------------------------------------
+
+ QGroupBox* m_groupDataMode;
+ K3bDataModeWidget* m_dataModeWidget;
+ K3bDataMultiSessionCombobox* m_comboMultisession;
+
+ QCheckBox* m_checkVerify;
+
+ protected slots:
+ void slotStartClicked();
+ void saveSettings();
+ void readSettings();
+
+ void slotMultiSessionModeChanged();
+};
+
+#endif
diff --git a/src/projects/k3bdatadirtreeview.cpp b/src/projects/k3bdatadirtreeview.cpp
new file mode 100644
index 0000000..4a7ec18
--- /dev/null
+++ b/src/projects/k3bdatadirtreeview.cpp
@@ -0,0 +1,506 @@
+/*
+ *
+ * $Id: k3bdatadirtreeview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdatadirtreeview.h"
+#include "k3bdatafileview.h"
+#include "k3bdataview.h"
+#include "k3bdatadoc.h"
+#include "k3bdataitem.h"
+#include "k3bdiritem.h"
+#include "k3bdatapropertiesdialog.h"
+#include "k3bdataviewitem.h"
+#include "k3bdataurladdingdialog.h"
+#include <k3bview.h>
+#include <k3bvalidators.h>
+
+#include <qdragobject.h>
+#include <qheader.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kurldrag.h>
+#include <kinputdialog.h>
+#include <kiconloader.h>
+#include <kshortcut.h>
+
+#include <kdebug.h>
+
+
+class K3bDataDirTreeView::Private
+{
+public:
+ Private()
+ : animatedDirItem(0),
+ dropDirItem(0) {
+ }
+
+ K3bDataDirViewItem* animatedDirItem;
+ K3bDataDirViewItem* dropDirItem;
+ int animationCounter;
+ QPixmap beforeAniPixmap;
+
+ // used for the urladdingdialog hack
+ KURL::List addUrls;
+ K3bDirItem* addParentDir;
+
+ QString lastUpdateVolumeId;
+
+ QValidator* iso9660Validator;
+ QValidator* asciiValidator;
+};
+
+
+K3bDataDirTreeView::K3bDataDirTreeView( K3bView* view, K3bDataDoc* doc, QWidget* parent )
+ : K3bListView( parent ), m_view(view)
+{
+ d = new Private();
+
+ m_fileView = 0;
+
+ setAcceptDrops( true );
+ setDropVisualizer( false );
+ setDropHighlighter( true );
+ setRootIsDecorated( false );
+ setFullWidth( true );
+ setDragEnabled( true );
+ setItemsMovable( false );
+ setAlternateBackground( QColor() );
+ // setSorting(-1);
+
+ addColumn( i18n("Directory") );
+ header()->hide();
+
+ m_doc = doc;
+
+ m_root = new K3bDataRootViewItem( doc, this );
+ m_itemMap.insert( doc->root(), m_root );
+
+ connect( m_doc, SIGNAL(changed()), this, SLOT(slotDocChanged()) );
+ connect( this, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotExecuted(QListViewItem*)) );
+ connect( this, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotExecuted(QListViewItem*)) );
+ connect( m_doc, SIGNAL(itemRemoved(K3bDataItem*)), this, SLOT(slotDataItemRemoved(K3bDataItem*)) );
+ connect( m_doc, SIGNAL(itemAdded(K3bDataItem*)), this, SLOT(slotItemAdded(K3bDataItem*)) );
+ connect( this, SIGNAL(contextMenu(KListView*,QListViewItem*, const QPoint&)),
+ this, SLOT(showPopupMenu(KListView*,QListViewItem*, const QPoint&)) );
+ connect( this, SIGNAL(dropped(QDropEvent*, QListViewItem*, QListViewItem*)),
+ this, SLOT(slotDropped(QDropEvent*, QListViewItem*, QListViewItem*)) );
+
+ setupActions();
+}
+
+
+K3bDataDirTreeView::~K3bDataDirTreeView()
+{
+ delete d;
+}
+
+
+void K3bDataDirTreeView::slotExecuted( QListViewItem* item )
+{
+ if( K3bDataDirViewItem* viewItem = dynamic_cast<K3bDataDirViewItem*>(item) )
+ emit dirSelected( viewItem->dirItem() );
+}
+
+
+bool K3bDataDirTreeView::acceptDrag(QDropEvent* e) const{
+ return ( e->source() == viewport() || KURLDrag::canDecode(e) ||
+ ( m_fileView && e->source() == m_fileView->viewport() ) );
+}
+
+
+void K3bDataDirTreeView::contentsDragMoveEvent( QDragMoveEvent* e )
+{
+ K3bListView::contentsDragMoveEvent( e );
+
+ // highlight the folder the items would be added to
+ if( d->dropDirItem )
+ d->dropDirItem->highlightIcon( false );
+
+ d->dropDirItem = dynamic_cast<K3bDataDirViewItem*>( itemAt(contentsToViewport(e->pos())) );
+ if( !d->dropDirItem )
+ d->dropDirItem = m_root;
+
+ d->dropDirItem->highlightIcon( true );
+}
+
+
+void K3bDataDirTreeView::contentsDragLeaveEvent( QDragLeaveEvent* e )
+{
+ K3bListView::contentsDragLeaveEvent( e );
+
+ // remove any highlighting
+ if( d->dropDirItem ) {
+ d->dropDirItem->highlightIcon( false );
+ d->dropDirItem = 0;
+ }
+}
+
+
+void K3bDataDirTreeView::slotDropped( QDropEvent* e, QListViewItem*, QListViewItem* )
+{
+ // remove any highlighting
+ if( d->dropDirItem ) {
+ d->dropDirItem->highlightIcon( false );
+ d->dropDirItem = 0;
+ }
+
+ if( !e->isAccepted() )
+ return;
+
+ // determine K3bDirItem to add the items to
+ if( K3bDataDirViewItem* dirViewItem = dynamic_cast<K3bDataDirViewItem*>( itemAt(contentsToViewport(e->pos())) ) ) {
+ d->addParentDir = dirViewItem->dirItem();
+ }
+ else {
+ d->addParentDir = m_doc->root();
+ }
+
+ if( d->addParentDir ) {
+
+ // startDropAnimation( parent );
+
+ // check if items have been moved
+ if( m_fileView &&
+ e->source() == m_fileView->viewport() ) {
+ // move all selected items
+ QPtrList<QListViewItem> selectedViewItems = m_fileView->selectedItems();
+ QValueList<K3bDataItem*> selectedDataItems;
+ QPtrListIterator<QListViewItem> it( selectedViewItems );
+ for( ; it.current(); ++it ) {
+ K3bDataViewItem* dataViewItem = dynamic_cast<K3bDataViewItem*>( it.current() );
+ if( dataViewItem )
+ selectedDataItems.append( dataViewItem->dataItem() );
+ else
+ kdDebug() << "no dataviewitem" << endl;
+ }
+
+ K3bDataUrlAddingDialog::copyMoveItems( selectedDataItems, d->addParentDir, this, e->action() == QDropEvent::Copy );
+ }
+ else if( e->source() == viewport() ) {
+ // move the selected dir
+ if( K3bDataDirViewItem* dirItem = dynamic_cast<K3bDataDirViewItem*>( selectedItem() ) ) {
+ QValueList<K3bDataItem*> selectedDataItems;
+ selectedDataItems.append( dirItem->dirItem() );
+ K3bDataUrlAddingDialog::copyMoveItems( selectedDataItems, d->addParentDir, this, e->action() == QDropEvent::Copy );
+ }
+ }
+ else {
+ // seems that new items have been dropped
+ d->addUrls.clear();
+ if( KURLDrag::decode( e, d->addUrls ) ) {
+ //
+ // This is a small (not to ugly) hack to circumvent problems with the
+ // event queues: the url adding dialog will be non-modal regardless of
+ // the settings in case we open it directly.
+ //
+ QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
+ }
+ }
+ }
+
+ // now grab that focus
+ setFocus();
+}
+
+
+void K3bDataDirTreeView::slotAddUrls()
+{
+ K3bDataUrlAddingDialog::addUrls( d->addUrls, d->addParentDir, this );
+}
+
+
+void K3bDataDirTreeView::slotItemAdded( K3bDataItem* item )
+{
+ if( item->isDir() ) {
+ //
+ // We assume that we do not already have an item for the dir since the itemAdded signal
+ // should only be emitted once for every item
+ //
+ K3bDirItem* dirItem = static_cast<K3bDirItem*>( item );
+ K3bDataDirViewItem* parentViewItem = m_itemMap[dirItem->parent()];
+ K3bDataDirViewItem* newDirItem = new K3bDataDirViewItem( dirItem, parentViewItem );
+ m_itemMap.insert( dirItem, newDirItem );
+ }
+}
+
+
+void K3bDataDirTreeView::slotDataItemRemoved( K3bDataItem* item )
+{
+ if( item->isDir() ) {
+ K3bDirItem* dirItem = static_cast<K3bDirItem*>( item );
+ QMapIterator<K3bDirItem*, K3bDataDirViewItem*> it = m_itemMap.find( dirItem );
+ if( it != m_itemMap.end() ) {
+ K3bDataDirViewItem* viewItem = it.data();
+ m_itemMap.remove( it );
+
+ // we don't get removedInfo for the child items
+ // so we need to remove them here
+ QPtrListIterator<K3bDataItem> it( dirItem->children() );
+ for( ; it.current(); ++it ) {
+ if( it.current()->isDir() )
+ slotDataItemRemoved( it.current() );
+ }
+
+ delete viewItem;
+ }
+ }
+}
+
+
+void K3bDataDirTreeView::setCurrentDir( K3bDirItem* dirItem )
+{
+ QMapIterator<K3bDirItem*, K3bDataDirViewItem*> it = m_itemMap.find( dirItem );
+ if( it != m_itemMap.end() ) {
+ setCurrentItem( it.data() );
+ it.data()->setOpen(true);
+ if( it.data() != root() )
+ it.data()->parent()->setOpen(true);
+ }
+ else {
+ kdDebug() << "Tried to set unknown dirItem to current" << endl;
+ }
+}
+
+
+void K3bDataDirTreeView::setupActions()
+{
+ m_actionCollection = new KActionCollection( this );
+
+ m_actionProperties = new KAction( i18n("Properties"), "misc", 0, this, SLOT(slotProperties()),
+ actionCollection(), "properties" );
+ m_actionNewDir = new KAction( i18n("New Directory..."), "folder_new", CTRL+Key_N, this, SLOT(slotNewDir()),
+ actionCollection(), "new_dir" );
+ m_actionRemove = new KAction( i18n("Remove"), "editdelete", Key_Delete, this, SLOT(slotRemoveItem()),
+ actionCollection(), "remove" );
+ KShortcut renameShortCut( Key_F2 );
+ renameShortCut.append( KShortcut(CTRL+Key_R) ); // backwards compatibility
+ m_actionRename = new KAction( i18n("Rename"), "edit", renameShortCut, this, SLOT(slotRenameItem()),
+ actionCollection(), "rename" );
+
+ m_popupMenu = new KActionMenu( m_actionCollection, "contextMenu" );
+ m_popupMenu->insert( m_actionRename );
+ m_popupMenu->insert( m_actionRemove );
+ m_popupMenu->insert( m_actionNewDir );
+ m_popupMenu->insert( new KActionSeparator( this ) );
+ m_popupMenu->insert( m_actionProperties );
+ m_popupMenu->insert( new KActionSeparator( this ) );
+ m_popupMenu->insert( m_view->actionCollection()->action("project_burn") );
+}
+
+
+void K3bDataDirTreeView::showPopupMenu( KListView*, QListViewItem* item, const QPoint& point )
+{
+ if( item ) {
+ if( K3bDataViewItem* di = dynamic_cast<K3bDataViewItem*>(item) ) {
+ m_actionRemove->setEnabled( di->dataItem()->isRemoveable() );
+ m_actionRename->setEnabled( di->dataItem()->isRenameable() );
+ }
+ else {
+ m_actionRemove->setEnabled( false );
+ m_actionRename->setEnabled( false );
+ }
+ m_actionProperties->setEnabled( true );
+ }
+ else {
+ m_actionRemove->setEnabled( false );
+ m_actionRename->setEnabled( false );
+ m_actionProperties->setEnabled( false );
+ }
+
+ m_popupMenu->popup( point );
+}
+
+
+void K3bDataDirTreeView::slotNewDir()
+{
+ if( K3bDataDirViewItem* vI = dynamic_cast<K3bDataDirViewItem*>(currentItem()) ) {
+ K3bDirItem* parent = vI->dirItem();
+
+ QString name;
+ bool ok;
+
+ name = KInputDialog::getText( i18n("New Directory"),
+ i18n("Please insert the name for the new directory:"),
+ i18n("New Directory"), &ok, this );
+
+ while( ok && K3bDataDoc::nameAlreadyInDir( name, parent ) ) {
+ name = KInputDialog::getText( i18n("New Directory"),
+ i18n("A file with that name already exists. "
+ "Please insert the name for the new directory:"),
+ i18n("New Directory"), &ok, this );
+ }
+
+ if( !ok )
+ return;
+
+
+ m_doc->addEmptyDir( name, parent );
+ }
+}
+
+
+void K3bDataDirTreeView::slotRenameItem()
+{
+ showEditor( (K3bListViewItem*)currentItem(), 0 );
+}
+
+
+void K3bDataDirTreeView::slotRemoveItem()
+{
+ if( currentItem() ) {
+ if( K3bDataDirViewItem* dirViewItem = dynamic_cast<K3bDataDirViewItem*>( currentItem() ) )
+ m_doc->removeItem( dirViewItem->dirItem() );
+ }
+}
+
+
+void K3bDataDirTreeView::slotProperties()
+{
+ K3bDataViewItem* viewItem = dynamic_cast<K3bDataViewItem*>( currentItem() );
+ if( viewItem && currentItem() != root() ) {
+ K3bDataPropertiesDialog d( viewItem->dataItem(), this );
+ if( d.exec() ) {
+ repaint();
+ if( m_fileView )
+ m_fileView->repaint();
+ }
+ }
+ else
+ m_view->slotProperties();
+}
+
+
+void K3bDataDirTreeView::startDropAnimation( K3bDirItem* dir )
+{
+ stopDropAnimation();
+
+ K3bDataDirViewItem* vI = m_itemMap[dir];
+ if( vI ) {
+ d->animationCounter = 0;
+ d->animatedDirItem = vI;
+ d->beforeAniPixmap = QPixmap( *vI->pixmap(0) );
+ QTimer::singleShot( 0, this, SLOT(slotDropAnimate()) );
+ }
+}
+
+
+void K3bDataDirTreeView::slotDropAnimate()
+{
+ if( d->animatedDirItem ) {
+ if( d->animationCounter > 5 )
+ stopDropAnimation();
+ else {
+ switch(d->animationCounter) {
+ case 0:
+ d->animatedDirItem->setPixmap( 0, SmallIcon( "folder_cyan" ) );
+ break;
+ case 1:
+ d->animatedDirItem->setPixmap( 0, SmallIcon( "folder_green" ) );
+ break;
+ case 2:
+ d->animatedDirItem->setPixmap( 0, SmallIcon( "folder_yellow" ) );
+ break;
+ case 3:
+ d->animatedDirItem->setPixmap( 0, SmallIcon( "folder_orange" ) );
+ break;
+ case 4:
+ d->animatedDirItem->setPixmap( 0, SmallIcon( "folder_red" ) );
+ break;
+ case 5:
+ d->animatedDirItem->setPixmap( 0, SmallIcon( "folder_violet" ) );
+ break;
+ }
+
+ d->animationCounter++;
+ QTimer::singleShot( 300, this, SLOT(slotDropAnimate()) );
+ }
+ }
+}
+
+
+void K3bDataDirTreeView::stopDropAnimation()
+{
+ if( d->animatedDirItem ) {
+ d->animatedDirItem->setPixmap( 0, d->beforeAniPixmap );
+ d->animatedDirItem = 0;
+ }
+}
+
+
+// FIXME: remove this
+void K3bDataDirTreeView::checkForNewItems()
+{
+ K3bDataItem* item = m_root->dirItem()->nextSibling();
+ while( item != 0 )
+ {
+ // check if we have an entry and if not, create one
+ // we can assume that a listViewItem for the parent exists
+ // since we go top to bottom
+ if( item->isDir() )
+ {
+ K3bDirItem* dirItem = dynamic_cast<K3bDirItem*>( item );
+
+ QMapIterator<K3bDirItem*, K3bDataDirViewItem*> itDirItem = m_itemMap.find( dirItem );
+ if( itDirItem == m_itemMap.end() ) {
+ K3bDataDirViewItem* parentViewItem = m_itemMap[dirItem->parent()];
+ K3bDataDirViewItem* newDirItem = new K3bDataDirViewItem( dirItem, parentViewItem );
+ m_itemMap.insert( dirItem, newDirItem );
+ }
+ else {
+ // check if parent still correct (to get moved items)
+ K3bDataDirViewItem* dirViewItem = itDirItem.data();
+ K3bDataDirViewItem* parentViewItem = (K3bDataDirViewItem*)dirViewItem->parent();
+ K3bDataDirViewItem* dirParentViewItem = m_itemMap[dirItem->parent()];
+ if( dirParentViewItem != parentViewItem ) {
+ // reparent it
+ parentViewItem->takeItem( dirViewItem );
+ dirParentViewItem->insertItem( dirViewItem );
+ }
+ }
+ }
+
+ item = item->nextSibling();
+ }
+
+
+ // check the directory depth
+ QListViewItemIterator it(root());
+ while( it.current() != 0 ) {
+ if( K3bDataDirViewItem* dirViewItem = dynamic_cast<K3bDataDirViewItem*>(it.current()) )
+ if( it.current() != m_root ) {
+ K3bDirItem* dirItem = dirViewItem->dirItem();
+ dirViewItem->setPixmap( 0, dirItem->depth() > 7 ? SmallIcon( "folder_red" ) : SmallIcon( "folder" ) );
+ }
+
+ ++it;
+ }
+
+ // always show the first level
+ m_root->setOpen( true );
+}
+
+
+void K3bDataDirTreeView::slotDocChanged()
+{
+ // avoid flicker
+ if( d->lastUpdateVolumeId != m_doc->isoOptions().volumeID() ) {
+ d->lastUpdateVolumeId = m_doc->isoOptions().volumeID();
+ root()->repaint();
+ }
+}
+
+#include "k3bdatadirtreeview.moc"
diff --git a/src/projects/k3bdatadirtreeview.h b/src/projects/k3bdatadirtreeview.h
new file mode 100644
index 0000000..c79a9c6
--- /dev/null
+++ b/src/projects/k3bdatadirtreeview.h
@@ -0,0 +1,115 @@
+/*
+ *
+ * $Id: k3bdatadirtreeview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDATADIRTREEVIEW_H
+#define K3BDATADIRTREEVIEW_H
+
+
+#include <k3blistview.h>
+#include <kurl.h>
+
+#include <qmap.h>
+
+class K3bDataView;
+class K3bDataDoc;
+class K3bDataDirViewItem;
+class K3bDirItem;
+class K3bDataItem;
+class K3bDataFileView;
+class KActionCollection;
+class KActionMenu;
+class KAction;
+class K3bView;
+class QDragMoveEvent;
+class QDragLeaveEvent;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+
+class K3bDataDirTreeView : public K3bListView
+{
+ Q_OBJECT
+
+ public:
+ K3bDataDirTreeView( K3bView*, K3bDataDoc*, QWidget* parent );
+ virtual ~K3bDataDirTreeView();
+
+ K3bDataDirViewItem* root() { return m_root; }
+
+ void setFileView( K3bDataFileView* view ) { m_fileView = view; }
+
+ KActionCollection* actionCollection() const { return m_actionCollection; }
+
+ public slots:
+ void checkForNewItems();
+ void setCurrentDir( K3bDirItem* );
+
+ signals:
+ // void urlsDropped( const KURL::List&, QListViewItem* parent );
+ void dirSelected( K3bDirItem* );
+
+ protected:
+ bool acceptDrag(QDropEvent* e) const;
+ void contentsDragMoveEvent( QDragMoveEvent* e );
+ void contentsDragLeaveEvent( QDragLeaveEvent* e );
+
+ KActionCollection* m_actionCollection;
+ KActionMenu* m_popupMenu;
+ KAction* m_actionRemove;
+ KAction* m_actionRename;
+ KAction* m_actionNewDir;
+ KAction* m_actionProperties;
+
+ protected slots:
+ virtual void slotDropped( QDropEvent* e, QListViewItem* after, QListViewItem* parent );
+
+ private:
+ void setupActions();
+ void startDropAnimation( K3bDirItem* );
+ void stopDropAnimation();
+
+ K3bView* m_view;
+
+ K3bDataDoc* m_doc;
+ K3bDataDirViewItem* m_root;
+ K3bDataFileView* m_fileView;
+
+ /**
+ * We save the dirItems in a map to have a fast way
+ * for checking for new or removed items
+ */
+ QMap<K3bDirItem*, K3bDataDirViewItem*> m_itemMap;
+
+ class Private;
+ Private* d;
+
+ private slots:
+ void slotExecuted( QListViewItem* );
+ void slotDataItemRemoved( K3bDataItem* );
+ void showPopupMenu( KListView*, QListViewItem* _item, const QPoint& );
+ void slotRenameItem();
+ void slotRemoveItem();
+ void slotNewDir();
+ void slotProperties();
+ void slotDropAnimate();
+ void slotItemAdded( K3bDataItem* );
+ void slotAddUrls();
+ void slotDocChanged();
+};
+
+#endif
diff --git a/src/projects/k3bdatafileview.cpp b/src/projects/k3bdatafileview.cpp
new file mode 100644
index 0000000..4c06bde
--- /dev/null
+++ b/src/projects/k3bdatafileview.cpp
@@ -0,0 +1,483 @@
+/*
+ *
+ * $Id: k3bdatafileview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdatafileview.h"
+#include "k3bdataview.h"
+#include <k3bdatadoc.h>
+#include <k3bdataitem.h>
+#include <k3bdiritem.h>
+#include <k3bfileitem.h>
+#include <k3bspecialdataitem.h>
+#include <k3bsessionimportitem.h>
+#include "k3bdataurladdingdialog.h"
+#include <k3bvalidators.h>
+#include "k3bdatapropertiesdialog.h"
+#include "k3bdatadirtreeview.h"
+#include "k3bdataviewitem.h"
+#include <k3bview.h>
+
+
+#include <qdragobject.h>
+#include <qpainter.h>
+#include <qfontmetrics.h>
+#include <qtimer.h>
+#include <qheader.h>
+#include <qfileinfo.h>
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kurldrag.h>
+#include <kinputdialog.h>
+#include <kdebug.h>
+#include <kshortcut.h>
+#include <krun.h>
+#include <kdeversion.h>
+
+
+K3bDataFileView::K3bDataFileView( K3bView* view, K3bDataDirTreeView* dirTreeView, K3bDataDoc* doc, QWidget* parent )
+ : K3bListView( parent ),
+ m_view(view),
+ m_dropDirItem(0)
+{
+ m_treeView = dirTreeView;
+
+ setAcceptDrops( true );
+ setDropVisualizer( false );
+ setDropHighlighter( true );
+ setDragEnabled( true );
+ setItemsMovable( false );
+ setAllColumnsShowFocus( true );
+ setShowSortIndicator( true );
+
+ setNoItemText( i18n("Use drag'n'drop to add files and directories to the project.\n"
+ "To remove or rename files use the context menu.\n"
+ "After that press the burn button to write the CD.") );
+
+
+ addColumn( i18n("Name") );
+ addColumn( i18n("Type") );
+ addColumn( i18n("Size") );
+ addColumn( i18n("Local Path") );
+ addColumn( i18n("Link") );
+
+ setSelectionModeExt( KListView::Extended );
+
+ m_doc = doc;
+ m_currentDir = doc->root();
+ checkForNewItems();
+
+ connect( m_treeView, SIGNAL(dirSelected(K3bDirItem*)), this, SLOT(slotSetCurrentDir(K3bDirItem*)) );
+ connect( m_doc, SIGNAL(itemRemoved(K3bDataItem*)), this, SLOT(slotDataItemRemoved(K3bDataItem*)) );
+ connect( m_doc, SIGNAL(itemAdded(K3bDataItem*)), this, SLOT(slotItemAdded(K3bDataItem*)) );
+ connect( this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotExecuted(QListViewItem*)) );
+ connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(showPopupMenu(KListView*, QListViewItem*, const QPoint&)) );
+ connect( this, SIGNAL(dropped(QDropEvent*, QListViewItem*, QListViewItem*)),
+ this, SLOT(slotDropped(QDropEvent*, QListViewItem*, QListViewItem*)) );
+ connect( this, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)),
+ this, SLOT(slotDoubleClicked(QListViewItem*)) );
+
+ setupActions();
+}
+
+
+K3bDataFileView::~K3bDataFileView()
+{
+}
+
+
+K3bDirItem* K3bDataFileView::currentDir() const
+{
+ if( !m_currentDir )
+ m_currentDir = m_doc->root();
+ return m_currentDir;
+}
+
+
+void K3bDataFileView::slotSetCurrentDir( K3bDirItem* dir )
+{
+ if( dir ) {
+ m_currentDir = dir;
+ clearItems();
+ checkForNewItems();
+ }
+}
+
+
+void K3bDataFileView::clearItems()
+{
+ m_itemMap.clear();
+ K3bListView::clear();
+}
+
+
+void K3bDataFileView::slotItemAdded( K3bDataItem* item )
+{
+ if( item->parent() == currentDir() ) {
+ K3bDataViewItem* vi = 0;
+ if( item->isDir() )
+ vi = new K3bDataDirViewItem( static_cast<K3bDirItem*>(item), this );
+ else if( item->isFile() )
+ vi = new K3bDataFileViewItem( static_cast<K3bFileItem*>(item), this );
+ else if( item->isSpecialFile() )
+ vi = new K3bSpecialDataViewItem( static_cast<K3bSpecialDataItem*>(item), this );
+ else if( item->isFromOldSession() )
+ vi = new K3bSessionImportViewItem( static_cast<K3bSessionImportItem*>(item), this );
+ else
+ kdDebug() << "(K3bDataFileView) ERROR: unknown data item type" << endl;
+
+ if( vi )
+ m_itemMap[item] = vi;
+ }
+}
+
+
+void K3bDataFileView::slotDataItemRemoved( K3bDataItem* item )
+{
+ if( item->isDir() ) {
+ if( static_cast<K3bDirItem*>(item)->isSubItem( currentDir() ) ) {
+ slotSetCurrentDir( m_doc->root() );
+ }
+ }
+
+ if( m_itemMap.contains( item ) ) {
+ delete m_itemMap[item];
+ m_itemMap.remove(item);
+ }
+}
+
+
+void K3bDataFileView::checkForNewItems()
+{
+ hideEditor();
+
+ // add items that are not there yet
+ for( QPtrListIterator<K3bDataItem> it( m_currentDir->children() ); it.current(); ++it ) {
+ if( !m_itemMap.contains( it.current() ) ) {
+ slotItemAdded( it.current() );
+ }
+ }
+
+ // now check if some of the items have been moved out of the currently showing dir.
+ for( QListViewItemIterator it( this ); it.current(); ++it ) {
+ K3bDataViewItem* dataViewItem = dynamic_cast<K3bDataViewItem*>( it.current() );
+ if( dataViewItem && dataViewItem->dataItem()->parent() != currentDir() )
+ delete dataViewItem;
+ }
+}
+
+
+QDragObject* K3bDataFileView::dragObject()
+{
+ QPtrList<QListViewItem> selectedViewItems = selectedItems();
+ KURL::List urls;
+ for( QPtrListIterator<QListViewItem> it( selectedViewItems ); it.current(); ++it ) {
+ K3bDataViewItem* dataViewItem = dynamic_cast<K3bDataViewItem*>( it.current() );
+ if( dataViewItem ) {
+ urls.append( KURL::fromPathOrURL(dataViewItem->dataItem()->localPath()) );
+ }
+ else
+ kdDebug() << "no dataviewitem" << endl;
+ }
+
+ if( urls.isEmpty() )
+ return 0;
+
+ return KURLDrag::newDrag( urls, viewport() );
+}
+
+
+bool K3bDataFileView::acceptDrag(QDropEvent* e) const
+{
+ return ( e->source() == viewport() ||
+ KURLDrag::canDecode(e) ||
+ e->source() == m_treeView->viewport() );
+}
+
+
+void K3bDataFileView::contentsDragMoveEvent( QDragMoveEvent* e )
+{
+ K3bListView::contentsDragMoveEvent( e );
+
+ // highlight the folder the items would be added to
+ if( m_dropDirItem )
+ m_dropDirItem->highlightIcon( false );
+
+ m_dropDirItem = dynamic_cast<K3bDataDirViewItem*>( itemAt(contentsToViewport(e->pos())) );
+ if( m_dropDirItem )
+ m_dropDirItem->highlightIcon( true );
+}
+
+
+void K3bDataFileView::contentsDragLeaveEvent( QDragLeaveEvent* e )
+{
+ K3bListView::contentsDragLeaveEvent( e );
+
+ // remove any highlighting
+ if( m_dropDirItem ) {
+ m_dropDirItem->highlightIcon( false );
+ m_dropDirItem = 0;
+ }
+}
+
+
+void K3bDataFileView::slotDropped( QDropEvent* e, QListViewItem*, QListViewItem* )
+{
+ // remove any highlighting
+ if( m_dropDirItem ) {
+ m_dropDirItem->highlightIcon( false );
+ m_dropDirItem = 0;
+ }
+
+ if( !e->isAccepted() )
+ return;
+
+ // determine K3bDirItem to add the items to
+ m_addParentDir = currentDir();
+
+ if( K3bDataDirViewItem* dirViewItem = dynamic_cast<K3bDataDirViewItem*>( itemAt(contentsToViewport(e->pos())) ) ) {
+ // only add to a dir if we drop directly on the name
+ if( header()->sectionAt( e->pos().x() ) == 0 )
+ m_addParentDir = dirViewItem->dirItem();
+ }
+
+ if( m_addParentDir ) {
+
+ // check if items have been moved
+ if( e->source() == viewport() ) {
+ // move all selected items
+ QPtrList<QListViewItem> selectedViewItems = selectedItems();
+ QValueList<K3bDataItem*> selectedDataItems;
+ QPtrListIterator<QListViewItem> it( selectedViewItems );
+ for( ; it.current(); ++it ) {
+ K3bDataViewItem* dataViewItem = dynamic_cast<K3bDataViewItem*>( it.current() );
+ if( dataViewItem )
+ selectedDataItems.append( dataViewItem->dataItem() );
+ else
+ kdDebug() << "no dataviewitem" << endl;
+ }
+
+ K3bDataUrlAddingDialog::copyMoveItems( selectedDataItems, m_addParentDir, this, e->action() == QDropEvent::Copy );
+ }
+ else if( e->source() == m_treeView->viewport() ) {
+ // move the selected dir
+ if( K3bDataDirViewItem* dirItem = dynamic_cast<K3bDataDirViewItem*>( m_treeView->selectedItem() ) ) {
+ QValueList<K3bDataItem*> selectedDataItems;
+ selectedDataItems.append( dirItem->dirItem() );
+ K3bDataUrlAddingDialog::copyMoveItems( selectedDataItems, m_addParentDir, this, e->action() == QDropEvent::Copy );
+ }
+ }
+ else {
+ // seems that new items have been dropped
+ m_addUrls.clear();
+ if( KURLDrag::decode( e, m_addUrls ) ) {
+ //
+ // This is a small (not to ugly) hack to circumvent problems with the
+ // event queues: the url adding dialog will be non-modal regardless of
+ // the settings in case we open it directly.
+ //
+ QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
+ }
+ }
+ }
+
+ // now grab that focus
+ setFocus();
+}
+
+
+void K3bDataFileView::slotAddUrls()
+{
+ K3bDataUrlAddingDialog::addUrls( m_addUrls, m_addParentDir, this );
+}
+
+
+void K3bDataFileView::slotExecuted( QListViewItem* item )
+{
+ if( K3bDataDirViewItem* k = dynamic_cast<K3bDataDirViewItem*>( item ) ) {
+ hideEditor(); // disable the K3bListView Editor
+ slotSetCurrentDir( k->dirItem() );
+ emit dirSelected( currentDir() );
+ }
+}
+
+
+void K3bDataFileView::setupActions()
+{
+ m_actionCollection = new KActionCollection( this );
+
+ m_actionProperties = new KAction( i18n("Properties"), "misc", 0, this, SLOT(slotProperties()),
+ actionCollection(), "properties" );
+ m_actionNewDir = new KAction( i18n("New Directory..."), "folder_new", CTRL+Key_N, this, SLOT(slotNewDir()),
+ actionCollection(), "new_dir" );
+ m_actionRemove = new KAction( i18n("Remove"), "editdelete", Key_Delete, this, SLOT(slotRemoveItem()),
+ actionCollection(), "remove" );
+ KShortcut renameShortCut( Key_F2 );
+ renameShortCut.append( KShortcut(CTRL+Key_R) ); // backwards compatibility
+ m_actionRename = new KAction( i18n("Rename"), "edit", renameShortCut, this, SLOT(slotRenameItem()),
+ actionCollection(), "rename" );
+ m_actionParentDir = new KAction( i18n("Parent Directory"), "up", 0, this, SLOT(slotParentDir()),
+ actionCollection(), "parent_dir" );
+ m_actionOpen = new KAction( i18n("Open"), "fileopen", 0, this, SLOT(slotOpen()),
+ actionCollection(), "open" );
+
+ m_popupMenu = new KActionMenu( m_actionCollection, "contextMenu" );
+ m_popupMenu->insert( m_actionParentDir );
+ m_popupMenu->insert( new KActionSeparator( this ) );
+ m_popupMenu->insert( m_actionRename );
+ m_popupMenu->insert( m_actionRemove );
+ m_popupMenu->insert( m_actionNewDir );
+ m_popupMenu->insert( new KActionSeparator( this ) );
+ m_popupMenu->insert( m_actionOpen );
+ m_popupMenu->insert( new KActionSeparator( this ) );
+ m_popupMenu->insert( m_actionProperties );
+ m_popupMenu->insert( new KActionSeparator( this ) );
+ m_popupMenu->insert( m_view->actionCollection()->action("project_burn") );
+}
+
+
+void K3bDataFileView::showPopupMenu( KListView*, QListViewItem* item, const QPoint& point )
+{
+ if( item ) {
+ K3bDataItem* di = static_cast<K3bDataViewItem*>(item)->dataItem();
+ m_actionRemove->setEnabled( di->isRemoveable() );
+ m_actionRename->setEnabled( di->isRenameable() );
+ if( currentDir() == m_doc->root() )
+ m_actionParentDir->setEnabled( false );
+ else
+ m_actionParentDir->setEnabled( true );
+ m_actionOpen->setEnabled( di->isFile() );
+ }
+ else {
+ m_actionRemove->setEnabled( false );
+ m_actionRename->setEnabled( false );
+ m_actionOpen->setEnabled( false );
+ }
+
+ m_popupMenu->popup( point );
+}
+
+
+void K3bDataFileView::slotNewDir()
+{
+ K3bDirItem* parent = currentDir();
+
+ QString name;
+ bool ok;
+
+ name = KInputDialog::getText( i18n("New Directory"),
+ i18n("Please insert the name for the new directory:"),
+ i18n("New Directory"), &ok, this );
+
+ while( ok && K3bDataDoc::nameAlreadyInDir( name, parent ) ) {
+ name = KInputDialog::getText( i18n("New Directory"),
+ i18n("A file with that name already exists. "
+ "Please insert the name for the new directory:"),
+ i18n("New Directory"), &ok, this );
+ }
+
+ if( !ok )
+ return;
+
+
+ m_doc->addEmptyDir( name, parent );
+}
+
+
+void K3bDataFileView::slotRenameItem()
+{
+ if( currentItem() )
+ showEditor( (K3bListViewItem*)currentItem(), 0 );
+}
+
+
+void K3bDataFileView::slotRemoveItem()
+{
+ QPtrList<QListViewItem> items = selectedItems();
+ QPtrListIterator<QListViewItem> it( items );
+ for(; it.current(); ++it ) {
+ if( K3bDataViewItem* d = dynamic_cast<K3bDataViewItem*>( it.current() ) )
+ m_doc->removeItem( d->dataItem() );
+ }
+}
+
+
+void K3bDataFileView::slotParentDir()
+{
+ if( currentDir() != m_doc->root() ) {
+ slotSetCurrentDir( currentDir()->parent() );
+
+ emit dirSelected( currentDir() );
+ }
+}
+
+
+void K3bDataFileView::slotProperties()
+{
+ K3bDataItem* dataItem = 0;
+
+ // get selected item
+ if( K3bDataViewItem* viewItem = dynamic_cast<K3bDataViewItem*>( selectedItems().first() ) ) {
+ dataItem = viewItem->dataItem();
+ }
+ else {
+ // default to current dir
+ dataItem = currentDir();
+ }
+
+ if( dataItem ) {
+ K3bDataPropertiesDialog d( dataItem, this );
+ d.exec();
+ }
+ else
+ m_view->slotProperties();
+}
+
+
+void K3bDataFileView::slotOpen()
+{
+ if( K3bDataViewItem* viewItem = dynamic_cast<K3bDataViewItem*>( selectedItems().first() ) ) {
+ K3bDataItem* item = viewItem->dataItem();
+ if( item->isFile() ) {
+ K3bDataFileViewItem* fvi = static_cast<K3bDataFileViewItem*>( viewItem );
+ if( fvi->mimeType() &&
+#if KDE_IS_VERSION(3,3,0)
+ !KRun::isExecutableFile( KURL::fromPathOrURL(item->localPath()),
+ fvi->mimeType()->name() )
+#else
+ !QFileInfo( item->localPath() ).isExecutable()
+#endif
+ )
+ KRun::runURL( KURL::fromPathOrURL(item->localPath()),
+ fvi->mimeType()->name() );
+ else
+ KRun::displayOpenWithDialog( KURL::fromPathOrURL(item->localPath()) );
+ }
+ }
+}
+
+
+void K3bDataFileView::slotDoubleClicked( QListViewItem* )
+{
+ if( K3bDataViewItem* viewItem = dynamic_cast<K3bDataViewItem*>( selectedItems().first() ) ) {
+ if( !viewItem->dataItem()->isDir() ) {
+ K3bDataPropertiesDialog d( viewItem->dataItem(), this );
+ d.exec();
+ }
+ }
+}
+
+#include "k3bdatafileview.moc"
diff --git a/src/projects/k3bdatafileview.h b/src/projects/k3bdatafileview.h
new file mode 100644
index 0000000..580af96
--- /dev/null
+++ b/src/projects/k3bdatafileview.h
@@ -0,0 +1,115 @@
+/*
+ *
+ * $Id: k3bdatafileview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDATAFILEVIEW_H
+#define K3BDATAFILEVIEW_H
+
+#include <k3blistview.h>
+
+#include <kurl.h>
+
+#include <qmap.h>
+
+
+class K3bDataDoc;
+class K3bDirItem;
+class K3bDataView;
+class K3bDataViewItem;
+class K3bDataItem;
+class QDropEvent;
+class KActionCollection;
+class KActionMenu;
+class KAction;
+class K3bDataDirTreeView;
+class K3bDataDirViewItem;
+class K3bView;
+class QPainter;
+class QDragMoveEvent;
+class QDragLeaveEvent;
+
+/**
+ *@author Sebastian Trueg
+ */
+
+class K3bDataFileView : public K3bListView
+{
+ Q_OBJECT
+
+ public:
+ K3bDataFileView( K3bView*, K3bDataDirTreeView*, K3bDataDoc*, QWidget* parent );
+ ~K3bDataFileView();
+
+ K3bDirItem* currentDir() const;
+
+ KActionCollection* actionCollection() const { return m_actionCollection; }
+
+ signals:
+ void dirSelected( K3bDirItem* );
+
+ public slots:
+ void slotSetCurrentDir( K3bDirItem* );
+ void checkForNewItems();
+
+ private slots:
+ void slotDataItemRemoved( K3bDataItem* );
+ void slotExecuted( QListViewItem* );
+ void slotDropped( QDropEvent* e, QListViewItem* after, QListViewItem* parent );
+ void showPopupMenu( KListView*, QListViewItem* _item, const QPoint& );
+ void slotRenameItem();
+ void slotRemoveItem();
+ void slotNewDir();
+ void slotParentDir();
+ void slotProperties();
+ void slotDoubleClicked( QListViewItem* item );
+ void slotItemAdded( K3bDataItem* );
+ void slotAddUrls();
+ void slotOpen();
+
+ protected:
+ bool acceptDrag(QDropEvent* e) const;
+ void contentsDragMoveEvent( QDragMoveEvent* e );
+ void contentsDragLeaveEvent( QDragLeaveEvent* e );
+ QDragObject* dragObject();
+
+ private:
+ void clearItems();
+ void setupActions();
+
+ KActionCollection* m_actionCollection;
+ KActionMenu* m_popupMenu;
+ KAction* m_actionParentDir;
+ KAction* m_actionRemove;
+ KAction* m_actionRename;
+ KAction* m_actionNewDir;
+ KAction* m_actionProperties;
+ KAction* m_actionOpen;
+
+ K3bView* m_view;
+
+ K3bDataDoc* m_doc;
+ mutable K3bDirItem* m_currentDir;
+ K3bDataDirTreeView* m_treeView;
+
+ K3bDataDirViewItem* m_dropDirItem;
+
+ QMap<K3bDataItem*, K3bDataViewItem*> m_itemMap;
+
+ // used for the urladdingdialog hack
+ KURL::List m_addUrls;
+ K3bDirItem* m_addParentDir;
+};
+
+#endif
diff --git a/src/projects/k3bdataimagesettingswidget.cpp b/src/projects/k3bdataimagesettingswidget.cpp
new file mode 100644
index 0000000..331e1eb
--- /dev/null
+++ b/src/projects/k3bdataimagesettingswidget.cpp
@@ -0,0 +1,400 @@
+/*
+ *
+ * $Id: k3bdataimagesettingswidget.cpp 691413 2007-07-23 16:01:13Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdataimagesettingswidget.h"
+#include "k3bdataadvancedimagesettingswidget.h"
+#include "k3bdatavolumedescwidget.h"
+
+#include "k3bisooptions.h"
+
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include <qwhatsthis.h>
+#include <qlayout.h>
+
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kdialogbase.h>
+#include <kdebug.h>
+
+
+// indices for the filesystems combobox
+static const int FS_LINUX_ONLY = 0;
+static const int FS_LINUX_AND_WIN = 1;
+static const int FS_UDF = 2;
+static const int FS_DOS_COMP = 3;
+static const int FS_CUSTOM = 4;
+static const int FS_MAX = 5;
+
+static const char* s_fsPresetNames[] = {
+ I18N_NOOP("Linux/Unix only"),
+ I18N_NOOP("Linux/Unix + Windows"),
+ I18N_NOOP("Very large files (UDF)"),
+ I18N_NOOP("DOS Compatibility"),
+ I18N_NOOP("Custom")
+};
+
+static bool s_fsPresetsInitialized = false;
+static K3bIsoOptions s_fsPresets[FS_CUSTOM];
+
+// indices for the whitespace treatment combobox
+static const int WS_NO_CHANGE = 0;
+static const int WS_STRIP = 1;
+static const int WS_EXTENDED_STRIP = 2;
+static const int WS_REPLACE = 3;
+
+// indices for the symlink handling combobox
+static const int SYM_NO_CHANGE = 0;
+static const int SYM_DISCARD_BROKEN = 1;
+static const int SYM_DISCARD_ALL = 2;
+static const int SYM_FOLLOW = 3;
+
+
+//
+// returns true if the part of the options that is presented in the advanced custom
+// settings dialog is equal. used to determine if some preset is used.
+//
+static bool compareAdvancedOptions( const K3bIsoOptions& o1, const K3bIsoOptions& o2 )
+{
+ return ( o1.forceInputCharset() == o2.forceInputCharset() &&
+ ( !o1.forceInputCharset() || o1.inputCharset() == o2.inputCharset() ) &&
+ o1.createRockRidge() == o2.createRockRidge() &&
+ o1.createJoliet() == o2.createJoliet() &&
+ o1.createUdf() == o2.createUdf() &&
+ o1.ISOallowLowercase() == o2.ISOallowLowercase() &&
+ o1.ISOallowPeriodAtBegin() == o2.ISOallowPeriodAtBegin() &&
+ o1.ISOallow31charFilenames() == o2.ISOallow31charFilenames() &&
+ o1.ISOomitVersionNumbers() == o2.ISOomitVersionNumbers() &&
+ o1.ISOomitTrailingPeriod() == o2.ISOomitTrailingPeriod() &&
+ o1.ISOmaxFilenameLength() == o2.ISOmaxFilenameLength() &&
+ o1.ISOrelaxedFilenames() == o2.ISOrelaxedFilenames() &&
+ o1.ISOnoIsoTranslate() == o2.ISOnoIsoTranslate() &&
+ o1.ISOallowMultiDot() == o2.ISOallowMultiDot() &&
+ o1.ISOuntranslatedFilenames() == o2.ISOuntranslatedFilenames() &&
+ o1.createTRANS_TBL() == o2.createTRANS_TBL() &&
+ o1.hideTRANS_TBL() == o2.hideTRANS_TBL() &&
+ o1.jolietLong() == o2.jolietLong() &&
+ o1.ISOLevel() == o2.ISOLevel() &&
+ o1.preserveFilePermissions() == o2.preserveFilePermissions() &&
+ o1.doNotCacheInodes() == o2.doNotCacheInodes() );
+}
+
+
+static void initializePresets()
+{
+ // Linux-only
+ s_fsPresets[FS_LINUX_ONLY].setCreateJoliet( false );
+ s_fsPresets[FS_LINUX_ONLY].setISOallow31charFilenames( true );
+
+ // Linux + Windows
+ s_fsPresets[FS_LINUX_AND_WIN].setCreateJoliet( true );
+ s_fsPresets[FS_LINUX_AND_WIN].setJolietLong( true );
+ s_fsPresets[FS_LINUX_AND_WIN].setISOallow31charFilenames( true );
+
+ // UDF
+ s_fsPresets[FS_UDF].setCreateJoliet( false );
+ s_fsPresets[FS_UDF].setCreateUdf( true );
+ s_fsPresets[FS_UDF].setISOallow31charFilenames( true );
+
+ // DOS comp
+ s_fsPresets[FS_DOS_COMP].setCreateJoliet( false );
+ s_fsPresets[FS_DOS_COMP].setCreateRockRidge( false );
+ s_fsPresets[FS_DOS_COMP].setISOallow31charFilenames( false );
+ s_fsPresets[FS_DOS_COMP].setISOLevel( 1 );
+
+ s_fsPresetsInitialized = true;
+}
+
+
+
+class K3bDataImageSettingsWidget::CustomFilesystemsDialog : public KDialogBase
+{
+public:
+ CustomFilesystemsDialog( QWidget* parent )
+ : KDialogBase( parent,
+ "custom_filesystems_dialog",
+ true,
+ i18n("Custom Data Project Filesystems"),
+ Ok|Cancel,
+ Ok,
+ true ) {
+ w = new K3bDataAdvancedImageSettingsWidget( this );
+ setMainWidget( w );
+ }
+
+ K3bDataAdvancedImageSettingsWidget* w;
+};
+
+
+class K3bDataImageSettingsWidget::VolumeDescDialog : public KDialogBase
+{
+public:
+ VolumeDescDialog( QWidget* parent )
+ : KDialogBase( parent,
+ "voldesc_dialog",
+ true,
+ i18n("Volume Descriptor"),
+ Ok|Cancel,
+ Ok,
+ true ) {
+ w = new K3bDataVolumeDescWidget( this );
+ setMainWidget( w );
+
+ // give ourselves a reasonable size
+ QSize s = sizeHint();
+ s.setWidth( QMAX(s.width(), 300) );
+ resize( s );
+ }
+
+ K3bDataVolumeDescWidget* w;
+};
+
+
+
+K3bDataImageSettingsWidget::K3bDataImageSettingsWidget( QWidget* parent, const char* name )
+ : base_K3bDataImageSettings( parent, name ),
+ m_fileSystemOptionsShown(true)
+{
+ layout()->setMargin( KDialog::marginHint() );
+
+ m_customFsDlg = new CustomFilesystemsDialog( this );
+ m_volDescDlg = new VolumeDescDialog( this );
+
+ connect( m_buttonCustomFilesystems, SIGNAL(clicked()),
+ this, SLOT(slotCustomFilesystems()) );
+ connect( m_buttonMoreVolDescFields, SIGNAL(clicked()),
+ this, SLOT(slotMoreVolDescFields()) );
+ connect( m_comboSpaceHandling, SIGNAL(activated(int)),
+ this, SLOT(slotSpaceHandlingChanged(int)) );
+
+ for( int i = 0; i < FS_MAX; ++i )
+ m_comboFilesystems->insertItem( i18n( s_fsPresetNames[i] ) );
+
+ if( !s_fsPresetsInitialized )
+ initializePresets();
+
+ QWhatsThis::add( m_comboFilesystems,
+ i18n("<p><b>File System Presets</b>"
+ "<p>K3b provides the following file system Presets which allow for a quick selection "
+ "of the most frequently used settings.")
+ + "<p><b>" + i18n(s_fsPresetNames[0]) + "</b><br>"
+ + i18n("The file system is optimized for usage on Linux/Unix systems. This mainly means that "
+ "it uses the Rock Ridge extensions to provide long filenames, symbolic links, and POSIX "
+ "compatible file permissions.")
+ + "<p><b>" + i18n(s_fsPresetNames[1]) + "</b><br>"
+ + i18n("In addition to the settings for Linux/Unix the file system contains a Joliet tree which "
+ "allows for long file names on Windows which does not support the Rock Ridget extensions. "
+ "Be aware that the file name length is restricted to 103 characters.")
+ + "<p><b>" + i18n(s_fsPresetNames[2]) + "</b><br>"
+ + i18n("The file system has additional UDF entries attached to it. This raises the maximal file "
+ "size to 4 GB. Be aware that the UDF support in K3b is limited.")
+ + "<p><b>" + i18n(s_fsPresetNames[3]) + "</b><br>"
+ + i18n("The file system is optimized for compatibility with old systems. That means file names "
+ "are restricted to 8.3 characters and no symbolic links or file permissions are supported.") );
+}
+
+
+K3bDataImageSettingsWidget::~K3bDataImageSettingsWidget()
+{
+}
+
+
+void K3bDataImageSettingsWidget::showFileSystemOptions( bool b )
+{
+ m_groupFileSystem->setShown(b);
+ m_groupSymlinks->setShown(b);
+ m_groupWhitespace->setShown(b);
+
+ m_fileSystemOptionsShown = b;
+}
+
+
+void K3bDataImageSettingsWidget::slotSpaceHandlingChanged( int i )
+{
+ m_editReplace->setEnabled( i == WS_REPLACE );
+}
+
+
+void K3bDataImageSettingsWidget::slotCustomFilesystems()
+{
+ // load settings in custom window
+ if( m_comboFilesystems->currentItem() != FS_CUSTOM ) {
+ m_customFsDlg->w->load( s_fsPresets[m_comboFilesystems->currentItem()] );
+ }
+
+ // store the current settings in case the user cancels the changes
+ K3bIsoOptions o;
+ m_customFsDlg->w->save( o );
+
+ if( m_customFsDlg->exec() == QDialog::Accepted ) {
+ slotFilesystemsChanged();
+ }
+ else {
+ // reload the old settings discarding any changes
+ m_customFsDlg->w->load( o );
+ }
+}
+
+
+void K3bDataImageSettingsWidget::slotFilesystemsChanged()
+{
+ if( !m_fileSystemOptionsShown )
+ return;
+
+ // new custom entry
+ QStringList s;
+ if( m_customFsDlg->w->m_checkRockRidge->isChecked() )
+ s += i18n("Rock Ridge");
+ if( m_customFsDlg->w->m_checkJoliet->isChecked() )
+ s += i18n("Joliet");
+ if( m_customFsDlg->w->m_checkUdf->isChecked() )
+ s += i18n("UDF");
+ if( s.isEmpty() )
+ m_comboFilesystems->changeItem( i18n("Custom (ISO9660 only)"), FS_CUSTOM );
+ else
+ m_comboFilesystems->changeItem( i18n("Custom (%1)").arg( s.join(", ") ), FS_CUSTOM );
+
+ // see if any of the presets is loaded
+ m_comboFilesystems->setCurrentItem( FS_CUSTOM );
+ K3bIsoOptions o;
+ m_customFsDlg->w->save( o );
+ for( int i = 0; i < FS_CUSTOM; ++i ) {
+ if( compareAdvancedOptions( o, s_fsPresets[i] ) ) {
+ kdDebug() << "(K3bDataImageSettingsWidget) found preset settings: " << s_fsPresetNames[i] << endl;
+ m_comboFilesystems->setCurrentItem( i );
+ break;
+ }
+ }
+
+ if( m_comboFilesystems->currentItem() == FS_CUSTOM ) {
+ if( !m_customFsDlg->w->m_checkRockRidge->isChecked() ) {
+ KMessageBox::information( this,
+ i18n("<p>Be aware that it is not recommended to disable the Rock Ridge "
+ "Extensions. There is no disadvantage in enabling Rock Ridge (except "
+ "for a very small space overhead) but a lot of advantages."
+ "<p>Without Rock Ridge Extensions symbolic links are not supported "
+ "and will always be followed as if the \"Follow Symbolic Links\" option "
+ "was enabled."),
+ i18n("Rock Ridge Extensions Disabled"),
+ "warning_about_rock_ridge" );
+ }
+
+ if( !m_customFsDlg->w->m_checkJoliet->isChecked() )
+ KMessageBox::information( this,
+ i18n("<p>Be aware that without the Joliet extensions Windows "
+ "systems will not be able to display long filenames. You "
+ "will only see the ISO9660 filenames."
+ "<p>If you do not intend to use the CD/DVD on a Windows "
+ "system it is safe to disable Joliet."),
+ i18n("Joliet Extensions Disabled"),
+ "warning_about_joliet" );
+ }
+}
+
+
+void K3bDataImageSettingsWidget::slotMoreVolDescFields()
+{
+ // update dlg to current state
+ m_volDescDlg->w->m_editVolumeName->setText( m_editVolumeName->text() );
+
+ // remember old settings
+ K3bIsoOptions o;
+ m_volDescDlg->w->save( o );
+
+ // exec dlg
+ if( m_volDescDlg->exec() == QDialog::Accepted ) {
+ // accept new entries
+ m_volDescDlg->w->save( o );
+ m_editVolumeName->setText( o.volumeID() );
+ }
+ else {
+ // restore old settings
+ m_volDescDlg->w->load( o );
+ }
+}
+
+
+void K3bDataImageSettingsWidget::load( const K3bIsoOptions& o )
+{
+ m_customFsDlg->w->load( o );
+ m_volDescDlg->w->load( o );
+
+ slotFilesystemsChanged();
+
+ if( o.discardBrokenSymlinks() )
+ m_comboSymlinkHandling->setCurrentItem( SYM_DISCARD_BROKEN );
+ else if( o.discardSymlinks() )
+ m_comboSymlinkHandling->setCurrentItem( SYM_DISCARD_ALL );
+ else if( o.followSymbolicLinks() )
+ m_comboSymlinkHandling->setCurrentItem( SYM_FOLLOW );
+ else
+ m_comboSymlinkHandling->setCurrentItem( SYM_NO_CHANGE );
+
+ switch( o.whiteSpaceTreatment() ) {
+ case K3bIsoOptions::strip:
+ m_comboSpaceHandling->setCurrentItem( WS_STRIP );
+ break;
+ case K3bIsoOptions::extended:
+ m_comboSpaceHandling->setCurrentItem( WS_EXTENDED_STRIP );
+ break;
+ case K3bIsoOptions::replace:
+ m_comboSpaceHandling->setCurrentItem( WS_REPLACE );
+ break;
+ default:
+ m_comboSpaceHandling->setCurrentItem( WS_NO_CHANGE );
+ }
+ slotSpaceHandlingChanged( m_comboSpaceHandling->currentItem() );
+
+ m_editReplace->setText( o.whiteSpaceTreatmentReplaceString() );
+
+ m_editVolumeName->setText( o.volumeID() );
+}
+
+
+void K3bDataImageSettingsWidget::save( K3bIsoOptions& o )
+{
+ if( m_comboFilesystems->currentItem() != FS_CUSTOM )
+ m_customFsDlg->w->load( s_fsPresets[m_comboFilesystems->currentItem()] );
+ m_customFsDlg->w->save( o );
+
+ m_volDescDlg->w->save( o );
+
+ o.setDiscardSymlinks( m_comboSymlinkHandling->currentItem() == SYM_DISCARD_ALL );
+ o.setDiscardBrokenSymlinks( m_comboSymlinkHandling->currentItem() == SYM_DISCARD_BROKEN );
+ o.setFollowSymbolicLinks( m_comboSymlinkHandling->currentItem() == SYM_FOLLOW );
+
+ switch( m_comboSpaceHandling->currentItem() ) {
+ case WS_STRIP:
+ o.setWhiteSpaceTreatment( K3bIsoOptions::strip );
+ break;
+ case WS_EXTENDED_STRIP:
+ o.setWhiteSpaceTreatment( K3bIsoOptions::extended );
+ break;
+ case WS_REPLACE:
+ o.setWhiteSpaceTreatment( K3bIsoOptions::replace );
+ break;
+ default:
+ o.setWhiteSpaceTreatment( K3bIsoOptions::noChange );
+ }
+ o.setWhiteSpaceTreatmentReplaceString( m_editReplace->text() );
+
+ o.setVolumeID( m_editVolumeName->text() );
+}
+
+#include "k3bdataimagesettingswidget.moc"
diff --git a/src/projects/k3bdataimagesettingswidget.h b/src/projects/k3bdataimagesettingswidget.h
new file mode 100644
index 0000000..e16226f
--- /dev/null
+++ b/src/projects/k3bdataimagesettingswidget.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * $Id: k3bdataimagesettingswidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3B_DATAIMAGE_SETTINGS_WIDGET_H
+#define K3B_DATAIMAGE_SETTINGS_WIDGET_H
+
+
+#include "base_k3bdataimagesettings.h"
+
+class K3bIsoOptions;
+
+
+class K3bDataImageSettingsWidget : public base_K3bDataImageSettings
+{
+ Q_OBJECT
+
+ public:
+ K3bDataImageSettingsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bDataImageSettingsWidget();
+
+ void load( const K3bIsoOptions& );
+ void save( K3bIsoOptions& );
+
+ void showFileSystemOptions( bool );
+
+ private slots:
+ void slotSpaceHandlingChanged( int i );
+ void slotCustomFilesystems();
+ void slotMoreVolDescFields();
+ void slotFilesystemsChanged();
+
+ private:
+ class CustomFilesystemsDialog;
+ class VolumeDescDialog;
+ CustomFilesystemsDialog* m_customFsDlg;
+ VolumeDescDialog* m_volDescDlg;
+
+ bool m_fileSystemOptionsShown;
+};
+
+
+#endif
diff --git a/src/projects/k3bdatamultisessioncombobox.cpp b/src/projects/k3bdatamultisessioncombobox.cpp
new file mode 100644
index 0000000..57dd818
--- /dev/null
+++ b/src/projects/k3bdatamultisessioncombobox.cpp
@@ -0,0 +1,177 @@
+/*
+ *
+ * $Id: k3bdatamultisessioncombobox.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdatamultisessioncombobox.h"
+
+#include <klocale.h>
+#include <kconfig.h>
+
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+
+
+static const int s_autoIndex = 0;
+static const int s_noneIndex = 1;
+static const int s_startIndex = 2;
+static const int s_continueIndex = 3;
+static const int s_finishIndex = 4;
+
+
+K3bDataMultiSessionCombobox::K3bDataMultiSessionCombobox( QWidget* parent, const char* name )
+ : QComboBox( parent, name ),
+ m_forceNoMultiSession(false)
+{
+ init( false );
+
+ QToolTip::add( this, i18n("Select the Multisession Mode for the project.") );
+ QWhatsThis::add( this, i18n("<p><b>Multisession Mode</b>"
+ "<p><b>Auto</b><br>"
+ "Let K3b decide which mode to use. The decision will be based "
+ "on the size of the project (does it fill the whole media) and "
+ "the state of the inserted media (appendable or not)."
+ "<p><b>No Multisession</b><br>"
+ "Create a single-session CD or DVD and close the disk."
+ "<p><b>Start Multisession</b><br>"
+ "Start a multisession CD or DVD, not closing the disk to "
+ "allow further sessions to be apppended."
+ "<p><b>Continue Multisession</b><br>"
+ "Continue an appendable data CD (as for example created in "
+ "<em>Start Multisession</em> mode) and add another session "
+ "without closing the disk to "
+ "allow further sessions to be apppended."
+ "<p><b>Finish Multisession</b><br>"
+ "Continue an appendable data CD (as for example created in "
+ "<em>Start Multisession</em> mode), add another session, "
+ "and close the disk."
+ "<p><em>In the case of DVD+RW and DVD-RW restricted overwrite media "
+ "K3b will not actually create multiple sessions but grow the "
+ "file system to include the new data.</em>") );
+}
+
+
+K3bDataMultiSessionCombobox::~K3bDataMultiSessionCombobox()
+{
+}
+
+
+void K3bDataMultiSessionCombobox::init( bool force )
+{
+ m_forceNoMultiSession = force;
+
+ clear();
+
+ insertItem( i18n("Auto"), s_autoIndex );
+ insertItem( i18n("No Multisession"), s_noneIndex );
+ if( !m_forceNoMultiSession ) {
+ insertItem( i18n("Start Multisession"), s_startIndex );
+ insertItem( i18n("Continue Multisession "), s_continueIndex );
+ insertItem( i18n("Finish Multisession "), s_finishIndex );
+ }
+}
+
+
+K3bDataDoc::MultiSessionMode K3bDataMultiSessionCombobox::multiSessionMode() const
+{
+ switch( currentItem() ) {
+ case s_noneIndex:
+ return K3bDataDoc::NONE;
+ case s_startIndex:
+ return K3bDataDoc::START;
+ case s_continueIndex:
+ return K3bDataDoc::CONTINUE;
+ case s_finishIndex:
+ return K3bDataDoc::FINISH;
+ default:
+ return K3bDataDoc::AUTO;
+ }
+}
+
+
+void K3bDataMultiSessionCombobox::saveConfig( KConfigBase* c )
+{
+ QString s;
+ switch( currentItem() ) {
+ case s_autoIndex:
+ s = "auto";
+ break;
+ case s_noneIndex:
+ s = "none";
+ break;
+ case s_startIndex:
+ s = "start";
+ break;
+ case s_continueIndex:
+ s = "continue";
+ break;
+ case s_finishIndex:
+ s = "finish";
+ break;
+ }
+
+ c->writeEntry( "multisession mode", s );
+}
+
+
+void K3bDataMultiSessionCombobox::loadConfig( KConfigBase* c )
+{
+ QString s = c->readEntry( "multisession mode" );
+ if( s == "none" )
+ setMultiSessionMode( K3bDataDoc::NONE );
+ else if( s == "start" )
+ setMultiSessionMode( K3bDataDoc::START );
+ else if( s == "continue" )
+ setMultiSessionMode( K3bDataDoc::CONTINUE );
+ else if( s == "finish" )
+ setMultiSessionMode( K3bDataDoc::FINISH );
+ else
+ setMultiSessionMode( K3bDataDoc::AUTO );
+}
+
+
+void K3bDataMultiSessionCombobox::setMultiSessionMode( K3bDataDoc::MultiSessionMode m )
+{
+ switch( m ) {
+ case K3bDataDoc::AUTO:
+ setCurrentItem( s_autoIndex );
+ break;
+ case K3bDataDoc::NONE:
+ setCurrentItem( s_noneIndex );
+ break;
+ case K3bDataDoc::START:
+ if( !m_forceNoMultiSession )
+ setCurrentItem( s_startIndex );
+ break;
+ case K3bDataDoc::CONTINUE:
+ if( !m_forceNoMultiSession )
+ setCurrentItem( s_continueIndex );
+ break;
+ case K3bDataDoc::FINISH:
+ if( !m_forceNoMultiSession )
+ setCurrentItem( s_finishIndex );
+ break;
+ }
+}
+
+
+void K3bDataMultiSessionCombobox::setForceNoMultisession( bool f )
+{
+ if( f != m_forceNoMultiSession ) {
+ K3bDataDoc::MultiSessionMode m = multiSessionMode();
+ init( f );
+ setMultiSessionMode( m );
+ }
+}
+
+#include "k3bdatamultisessioncombobox.moc"
diff --git a/src/projects/k3bdatamultisessioncombobox.h b/src/projects/k3bdatamultisessioncombobox.h
new file mode 100644
index 0000000..cb44989
--- /dev/null
+++ b/src/projects/k3bdatamultisessioncombobox.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * $Id: k3bdatamultisessioncombobox.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_DATA_MULTISESSION_COMBOBOX_H_
+#define _K3B_DATA_MULTISESSION_COMBOBOX_H_
+
+#include <qcombobox.h>
+#include <k3bdatadoc.h>
+
+class KConfigBase;
+
+
+class K3bDataMultiSessionCombobox : public QComboBox
+{
+ Q_OBJECT
+
+ public:
+ K3bDataMultiSessionCombobox( QWidget* parent = 0, const char* name = 0 );
+ ~K3bDataMultiSessionCombobox();
+
+ /**
+ * returnes K3bDataDoc::multiSessionModes
+ */
+ K3bDataDoc::MultiSessionMode multiSessionMode() const;
+
+ void setForceNoMultisession( bool );
+
+ void saveConfig( KConfigBase* );
+ void loadConfig( KConfigBase* );
+
+ public slots:
+ void setMultiSessionMode( K3bDataDoc::MultiSessionMode );
+
+ private:
+ void init( bool forceNo );
+
+ bool m_forceNoMultiSession;
+};
+
+#endif
diff --git a/src/projects/k3bdatapropertiesdialog.cpp b/src/projects/k3bdatapropertiesdialog.cpp
new file mode 100644
index 0000000..39fec61
--- /dev/null
+++ b/src/projects/k3bdatapropertiesdialog.cpp
@@ -0,0 +1,248 @@
+/*
+ *
+ * $Id: k3bdatapropertiesdialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdatapropertiesdialog.h"
+
+#include "k3bdiritem.h"
+#include "k3bfileitem.h"
+#include <kcutlabel.h>
+#include <k3bvalidators.h>
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qtabwidget.h>
+#include <qvalidator.h>
+
+#include <klineedit.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kurl.h>
+#include <kio/global.h>
+#include <kfileitem.h>
+
+
+
+K3bDataPropertiesDialog::K3bDataPropertiesDialog( K3bDataItem* dataItem, QWidget* parent, const char* name )
+ : KDialogBase( Plain, i18n("File Properties"), Ok|Cancel, Ok, parent, name, true, false )
+{
+ m_dataItem = dataItem;
+
+ QLabel* labelMimeType = new QLabel( plainPage() );
+ QLabel* extraInfoLabel = new QLabel( plainPage() );
+ m_editName = new KLineEdit( plainPage() );
+ m_labelType = new QLabel( plainPage() );
+ m_labelLocation = new KCutLabel( plainPage() );
+ m_labelSize = new QLabel( plainPage() );
+ m_labelBlocks = new QLabel( plainPage() );
+ m_labelLocalName = new KCutLabel( plainPage() );
+ m_labelLocalLocation = new KCutLabel( plainPage() );
+
+
+ QGridLayout* grid = new QGridLayout( plainPage() );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( marginHint() );
+
+ grid->addWidget( labelMimeType, 0, 0 );
+ grid->addWidget( m_editName, 0, 2 );
+ QFrame* line = new QFrame( plainPage() );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ grid->addMultiCellWidget( line, 1, 1, 0, 2 );
+ grid->addWidget( new QLabel( i18n("Type:"), plainPage() ), 2, 0 );
+ grid->addWidget( new QLabel( i18n("Location:"), plainPage() ), 4, 0 );
+ grid->addWidget( new QLabel( i18n("Size:"), plainPage() ), 5, 0 );
+ grid->addWidget( new QLabel( i18n("Used blocks:"), plainPage() ), 6, 0 );
+ grid->addWidget( m_labelType, 2, 2 );
+ grid->addWidget( extraInfoLabel, 3, 2 );
+ grid->addWidget( m_labelLocation, 4, 2 );
+ grid->addWidget( m_labelSize, 5, 2 );
+ grid->addWidget( m_labelBlocks, 6, 2 );
+ line = new QFrame( plainPage() );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ grid->addMultiCellWidget( line, 7, 7, 0, 2 );
+ QLabel* label1 = new QLabel( i18n("Local name:"), plainPage() );
+ grid->addWidget( label1, 8, 0 );
+ QLabel* label2 = new QLabel( i18n("Local location:"), plainPage() );
+ grid->addWidget( label2, 9, 0 );
+ grid->addWidget( m_labelLocalName, 8, 2 );
+ grid->addWidget( m_labelLocalLocation, 9, 2 );
+
+ grid->addColSpacing( 1, 50 );
+ grid->setColStretch( 2, 1 );
+
+
+
+ if( K3bFileItem* fileItem = dynamic_cast<K3bFileItem*>(dataItem) ) {
+ KFileItem kFileItem( KFileItem::Unknown, KFileItem::Unknown, KURL::fromPathOrURL(fileItem->localPath()) );
+ labelMimeType->setPixmap( kFileItem.pixmap(KIcon::SizeLarge) );
+ if( fileItem->isSymLink() )
+ m_labelType->setText( i18n("Link to %1").arg(kFileItem.mimeComment()) );
+ else
+ m_labelType->setText( kFileItem.mimeComment() );
+ m_labelLocalName->setText( kFileItem.name() );
+ QString localLocation = kFileItem.url().path(-1);
+ localLocation.truncate( localLocation.findRev('/') );
+ m_labelLocalLocation->setText( localLocation );
+ m_labelSize->setText( KIO::convertSize(dataItem->size()) );
+ }
+ else if( K3bDirItem* dirItem = dynamic_cast<K3bDirItem*>(dataItem) ) {
+ labelMimeType->setPixmap( KMimeType::pixmapForURL( KURL( "/" )) );
+ m_labelType->setText( i18n("Directory") );
+ label1->hide();
+ label2->hide();
+ m_labelLocalName->hide();
+ m_labelLocalLocation->hide();
+ line->hide();
+ m_labelSize->setText( KIO::convertSize(dataItem->size()) + "\n(" +
+ i18n("in 1 file", "in %n files", dirItem->numFiles()) + " " +
+ i18n("and 1 directory", "and %n directories", dirItem->numDirs()) + ")" );
+ }
+ else {
+ labelMimeType->setPixmap( DesktopIcon("unknown", KIcon::SizeLarge) );
+ m_labelType->setText( i18n("Special file") );
+ m_labelLocalName->hide();
+ m_labelLocalLocation->hide();
+ label1->hide();
+ label2->hide();
+ line->hide();
+ m_labelSize->setText( KIO::convertSize(dataItem->size()) );
+ }
+
+ m_editName->setText( dataItem->k3bName() );
+ m_labelBlocks->setText( QString::number(dataItem->blocks().lba()) );
+
+ QString location = "/" + dataItem->k3bPath();
+ if( location[location.length()-1] == '/' )
+ location.truncate( location.length()-1 );
+ location.truncate( location.findRev('/') );
+ if( location.isEmpty() )
+ location = "/";
+ m_labelLocation->setText( location );
+ extraInfoLabel->setText( QString( "(%1)" ).arg(dataItem->extraInfo()) );
+ if( dataItem->extraInfo().isEmpty() )
+ extraInfoLabel->hide();
+
+ // OPTIONS
+ // /////////////////////////////////////////////////
+ QTabWidget* optionTab = new QTabWidget( plainPage() );
+ line = new QFrame( plainPage() );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+
+ grid->addMultiCellWidget( line, 10, 10, 0, 2 );
+ grid->addMultiCellWidget( optionTab, 12, 12, 0, 2 );
+ grid->setRowStretch( 11, 1 );
+
+ QWidget* hideBox = new QWidget( optionTab );
+ QGridLayout* hideBoxGrid = new QGridLayout( hideBox );
+ hideBoxGrid->setSpacing( spacingHint() );
+ hideBoxGrid->setMargin( marginHint() );
+ m_checkHideOnRockRidge = new QCheckBox( i18n("Hide on Rockridge"), hideBox );
+ m_checkHideOnJoliet = new QCheckBox( i18n("Hide on Joliet"), hideBox );
+ hideBoxGrid->addWidget( m_checkHideOnRockRidge, 0, 0 );
+ hideBoxGrid->addWidget( m_checkHideOnJoliet, 1, 0 );
+ hideBoxGrid->setRowStretch( 2, 1 );
+// grid->addMultiCellWidget( m_checkHideOnRockRidge, 10, 10, 0, 2 );
+// grid->addMultiCellWidget( m_checkHideOnJoliet, 11, 11, 0, 2 );
+
+ QWidget* sortingBox = new QWidget( optionTab );
+ QGridLayout* sortingBoxGrid = new QGridLayout( sortingBox );
+ sortingBoxGrid->setSpacing( spacingHint() );
+ sortingBoxGrid->setMargin( marginHint() );
+ m_editSortWeight = new KLineEdit( sortingBox );
+ m_editSortWeight->setValidator( new QIntValidator( -2147483647, 2147483647, m_editSortWeight ) );
+ m_editSortWeight->setAlignment( Qt::AlignRight );
+ sortingBoxGrid->addWidget( new QLabel( i18n("Sort weight:"), sortingBox ), 0, 0 );
+ sortingBoxGrid->addWidget( m_editSortWeight, 0, 1 );
+ sortingBoxGrid->setColStretch( 1, 1 );
+ sortingBoxGrid->setRowStretch( 1, 1 );
+
+ optionTab->addTab( hideBox, i18n("Settings") );
+ optionTab->addTab( sortingBox, i18n("Advanced") );
+
+
+ m_checkHideOnJoliet->setChecked( dataItem->hideOnJoliet() );
+ m_checkHideOnRockRidge->setChecked( dataItem->hideOnRockRidge() );
+ m_editSortWeight->setText( QString::number(dataItem->sortWeight()) );
+
+ // if the parent is hidden the value cannot be changed (see K3bDataItem::setHide...)
+ if( dataItem->parent() ) {
+ m_checkHideOnRockRidge->setDisabled( dataItem->parent()->hideOnRockRidge() );
+ m_checkHideOnJoliet->setDisabled( dataItem->parent()->hideOnJoliet() );
+ }
+
+ if( !dataItem->isHideable() ) {
+ m_checkHideOnJoliet->setDisabled(true);
+ m_checkHideOnRockRidge->setDisabled(true);
+ // line->hide();
+ }
+
+ QToolTip::add( m_checkHideOnRockRidge, i18n("Hide this file in the RockRidge filesystem") );
+ QToolTip::add( m_checkHideOnJoliet, i18n("Hide this file in the Joliet filesystem") );
+ QToolTip::add( m_editSortWeight, i18n("Modify the physical sorting") );
+ QWhatsThis::add( m_checkHideOnRockRidge, i18n("<p>If this option is checked, the file or directory "
+ "(and its entire contents) will be hidden on the "
+ "ISO9660 and RockRidge filesystem.</p>"
+ "<p>This is useful, for example, for having different README "
+ "files for RockRidge and Joliet, which can be managed "
+ "by hiding README.joliet on RockRidge and README.rr "
+ "on the Joliet filesystem.</p>") );
+ QWhatsThis::add( m_checkHideOnJoliet, i18n("<p>If this option is checked, the file or directory "
+ "(and its entire contents) will be hidden on the "
+ "Joliet filesystem.</p>"
+ "<p>This is useful, for example, for having different README "
+ "files for RockRidge and Joliet, which can be managed "
+ "by hiding README.joliet on RockRidge and README.rr "
+ "on the Joliet filesystem.</p>") );
+ QWhatsThis::add( m_editSortWeight, i18n("<p>This value modifies the physical sort order of the files "
+ "in the ISO9660 filesystem. A higher weighting means that the "
+ "file will be located closer to the beginning of the image "
+ "(and the disk)."
+ "<p>This option is useful in order to optimize the data layout "
+ "on a CD/DVD."
+ "<p><b>Caution:</b> This does not sort the order of the file "
+ "names that appear in the ISO9660 directory."
+ "It sorts the order in which the file data is "
+ "written to the image.") );
+
+ m_editName->setValidator( K3bValidators::iso9660Validator( false, this ) );
+ m_editName->setReadOnly( !dataItem->isRenameable() );
+ m_editName->setFocus();
+}
+
+
+K3bDataPropertiesDialog::~K3bDataPropertiesDialog()
+{
+}
+
+
+void K3bDataPropertiesDialog::slotOk()
+{
+ // save filename
+ m_dataItem->setK3bName( m_editName->text() );
+ m_dataItem->setHideOnRockRidge( m_checkHideOnRockRidge->isChecked() );
+ m_dataItem->setHideOnJoliet( m_checkHideOnJoliet->isChecked() );
+ m_dataItem->setSortWeight( m_editSortWeight->text().toInt() );
+
+ KDialogBase::slotOk();
+}
+
+
+#include "k3bdatapropertiesdialog.moc"
diff --git a/src/projects/k3bdatapropertiesdialog.h b/src/projects/k3bdatapropertiesdialog.h
new file mode 100644
index 0000000..eb585ce
--- /dev/null
+++ b/src/projects/k3bdatapropertiesdialog.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * $Id: k3bdatapropertiesdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDATAPROPERTIESDIALOG_H
+#define K3BDATAPROPERTIESDIALOG_H
+
+#include <kdialogbase.h>
+
+class K3bDataItem;
+
+class KLineEdit;
+class QPushButton;
+class QLabel;
+class QCheckBox;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bDataPropertiesDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ K3bDataPropertiesDialog( K3bDataItem*, QWidget* parent = 0, const char* name = 0 );
+ ~K3bDataPropertiesDialog();
+
+ protected slots:
+ void slotOk();
+
+ private:
+ KLineEdit* m_editName;
+ QLabel* m_labelType;
+ QLabel* m_labelLocation;
+ QLabel* m_labelSize;
+ QLabel* m_labelBlocks;
+
+ QLabel* m_labelLocalName;
+ QLabel* m_labelLocalLocation;
+
+ QCheckBox* m_checkHideOnRockRidge;
+ QCheckBox* m_checkHideOnJoliet;
+ KLineEdit* m_editSortWeight;
+
+ K3bDataItem* m_dataItem;
+};
+
+#endif
diff --git a/src/projects/k3bdatasessionimportdialog.cpp b/src/projects/k3bdatasessionimportdialog.cpp
new file mode 100644
index 0000000..f6f1b85
--- /dev/null
+++ b/src/projects/k3bdatasessionimportdialog.cpp
@@ -0,0 +1,137 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdatasessionimportdialog.h"
+#include "k3bmediaselectioncombobox.h"
+
+#include <k3bdatadoc.h>
+#include <k3bapplication.h>
+#include <k3biso9660.h>
+#include <k3bmediacache.h>
+#include <k3b.h>
+
+#include <qpushbutton.h>
+#include <qcursor.h>
+#include <qapplication.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+
+
+K3bDataSessionImportDialog::K3bDataSessionImportDialog( QWidget* parent )
+ : KDialogBase( parent,
+ "session_import_dialog",
+ true,
+ i18n("Session Import"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok,
+ false )
+{
+ m_comboMedia = new K3bMediaSelectionComboBox( this );
+ setMainWidget( m_comboMedia );
+
+ connect( m_comboMedia, SIGNAL(selectionChanged(K3bDevice::Device*)),
+ this, SLOT(slotSelectionChanged(K3bDevice::Device*)) );
+}
+
+
+K3bDataSessionImportDialog::~K3bDataSessionImportDialog()
+{
+}
+
+
+void K3bDataSessionImportDialog::importSession( K3bDataDoc* doc )
+{
+ m_doc = doc;
+
+ if( doc ) {
+ m_comboMedia->setWantedMediumType( m_doc->type() == K3bDoc::DVD
+ ? K3bDevice::MEDIA_WRITABLE_DVD
+ : K3bDevice::MEDIA_WRITABLE_CD );
+ }
+ else
+ m_comboMedia->setWantedMediumType( K3bDevice::MEDIA_WRITABLE );
+
+ m_comboMedia->setWantedMediumState( K3bDevice::STATE_INCOMPLETE );
+
+ slotSelectionChanged( m_comboMedia->selectedDevice() );
+}
+
+
+void K3bDataSessionImportDialog::slotOk()
+{
+ // find the selected device, show a busy mouse cursor and call K3bDataDoc::importSession
+ if( K3bDevice::Device* dev = m_comboMedia->selectedDevice() ) {
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+
+ //
+ // Mkisofs does not properly import joliet filenames from an old session
+ //
+ // See bug 79215 for details
+ //
+ K3bIso9660 iso( dev );
+ if( iso.open() ) {
+ if( iso.firstRRDirEntry() == 0 && iso.jolietLevel() > 0 )
+ KMessageBox::sorry( this,
+ i18n("<p>K3b found session containing Joliet information for long filenames "
+ "but no Rock Ridge extensions."
+ "<p>The filenames in the imported session will be converted to a restricted "
+ "character set in the new session. This character set is based on the ISO9660 "
+ "settings in the K3b project. K3b is not able to display these converted filenames yet."),
+ i18n("Session Import Warning") );
+ iso.close();
+ }
+
+ if( !m_doc ) {
+ if( k3bappcore->mediaCache()->diskInfo( dev ).isDvdMedia() )
+ m_doc = static_cast<K3bDataDoc*>( k3bappcore->k3bMainWindow()->slotNewDvdDoc() );
+ else
+ m_doc = static_cast<K3bDataDoc*>( k3bappcore->k3bMainWindow()->slotNewDataDoc() );
+ }
+
+ m_doc->setBurner( dev );
+ m_doc->importSession( dev );
+
+ QApplication::restoreOverrideCursor();
+
+ done( 0 );
+ }
+ else
+ done( 1 );
+}
+
+
+void K3bDataSessionImportDialog::slotCancel()
+{
+ KDialogBase::slotCancel();
+}
+
+
+void K3bDataSessionImportDialog::slotSelectionChanged( K3bDevice::Device* dev )
+{
+ actionButton( KDialogBase::Ok )->setEnabled( dev != 0 );
+}
+
+
+K3bDataDoc* K3bDataSessionImportDialog::importSession( K3bDataDoc* doc, QWidget* parent )
+{
+ K3bDataSessionImportDialog dlg( parent );
+ dlg.importSession( doc );
+ dlg.exec();
+ return dlg.m_doc;
+}
+
+
+#include "k3bdatasessionimportdialog.moc"
diff --git a/src/projects/k3bdatasessionimportdialog.h b/src/projects/k3bdatasessionimportdialog.h
new file mode 100644
index 0000000..77c074f
--- /dev/null
+++ b/src/projects/k3bdatasessionimportdialog.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_SESSION_IMPORT_DIALOG_H_
+#define _K3B_SESSION_IMPORT_DIALOG_H_
+
+#include <kdialogbase.h>
+
+#include <qptrlist.h>
+#include <qmap.h>
+
+#include <k3bdevice.h>
+
+
+class QLabel;
+class KListBox;
+class K3bDataDoc;
+class K3bMediaSelectionComboBox;
+
+
+class K3bDataSessionImportDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Import a session into the project.
+ * If the project is a DVD data project only DVD media are
+ * presented for selection.
+ *
+ * \param doc if 0 a new project will be created.
+ *
+ * \return the project
+ */
+ static K3bDataDoc* importSession( K3bDataDoc* doc, QWidget* parent );
+
+ private slots:
+ void slotOk();
+ void slotCancel();
+
+ void importSession( K3bDataDoc* doc );
+ void slotSelectionChanged( K3bDevice::Device* );
+
+ private:
+ K3bDataSessionImportDialog( QWidget* parent = 0 );
+ ~K3bDataSessionImportDialog();
+
+ K3bDataDoc* m_doc;
+ K3bMediaSelectionComboBox* m_comboMedia;
+};
+
+#endif
diff --git a/src/projects/k3bdataurladdingdialog.cpp b/src/projects/k3bdataurladdingdialog.cpp
new file mode 100644
index 0000000..2edb43b
--- /dev/null
+++ b/src/projects/k3bdataurladdingdialog.cpp
@@ -0,0 +1,826 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <k3bglobals.h>
+
+#include "k3bdataurladdingdialog.h"
+#include "k3bencodingconverter.h"
+
+#include <qtimer.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+
+#include <k3bdatadoc.h>
+#include <k3bdiritem.h>
+#include <k3bcore.h>
+#include <k3bfileitem.h>
+#include <k3bmultichoicedialog.h>
+#include <k3bvalidators.h>
+#include <k3bglobals.h>
+#include <k3bisooptions.h>
+#include <k3b.h>
+#include <k3bapplication.h>
+#include <k3biso9660.h>
+#include <k3bdirsizejob.h>
+#include <k3binteractiondialog.h>
+#include <k3bthread.h>
+#include <k3bsignalwaiter.h>
+#include <k3bexternalbinmanager.h>
+
+#include <klocale.h>
+#include <kurl.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kstdguiitem.h>
+#include <kconfig.h>
+#include <ksqueezedtextlabel.h>
+#include <kprogress.h>
+
+#include <unistd.h>
+
+
+K3bDataUrlAddingDialog::K3bDataUrlAddingDialog( K3bDataDoc* doc, QWidget* parent, const char* name )
+ : KDialogBase( Plain,
+ i18n("Adding files to project '%1'").arg(doc->URL().fileName()),
+ Cancel,
+ Cancel,
+ parent,
+ name,
+ true,
+ true ),
+ m_bExistingItemsReplaceAll(false),
+ m_bExistingItemsIgnoreAll(false),
+ m_bFolderLinksFollowAll(false),
+ m_bFolderLinksAddAll(false),
+ m_iAddHiddenFiles(0),
+ m_iAddSystemFiles(0),
+ m_bCanceled(false),
+ m_totalFiles(0),
+ m_filesHandled(0),
+ m_lastProgress(0)
+{
+ m_encodingConverter = new K3bEncodingConverter();
+
+ QWidget* page = plainPage();
+ QGridLayout* grid = new QGridLayout( page );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( 0 );
+
+ m_counterLabel = new QLabel( page );
+ m_infoLabel = new KSqueezedTextLabel( i18n("Adding files to project '%1'")
+ .arg(doc->URL().fileName()) + "...", page );
+ m_progressWidget = new KProgress( 0, page );
+
+ grid->addWidget( m_counterLabel, 0, 1 );
+ grid->addWidget( m_infoLabel, 0, 0 );
+ grid->addMultiCellWidget( m_progressWidget, 1, 1, 0, 1 );
+
+ m_dirSizeJob = new K3bDirSizeJob( this );
+ connect( m_dirSizeJob, SIGNAL(finished(bool)),
+ this, SLOT(slotDirSizeDone(bool)) );
+
+ // try to start with a reasonable size
+ resize( (int)( fontMetrics().width( caption() ) * 1.5 ), sizeHint().height() );
+}
+
+
+K3bDataUrlAddingDialog::~K3bDataUrlAddingDialog()
+{
+ delete m_encodingConverter;
+}
+
+
+int K3bDataUrlAddingDialog::addUrls( const KURL::List& urls,
+ K3bDirItem* dir,
+ QWidget* parent )
+{
+ if( urls.isEmpty() )
+ return 0;
+
+ //
+ // A common mistake by beginners is to try to burn an iso image
+ // with a data project. Let's warn them
+ //
+ if( urls.count() == 1 ) {
+ K3bIso9660 isoF( urls.first().path() );
+ if( isoF.open() ) {
+ if( KMessageBox::warningYesNo( parent,
+ i18n("<p>The file you are about to add to the project is an ISO9660 image. As such "
+ "it can be burned to a medium directly since it already contains a file "
+ "system.<br>"
+ "Are you sure you want to add this file to the project?"),
+ i18n("Adding image file to project"),
+ i18n("Add the file to the project"),
+ i18n("Burn the image directly") ) == KMessageBox::No ) {
+ // very rough dvd image size test
+ if( K3b::filesize( urls.first() ) > 1000*1024*1024 )
+ k3bappcore->k3bMainWindow()->slotWriteDvdIsoImage( urls.first() );
+ else
+ k3bappcore->k3bMainWindow()->slotWriteCdImage( urls.first() );
+ return 0;
+ }
+ }
+ }
+
+ K3bDataUrlAddingDialog dlg( dir->doc(), parent );
+ dlg.m_urls = urls;
+ for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it )
+ dlg.m_urlQueue.append( qMakePair( K3b::convertToLocalUrl(*it), dir ) );
+
+ dlg.slotAddUrls();
+ int ret = QDialog::Accepted;
+ if( !dlg.m_urlQueue.isEmpty() ) {
+ dlg.m_dirSizeJob->setUrls( urls );
+ dlg.m_dirSizeJob->setFollowSymlinks( dir->doc()->isoOptions().followSymbolicLinks() );
+ dlg.m_dirSizeJob->start();
+ ret = dlg.exec();
+ }
+
+ // make sure the dir size job is finished
+ dlg.m_dirSizeJob->cancel();
+ K3bSignalWaiter::waitForJob( dlg.m_dirSizeJob );
+
+ QString message = dlg.resultMessage();
+ if( !message.isEmpty() )
+ KMessageBox::detailedSorry( parent, i18n("Problems while adding files to the project."), message );
+
+ return ret;
+}
+
+
+QString K3bDataUrlAddingDialog::resultMessage() const
+{
+ QString message;
+ if( !m_unreadableFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("Insufficient permissions to read the following files") )
+ .arg( m_unreadableFiles.join( "<br>" ) );
+ if( !m_notFoundFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("Unable to find the following files") )
+ .arg( m_notFoundFiles.join( "<br>" ) );
+ if( !m_nonLocalFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("No non-local files supported") )
+ .arg( m_unreadableFiles.join( "<br>" ) );
+ if( !m_tooBigFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("It is not possible to add files bigger than %1").arg(KIO::convertSize(0xFFFFFFFF)) )
+ .arg( m_tooBigFiles.join( "<br>" ) );
+ if( !m_mkisofsLimitationRenamedFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("Some filenames had to be modified due to limitations in mkisofs") )
+ .arg( m_mkisofsLimitationRenamedFiles.join( "<br>" ) );
+ if( !m_invalidFilenameEncodingFiles.isEmpty() )
+ message += QString("<p><b>%1:</b><br>%2")
+ .arg( i18n("The following filenames have an invalid encoding. You may fix this "
+ "with the convmv tool") )
+ .arg( m_invalidFilenameEncodingFiles.join( "<br>" ) );
+
+ return message;
+}
+
+
+int K3bDataUrlAddingDialog::moveItems( const QValueList<K3bDataItem*>& items,
+ K3bDirItem* dir,
+ QWidget* parent )
+{
+ return copyMoveItems( items, dir, parent, false );
+}
+
+
+int K3bDataUrlAddingDialog::copyItems( const QValueList<K3bDataItem*>& items,
+ K3bDirItem* dir,
+ QWidget* parent )
+{
+ return copyMoveItems( items, dir, parent, true );
+}
+
+
+int K3bDataUrlAddingDialog::copyMoveItems( const QValueList<K3bDataItem*>& items,
+ K3bDirItem* dir,
+ QWidget* parent,
+ bool copy )
+{
+ if( items.isEmpty() )
+ return 0;
+
+ K3bDataUrlAddingDialog dlg( dir->doc(), parent );
+ dlg.m_infoLabel->setText( i18n("Moving files to project \"%1\"...").arg(dir->doc()->URL().fileName()) );
+ dlg.m_copyItems = copy;
+
+ for( QValueList<K3bDataItem*>::const_iterator it = items.begin(); it != items.end(); ++it ) {
+ dlg.m_items.append( qMakePair( *it, dir ) );
+ ++dlg.m_totalFiles;
+ if( (*it)->isDir() ) {
+ dlg.m_totalFiles += static_cast<K3bDirItem*>( *it )->numFiles();
+ dlg.m_totalFiles += static_cast<K3bDirItem*>( *it )->numDirs();
+ }
+ }
+
+ dlg.slotCopyMoveItems();
+ int ret = QDialog::Accepted;
+ if( !dlg.m_items.isEmpty() ) {
+ dlg.m_progressWidget->setTotalSteps( dlg.m_totalFiles );
+ ret = dlg.exec();
+ }
+
+ return ret;
+}
+
+
+void K3bDataUrlAddingDialog::slotCancel()
+{
+ m_bCanceled = true;
+ m_dirSizeJob->cancel();
+ KDialogBase::slotCancel();
+}
+
+
+void K3bDataUrlAddingDialog::slotAddUrls()
+{
+ if( m_bCanceled )
+ return;
+
+ // add next url
+ KURL url = m_urlQueue.first().first;
+ K3bDirItem* dir = m_urlQueue.first().second;
+ m_urlQueue.remove( m_urlQueue.begin() );
+ //
+ // HINT:
+ // we only use QFileInfo::absFilePath() and QFileInfo::isHidden()
+ // both do not cause QFileInfo to stat, thus no speed improvement
+ // can come from removing QFileInfo usage here.
+ //
+ QFileInfo info(url.path());
+ QString absFilePath( info.absFilePath() );
+ QString resolved( absFilePath );
+
+ bool valid = true;
+ k3b_struct_stat statBuf, resolvedStatBuf;
+ bool isSymLink = false;
+ bool isDir = false;
+ bool isFile = false;
+
+ ++m_filesHandled;
+
+#if 0
+ m_infoLabel->setText( url.path() );
+ if( m_totalFiles == 0 )
+ m_counterLabel->setText( QString("(%1)").arg(m_filesHandled) );
+ else
+ m_counterLabel->setText( QString("(%1/%2)").arg(m_filesHandled).arg(m_totalFiles) );
+#endif
+
+ //
+ // 1. Check if we want and can add the url
+ //
+
+ if( !url.isLocalFile() ) {
+ valid = false;
+ m_nonLocalFiles.append( url.path() );
+ }
+
+ else if( k3b_lstat( QFile::encodeName(absFilePath), &statBuf ) != 0 ) {
+ valid = false;
+ m_notFoundFiles.append( url.path() );
+ }
+
+ else if( !m_encodingConverter->encodedLocally( QFile::encodeName( url.path() ) ) ) {
+ valid = false;
+ m_invalidFilenameEncodingFiles.append( url.path() );
+ }
+
+ else {
+ isSymLink = S_ISLNK(statBuf.st_mode);
+ isFile = S_ISREG(statBuf.st_mode);
+ isDir = S_ISDIR(statBuf.st_mode);
+
+ // symlinks are always readable and can always be added to a project
+ // but we need to know if the symlink points to a directory
+ if( isSymLink ) {
+ resolved = K3b::resolveLink( absFilePath );
+ k3b_stat( QFile::encodeName(resolved), &resolvedStatBuf );
+ isDir = S_ISDIR(resolvedStatBuf.st_mode);
+ }
+
+ else {
+ if( ::access( QFile::encodeName( absFilePath ), R_OK ) != 0 ) {
+ valid = false;
+ m_unreadableFiles.append( url.path() );
+ }
+ else if( isFile && (unsigned long long)statBuf.st_size >= 0xFFFFFFFFULL ) {
+ if ( !k3bcore->externalBinManager()->binObject( "mkisofs" )->hasFeature( "no-4gb-limit" ) ) {
+ valid = false;
+ m_tooBigFiles.append( url.path() );
+ }
+ }
+ }
+
+ // FIXME: if we do not add hidden dirs the progress gets messed up!
+
+ //
+ // check for hidden and system files
+ //
+ if( valid ) {
+ if( info.isHidden() && !addHiddenFiles() )
+ valid = false;
+ if( S_ISCHR(statBuf.st_mode) ||
+ S_ISBLK(statBuf.st_mode) ||
+ S_ISFIFO(statBuf.st_mode) ||
+ S_ISSOCK(statBuf.st_mode) )
+ if( !addSystemFiles() )
+ valid = false;
+ if( isSymLink )
+ if( S_ISCHR(resolvedStatBuf.st_mode) ||
+ S_ISBLK(resolvedStatBuf.st_mode) ||
+ S_ISFIFO(resolvedStatBuf.st_mode) ||
+ S_ISSOCK(resolvedStatBuf.st_mode) )
+ if( !addSystemFiles() )
+ valid = false;
+ }
+ }
+
+
+ //
+ // 2. Handle the url
+ //
+
+ QString newName = url.fileName();
+
+ // filenames cannot end in backslashes (mkisofs problem. See comments in k3bisoimager.cpp (escapeGraftPoint()))
+ bool bsAtEnd = false;
+ while( newName[newName.length()-1] == '\\' ) {
+ newName.truncate( newName.length()-1 );
+ bsAtEnd = true;
+ }
+ if( bsAtEnd )
+ m_mkisofsLimitationRenamedFiles.append( url.path() + " -> " + newName );
+
+ // backup dummy name
+ if( newName.isEmpty() )
+ newName = "1";
+
+ K3bDirItem* newDirItem = 0;
+
+ //
+ // The source is valid. Now check if the project already contains a file with that name
+ // and if so handle it properly
+ //
+ if( valid ) {
+ if( K3bDataItem* oldItem = dir->find( newName ) ) {
+ //
+ // reuse an existing dir
+ //
+ if( oldItem->isDir() && isDir )
+ newDirItem = dynamic_cast<K3bDirItem*>(oldItem);
+
+ //
+ // we cannot replace files in the old session with dirs and vice versa (I think)
+ // files are handled in K3bFileItem constructor and dirs handled above
+ //
+ else if( oldItem->isFromOldSession() &&
+ isDir != oldItem->isDir() ) {
+ if( !getNewName( newName, dir, newName ) )
+ valid = false;
+ }
+
+ else if( m_bExistingItemsIgnoreAll )
+ valid = false;
+
+ else if( oldItem->localPath() == resolved ) {
+ //
+ // Just ignore if the same file is added again
+ //
+ valid = false;
+ }
+
+ else if( m_bExistingItemsReplaceAll ) {
+ // if we replace an item from an old session the K3bFileItem constructor takes care
+ // of replacing the item
+ if( !oldItem->isFromOldSession() )
+ delete oldItem;
+ }
+
+ //
+ // Let the user choose
+ //
+ else {
+ switch( K3bMultiChoiceDialog::choose( i18n("File already exists"),
+ i18n("<p>File <em>%1</em> already exists in "
+ "project folder <em>%2</em>.")
+ .arg(newName)
+ .arg('/' + dir->k3bPath()),
+ QMessageBox::Warning,
+ this,
+ 0,
+ 6,
+ KGuiItem( i18n("Replace"),
+ QString::null,
+ i18n("Replace the existing file") ),
+ KGuiItem( i18n("Replace All"),
+ QString::null,
+ i18n("Always replace existing files") ),
+ KGuiItem( i18n("Ignore"),
+ QString::null,
+ i18n("Keep the existing file") ),
+ KGuiItem( i18n("Ignore All"),
+ QString::null,
+ i18n("Always keep the existing file") ),
+ KGuiItem( i18n("Rename"),
+ QString::null,
+ i18n("Rename the new file") ),
+ KStdGuiItem::cancel() ) ) {
+ case 2: // replace all
+ m_bExistingItemsReplaceAll = true;
+ // fallthrough
+ case 1: // replace
+ // if we replace an item from an old session the K3bFileItem constructor takes care
+ // of replacing the item
+ if( !oldItem->isFromOldSession() )
+ delete oldItem;
+ break;
+ case 4: // ignore all
+ m_bExistingItemsIgnoreAll = true;
+ // fallthrough
+ case 3: // ignore
+ valid = false;
+ break;
+ case 5: // rename
+ if( !getNewName( newName, dir, newName ) )
+ valid = false;
+ break;
+ case 6: // cancel
+ slotCancel();
+ return;
+ }
+ }
+ }
+ }
+
+
+ //
+ // One more thing to warn the user about: We cannot follow links to folders since that
+ // would change the doc. So we simply ask the user what to do with a link to a folder
+ //
+ if( valid ) {
+ // let's see if this link starts a loop
+ // that means if it points to some folder above this one
+ // if so we cannot follow it anyway
+ if( isDir && isSymLink && !absFilePath.startsWith( resolved ) ) {
+ bool followLink = dir->doc()->isoOptions().followSymbolicLinks() || m_bFolderLinksFollowAll;
+ if( !followLink && !m_bFolderLinksAddAll ) {
+ switch( K3bMultiChoiceDialog::choose( i18n("Adding link to folder"),
+ i18n("<p>'%1' is a symbolic link to folder '%2'."
+ "<p>If you intend to make K3b follow symbolic links you should consider letting K3b do this now "
+ "since K3b will not be able to do so afterwards because symbolic links to folders inside a "
+ "K3b project cannot be resolved."
+ "<p><b>If you do not intend to enable the option <em>follow symbolic links</em> you may safely "
+ "ignore this warning and choose to add the link to the project.</b>")
+ .arg(absFilePath)
+ .arg(resolved ),
+ QMessageBox::Warning,
+ this,
+ 0,
+ 5,
+ i18n("Follow link now"),
+ i18n("Always follow links"),
+ i18n("Add link to project"),
+ i18n("Always add links"),
+ KStdGuiItem::cancel() ) ) {
+ case 2:
+ m_bFolderLinksFollowAll = true;
+ case 1:
+ followLink = true;
+ break;
+ case 4:
+ m_bFolderLinksAddAll = true;
+ case 3:
+ followLink = false;
+ break;
+ case 5:
+ slotCancel();
+ return;
+ }
+ }
+
+ if( followLink ) {
+ absFilePath = resolved;
+ isSymLink = false;
+
+ // count the files in the followed dir
+ if( m_dirSizeJob->active() )
+ m_dirSizeQueue.append( KURL::fromPathOrURL(absFilePath) );
+ else {
+ m_progressWidget->setTotalSteps( 0 );
+ m_dirSizeJob->setUrls( KURL::fromPathOrURL(absFilePath) );
+ m_dirSizeJob->start();
+ }
+ }
+ }
+ }
+
+
+ //
+ // Project valid also (we overwrite or renamed)
+ // now create the new item
+ //
+ if( valid ) {
+ //
+ // Set the volume id from the first added url
+ // only if the doc was not changed yet
+ //
+ if( m_urls.count() == 1 &&
+ !dir->doc()->isModified() &&
+ !dir->doc()->isSaved() ) {
+ dir->doc()->setVolumeID( K3b::removeFilenameExtension( newName ) );
+ }
+
+ if( isDir && !isSymLink ) {
+ if( !newDirItem ) { // maybe we reuse an already existing dir
+ newDirItem = new K3bDirItem( newName , dir->doc(), dir );
+ newDirItem->setLocalPath( url.path() ); // HACK: see k3bdiritem.h
+ }
+
+ QDir newDir( absFilePath );
+ int dirFilter = QDir::All|QDir::Hidden|QDir::System;
+
+ QStringList dlist = newDir.entryList( dirFilter );
+ const QString& dot = KGlobal::staticQString( "." );
+ const QString& dotdot = KGlobal::staticQString( ".." );
+ dlist.remove( dot );
+ dlist.remove( dotdot );
+
+ for( QStringList::Iterator it = dlist.begin(); it != dlist.end(); ++it ) {
+ m_urlQueue.append( qMakePair( KURL::fromPathOrURL(absFilePath + '/' + *it), newDirItem ) );
+ }
+ }
+ else {
+ (void)new K3bFileItem( &statBuf, &resolvedStatBuf, url.path(), dir->doc(), dir, newName );
+ }
+ }
+
+ if( m_urlQueue.isEmpty() ) {
+ m_dirSizeJob->cancel();
+ m_progressWidget->setProgress( 100 );
+ accept();
+ }
+ else {
+ updateProgress();
+ QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
+ }
+}
+
+
+void K3bDataUrlAddingDialog::slotCopyMoveItems()
+{
+ if( m_bCanceled )
+ return;
+
+ //
+ // Pop first item from the item list
+ //
+ K3bDataItem* item = m_items.first().first;
+ K3bDirItem* dir = m_items.first().second;
+ m_items.remove( m_items.begin() );
+
+ ++m_filesHandled;
+ m_infoLabel->setText( item->k3bPath() );
+ if( m_totalFiles == 0 )
+ m_counterLabel->setText( QString("(%1)").arg(m_filesHandled) );
+ else
+ m_counterLabel->setText( QString("(%1/%2)").arg(m_filesHandled).arg(m_totalFiles) );
+
+
+ if( dir == item->parent() ) {
+ kdDebug() << "(K3bDataUrlAddingDialog) trying to move an item into its own parent dir." << endl;
+ }
+ else if( dir == item ) {
+ kdDebug() << "(K3bDataUrlAddingDialog) trying to move an item into itselft." << endl;
+ }
+ else {
+ //
+ // Let's see if an item with that name alredy exists
+ //
+ if( K3bDataItem* oldItem = dir->find( item->k3bName() ) ) {
+ //
+ // reuse an existing dir: move all child items into the old dir
+ //
+ if( oldItem->isDir() && item->isDir() ) {
+ const QPtrList<K3bDataItem>& cl = dynamic_cast<K3bDirItem*>( item )->children();
+ for( QPtrListIterator<K3bDataItem> it( cl ); *it; ++it )
+ m_items.append( qMakePair( *it, dynamic_cast<K3bDirItem*>( oldItem ) ) );
+
+ // FIXME: we need to remove the old dir item
+ }
+
+ //
+ // we cannot replace files in the old session with dirs and vice versa (I think)
+ // files are handled in K3bFileItem constructor and dirs handled above
+ //
+ else if( oldItem->isFromOldSession() &&
+ item->isDir() != oldItem->isDir() ) {
+ QString newName;
+ if( getNewName( newName, dir, newName ) ) {
+ if( m_copyItems )
+ item = item->copy();
+ item->setK3bName( newName );
+ dir->addDataItem( item );
+ }
+ }
+
+ else if( m_bExistingItemsReplaceAll ) {
+ //
+ // if we replace an item from an old session K3bDirItem::addDataItem takes care
+ // of replacing the item
+ //
+ if( !oldItem->isFromOldSession() )
+ delete oldItem;
+ if( m_copyItems )
+ item = item->copy();
+ dir->addDataItem( item );
+ }
+
+ else if( !m_bExistingItemsIgnoreAll ) {
+ switch( K3bMultiChoiceDialog::choose( i18n("File already exists"),
+ i18n("<p>File <em>%1</em> already exists in "
+ "project folder <em>%2</em>.")
+ .arg( item->k3bName() )
+ .arg("/" + dir->k3bPath()),
+ QMessageBox::Warning,
+ this,
+ 0,
+ 6,
+ KGuiItem( i18n("Replace"),
+ QString::null,
+ i18n("Replace the existing file") ),
+ KGuiItem( i18n("Replace All"),
+ QString::null,
+ i18n("Always replace existing files") ),
+ KGuiItem( i18n("Ignore"),
+ QString::null,
+ i18n("Keep the existing file") ),
+ KGuiItem( i18n("Ignore All"),
+ QString::null,
+ i18n("Always keep the existing file") ),
+ KGuiItem( i18n("Rename"),
+ QString::null,
+ i18n("Rename the new file") ),
+ KStdGuiItem::cancel() ) ) {
+ case 2: // replace all
+ m_bExistingItemsReplaceAll = true;
+ // fallthrough
+ case 1: // replace
+ //
+ // if we replace an item from an old session K3bDirItem::addDataItem takes care
+ // of replacing the item
+ //
+ if( !oldItem->isFromOldSession() )
+ delete oldItem;
+ if( m_copyItems )
+ item = item->copy();
+ dir->addDataItem( item );
+ break;
+ case 4: // ignore all
+ m_bExistingItemsIgnoreAll = true;
+ // fallthrough
+ case 3: // ignore
+ // do nothing
+ break;
+ case 5: {// rename
+ QString newName;
+ if( getNewName( newName, dir, newName ) ) {
+ if( m_copyItems )
+ item = item->copy();
+ item->setK3bName( newName );
+ dir->addDataItem( item );
+ }
+ break;
+ }
+ case 6: // cancel
+ slotCancel();
+ return;
+ }
+ }
+ }
+
+ //
+ // No old item with the same name
+ //
+ else {
+ if( m_copyItems )
+ item = item->copy();
+ dir->addDataItem( item );
+ }
+ }
+
+ if( m_items.isEmpty() ) {
+ m_dirSizeJob->cancel();
+ accept();
+ }
+ else {
+ updateProgress();
+ QTimer::singleShot( 0, this, SLOT(slotCopyMoveItems()) );
+ }
+}
+
+
+bool K3bDataUrlAddingDialog::getNewName( const QString& oldName, K3bDirItem* dir, QString& newName )
+{
+ bool ok = true;
+ newName = oldName;
+ QValidator* validator = K3bValidators::iso9660Validator( false, this );
+ do {
+ newName = KInputDialog::getText( i18n("Enter New Filename"),
+ i18n("A file with that name already exists. Please enter a new name:"),
+ newName, &ok, this, "renamedialog", validator );
+
+ } while( ok && dir->find( newName ) );
+
+ delete validator;
+
+ return ok;
+}
+
+
+bool K3bDataUrlAddingDialog::addHiddenFiles()
+{
+ if( m_iAddHiddenFiles == 0 ) {
+ // FIXME: the isVisible() stuff makes the static addUrls method not return (same below)
+ if( KMessageBox::questionYesNo( /*isVisible() ? */this/* : parentWidget()*/,
+ i18n("Do you also want to add hidden files?"),
+ i18n("Hidden Files"), i18n("Add"), i18n("Do Not Add") ) == KMessageBox::Yes )
+ m_iAddHiddenFiles = 1;
+ else
+ m_iAddHiddenFiles = -1;
+ }
+
+ return ( m_iAddHiddenFiles == 1 );
+}
+
+
+bool K3bDataUrlAddingDialog::addSystemFiles()
+{
+ if( m_iAddSystemFiles == 0 ) {
+ if( KMessageBox::questionYesNo( /*isVisible() ? */this/* : parentWidget()*/,
+ i18n("Do you also want to add system files "
+ "(FIFOs, sockets, device files, and broken symlinks)?"),
+ i18n("System Files"), i18n("Add"), i18n("Do Not Add") ) == KMessageBox::Yes )
+ m_iAddSystemFiles = 1;
+ else
+ m_iAddSystemFiles = -1;
+ }
+
+ return ( m_iAddSystemFiles == 1 );
+}
+
+
+void K3bDataUrlAddingDialog::slotDirSizeDone( bool success )
+{
+ if( success ) {
+ m_totalFiles += m_dirSizeJob->totalFiles() + m_dirSizeJob->totalDirs();
+ if( m_dirSizeQueue.isEmpty() ) {
+ m_progressWidget->setTotalSteps( 100 );
+ updateProgress();
+ }
+ else {
+ m_dirSizeJob->setUrls( m_dirSizeQueue.back() );
+ m_dirSizeQueue.pop_back();
+ m_dirSizeJob->start();
+ }
+ }
+}
+
+
+void K3bDataUrlAddingDialog::updateProgress()
+{
+ if( m_totalFiles > 0 ) {
+ unsigned int p = 100*m_filesHandled/m_totalFiles;
+ if( p > m_lastProgress ) {
+ m_lastProgress = p;
+ m_progressWidget->setProgress( p );
+ }
+ }
+ else {
+ // make sure the progress bar shows something
+ m_progressWidget->setProgress( m_filesHandled );
+ }
+}
+
+#include "k3bdataurladdingdialog.moc"
diff --git a/src/projects/k3bdataurladdingdialog.h b/src/projects/k3bdataurladdingdialog.h
new file mode 100644
index 0000000..cb7c0ac
--- /dev/null
+++ b/src/projects/k3bdataurladdingdialog.h
@@ -0,0 +1,110 @@
+/*
+ *
+ * $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_DATA_URL_ADDING_DIALOG_H_
+#define _K3B_DATA_URL_ADDING_DIALOG_H_
+
+#include <kdialogbase.h>
+#include <kurl.h>
+#include <qstringlist.h>
+#include <qpair.h>
+#include <qdir.h>
+
+class KProgress;
+class QLabel;
+class K3bDataItem;
+class K3bDirItem;
+class K3bEncodingConverter;
+class K3bDirSizeJob;
+class K3bDataDoc;
+
+
+class K3bDataUrlAddingDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ ~K3bDataUrlAddingDialog();
+
+ /**
+ * \return \see QDialog::exec()
+ */
+ static int addUrls( const KURL::List& urls, K3bDirItem* dir = 0,
+ QWidget* parent = 0 );
+
+ static int moveItems( const QValueList<K3bDataItem*>& items, K3bDirItem* dir,
+ QWidget* parent = 0 );
+
+ static int copyItems( const QValueList<K3bDataItem*>& items, K3bDirItem* dir,
+ QWidget* parent = 0 );
+
+ static int copyMoveItems( const QValueList<K3bDataItem*>& items, K3bDirItem* dir,
+ QWidget* parent, bool copy );
+
+ private slots:
+ void slotAddUrls();
+ void slotCopyMoveItems();
+ void slotCancel();
+ void slotDirSizeDone( bool );
+ void updateProgress();
+
+ private:
+ K3bDataUrlAddingDialog( K3bDataDoc* doc, QWidget* parent = 0, const char* name = 0 );
+
+ bool getNewName( const QString& oldName, K3bDirItem* dir, QString& newName );
+
+ bool addHiddenFiles();
+ bool addSystemFiles();
+
+ QString resultMessage() const;
+
+ KProgress* m_progressWidget;
+ QLabel* m_infoLabel;
+ QLabel* m_counterLabel;
+ K3bEncodingConverter* m_encodingConverter;
+
+ KURL::List m_urls;
+ QValueList< QPair<KURL, K3bDirItem*> > m_urlQueue;
+
+ QValueList< QPair<K3bDataItem*, K3bDirItem*> > m_items;
+
+ QValueList<KURL> m_dirSizeQueue;
+
+ bool m_bExistingItemsReplaceAll;
+ bool m_bExistingItemsIgnoreAll;
+ bool m_bFolderLinksFollowAll;
+ bool m_bFolderLinksAddAll;
+ int m_iAddHiddenFiles;
+ int m_iAddSystemFiles;
+
+ QStringList m_unreadableFiles;
+ QStringList m_notFoundFiles;
+ QStringList m_nonLocalFiles;
+ QStringList m_tooBigFiles;
+ QStringList m_mkisofsLimitationRenamedFiles;
+ QStringList m_invalidFilenameEncodingFiles;
+
+ bool m_bCanceled;
+
+ bool m_copyItems;
+
+ KIO::filesize_t m_totalFiles;
+ KIO::filesize_t m_filesHandled;
+ K3bDirSizeJob* m_dirSizeJob;
+
+ unsigned int m_lastProgress;
+};
+
+#endif
diff --git a/src/projects/k3bdataview.cpp b/src/projects/k3bdataview.cpp
new file mode 100644
index 0000000..9539b5c
--- /dev/null
+++ b/src/projects/k3bdataview.cpp
@@ -0,0 +1,196 @@
+/*
+ *
+ * $Id: k3bdataview.cpp 731898 2007-11-02 08:22:18Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bdataview.h"
+#include "k3bdatadoc.h"
+#include "k3bdataburndialog.h"
+#include "k3bbootimageview.h"
+#include "k3bdatadirtreeview.h"
+#include "k3bdatafileview.h"
+#include "k3bdataurladdingdialog.h"
+#include "k3bdatasessionimportdialog.h"
+#include "k3bdiritem.h"
+#include <k3bdevice.h>
+#include <k3bdeviceselectiondialog.h>
+#include <k3bfillstatusdisplay.h>
+#include <k3bcore.h>
+#include <k3bprojectplugin.h>
+#include <k3btoolbox.h>
+#include <k3bvalidators.h>
+
+#include <klocale.h>
+#include <kurl.h>
+#include <kapplication.h>
+#include <kpopupmenu.h>
+#include <kaction.h>
+#include <kmessagebox.h>
+#include <kio/global.h>
+#include <kio/job.h>
+#include <kdialogbase.h>
+
+#include <qpixmap.h>
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qdragobject.h>
+#include <qheader.h>
+#include <qptrlist.h>
+#include <qlineedit.h>
+
+#include <assert.h>
+#include <kdebug.h>
+
+
+K3bDataView::K3bDataView(K3bDataDoc* doc, QWidget *parent, const char *name )
+ : K3bView(doc, parent,name)
+{
+ m_doc = doc;
+
+ // --- setup GUI ---------------------------------------------------
+ QSplitter* mainSplitter = new QSplitter( this );
+ m_dataDirTree = new K3bDataDirTreeView( this, doc, mainSplitter );
+ m_dataFileView = new K3bDataFileView( this, m_dataDirTree, doc, mainSplitter );
+ m_dataDirTree->setFileView( m_dataFileView );
+ setMainWidget( mainSplitter );
+
+
+ connect( m_dataFileView, SIGNAL(dirSelected(K3bDirItem*)),
+ m_dataDirTree, SLOT(setCurrentDir(K3bDirItem*)) );
+ connect( m_doc, SIGNAL(changed()), this, SLOT(slotDocChanged()) );
+
+ m_dataDirTree->checkForNewItems();
+ m_dataFileView->checkForNewItems();
+
+
+ // the data actions
+ KAction* actionImportSession = new KAction(i18n("&Import Session..."), "gear", 0, this, SLOT(importSession()),
+ actionCollection(), "project_data_import_session" );
+ KAction* actionClearSession = new KAction(i18n("&Clear Imported Session"), "gear", 0, this,
+ SLOT(clearImportedSession()), actionCollection(),
+ "project_data_clear_imported_session" );
+ KAction* actionEditBootImages = new KAction(i18n("&Edit Boot Images..."), "cdtrack", 0, this,
+ SLOT(editBootImages()), actionCollection(),
+ "project_data_edit_boot_images" );
+
+ actionImportSession->setToolTip( i18n("Import a previously burned session into the current project") );
+ actionClearSession->setToolTip( i18n("Remove the imported items from a previous session") );
+ actionEditBootImages->setToolTip( i18n("Modify the bootable settings of the current project") );
+
+ toolBox()->addButton( actionImportSession );
+ toolBox()->addButton( actionClearSession );
+ toolBox()->addButton( actionEditBootImages );
+ toolBox()->addSeparator();
+ toolBox()->addButton( m_dataFileView->actionCollection()->action("parent_dir") );
+ toolBox()->addSeparator();
+
+ addPluginButtons( K3bProjectPlugin::DATA_CD );
+
+ toolBox()->addStretch();
+
+ m_volumeIDEdit = new QLineEdit( doc->isoOptions().volumeID(), toolBox() );
+ m_volumeIDEdit->setValidator( new K3bLatin1Validator( m_volumeIDEdit ) );
+ toolBox()->addLabel( i18n("Volume Name:") );
+ toolBox()->addSpacing();
+ toolBox()->addWidget( m_volumeIDEdit );
+ connect( m_volumeIDEdit, SIGNAL(textChanged(const QString&)),
+ m_doc,
+ SLOT(setVolumeID(const QString&)) );
+
+ // this is just for testing (or not?)
+ // most likely every project type will have it's rc file in the future
+ // we only add the additional actions since K3bView already added the default actions
+ setXML( "<!DOCTYPE kpartgui SYSTEM \"kpartgui.dtd\">"
+ "<kpartgui name=\"k3bproject\" version=\"1\">"
+ "<MenuBar>"
+ " <Menu name=\"project\"><text>&amp;Project</text>"
+ " <Action name=\"project_data_import_session\"/>"
+ " <Action name=\"project_data_clear_imported_session\"/>"
+ " <Action name=\"project_data_edit_boot_images\"/>"
+ " </Menu>"
+ "</MenuBar>"
+ "</kpartgui>", true );
+}
+
+
+K3bDataView::~K3bDataView(){
+}
+
+
+K3bDirItem* K3bDataView::currentDir() const
+{
+ return m_dataFileView->currentDir();
+}
+
+
+void K3bDataView::importSession()
+{
+ K3bDataSessionImportDialog::importSession( m_doc, this );
+}
+
+
+void K3bDataView::clearImportedSession()
+{
+ m_doc->clearImportedSession();
+}
+
+
+void K3bDataView::editBootImages()
+{
+ KDialogBase* d = new KDialogBase( this, "", true, i18n("Edit Boot Images"),
+ KDialogBase::Ok, KDialogBase::Ok, true );
+ d->setMainWidget( new K3bBootImageView( m_doc, d ) );
+ d->exec();
+ delete d;
+}
+
+
+K3bProjectBurnDialog* K3bDataView::newBurnDialog( QWidget* parent, const char* name )
+{
+ return new K3bDataBurnDialog( m_doc, parent, name, true );
+}
+
+
+void K3bDataView::slotBurn()
+{
+ // Little hack which at least handles most situations (better in 1.1):
+ // If a session has been importet we cannot use the file count since that
+ // includes imported items
+ if( m_doc->sessionImported() && m_doc->burningSize() == 0 ||
+ m_doc->root()->numFiles() == 0 ) {
+ KMessageBox::information( this, i18n("Please add files to your project first."),
+ i18n("No Data to Burn"), QString::null, false );
+ }
+ else {
+ K3bProjectBurnDialog* dlg = newBurnDialog( this );
+ dlg->execBurnDialog(true);
+ delete dlg;
+ }
+}
+
+
+void K3bDataView::slotDocChanged()
+{
+ // do not update the editor in case it changed the volume id itself
+ if( m_doc->isoOptions().volumeID() != m_volumeIDEdit->text() )
+ m_volumeIDEdit->setText( m_doc->isoOptions().volumeID() );
+}
+
+
+void K3bDataView::addUrls( const KURL::List& urls )
+{
+ K3bDataUrlAddingDialog::addUrls( urls, m_dataFileView->currentDir() );
+}
+
+#include "k3bdataview.moc"
diff --git a/src/projects/k3bdataview.h b/src/projects/k3bdataview.h
new file mode 100644
index 0000000..bb9154e
--- /dev/null
+++ b/src/projects/k3bdataview.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * $Id: k3bdataview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BDATAVIEW_H
+#define K3BDATAVIEW_H
+
+#include <k3bview.h>
+
+class K3bDataDoc;
+class K3bDataItem;
+class K3bFileItem;
+class K3bDirItem;
+class K3bDataDirTreeView;
+class K3bDataFileView;
+class QLineEdit;
+
+
+namespace KIO {
+ class Job;
+}
+namespace K3bDevice {
+ class Device;
+}
+
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bDataView : public K3bView
+{
+ Q_OBJECT
+
+ public:
+ K3bDataView(K3bDataDoc* doc, QWidget *parent=0, const char *name=0);
+ virtual ~K3bDataView();
+
+ K3bDirItem* currentDir() const;
+
+ public slots:
+ void slotBurn();
+ void importSession();
+ void clearImportedSession();
+ void editBootImages();
+
+ void slotDocChanged();
+
+ void addUrls( const KURL::List& );
+
+ protected:
+ K3bDataDirTreeView* m_dataDirTree;
+ K3bDataFileView* m_dataFileView;
+ QLineEdit* m_volumeIDEdit;
+
+ virtual K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ private:
+ K3bDataDoc* m_doc;
+
+ // used for mounting when importing old session
+ K3bDevice::Device* m_device;
+};
+
+
+#endif
diff --git a/src/projects/k3bdataviewitem.cpp b/src/projects/k3bdataviewitem.cpp
new file mode 100644
index 0000000..78c044d
--- /dev/null
+++ b/src/projects/k3bdataviewitem.cpp
@@ -0,0 +1,340 @@
+/*
+ *
+ * $Id: k3bdataviewitem.cpp 689533 2007-07-18 14:19:39Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdataviewitem.h"
+
+#include "k3bfileitem.h"
+#include "k3bdiritem.h"
+#include "k3bspecialdataitem.h"
+#include "k3bsessionimportitem.h"
+#include "k3bdatadoc.h"
+#include <k3bvalidators.h>
+
+#include <kio/global.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kurl.h>
+#include <kpixmapeffect.h>
+#include <kpixmap.h>
+
+#include <qpainter.h>
+#include <qpalette.h>
+#include <qfileinfo.h>
+
+
+K3bDataViewItem::K3bDataViewItem( K3bDataItem* item, QListView* parent )
+ : K3bListViewItem( parent ),
+ m_dataItem(item)
+{
+ init();
+}
+
+K3bDataViewItem::K3bDataViewItem( K3bDataItem* item, QListViewItem* parent )
+ : K3bListViewItem( parent ),
+ m_dataItem(item)
+{
+ init();
+}
+
+K3bDataViewItem::~K3bDataViewItem()
+{}
+
+
+void K3bDataViewItem::init()
+{
+ setEditor( 0, LINE );
+ static QValidator* s_validator = K3bValidators::iso9660Validator();
+ setValidator( 0, s_validator );
+}
+
+void K3bDataViewItem::paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int align )
+{
+ QColorGroup _cg = cg;
+
+ if( !dataItem()->isRemoveable() && dataItem()->doc()->root() != dataItem() ) {
+ _cg.setColor( QColorGroup::Text, listView()->palette().disabled().foreground() );
+ }
+
+ if( column == 0 ) {
+ QFontMetrics fm = p->fontMetrics();
+
+ if( dataItem()->hideOnRockRidge() ) {
+ int tw = QMAX( fm.width( "rr" ) + 2*listView()->itemMargin(), height() );
+ p->fillRect( width-tw, 0, tw, height(), isSelected() ? _cg.highlight() : _cg.brush(QColorGroup::Base) );
+ p->setPen( isSelected() ? _cg.highlightedText() : red );
+ p->drawEllipse( width-tw, 0, tw, height() );
+ p->drawText( width-tw, 0, tw, height(), Qt::AlignCenter, "rr" );
+ width -= tw;
+ }
+
+ if( dataItem()->hideOnJoliet() ) {
+ int tw = QMAX( fm.width( "j" ) + 2*listView()->itemMargin(), height() );
+ p->fillRect( width-tw, 0, tw, height(), isSelected() ? _cg.highlight() : _cg.brush(QColorGroup::Base) );
+ p->setPen( isSelected() ? _cg.highlightedText() : blue );
+ p->drawEllipse( width-tw, 0, tw, height() );
+ p->drawText( width-tw, 0, tw, height(), Qt::AlignCenter, "j" );
+ width -= tw;
+ }
+ }
+ else if( column == 4 ) {
+ if( dataItem()->isSymLink() ) {
+ if( !dataItem()->doc()->isoOptions().followSymbolicLinks() &&
+ dataItem()->doc()->isoOptions().createRockRidge() &&
+ !dataItem()->isValid() ) {
+ // paint the link in red
+ _cg.setColor( QColorGroup::Text, Qt::red );
+ }
+ }
+ }
+
+ K3bListViewItem::paintCell( p, _cg, column, width, align );
+}
+
+
+void K3bDataViewItem::setText( int col, const QString& text )
+{
+ if( col == 0 && dataItem()->isRenameable() ) {
+ dataItem()->setK3bName( text );
+ }
+ K3bListViewItem::setText( col, text );
+}
+
+
+QString K3bDataViewItem::key( int col, bool a ) const
+{
+ if( col == 2 ) {
+ // to have correct sorting we need to justify the size in bytes
+ // 100 TB should be enough for the next year... ;-)
+
+ if( a )
+ return ( dataItem()->isDir() ? QString("0") : QString("1") )
+ + QString::number( dataItem()->size() ).rightJustify( 16, '0' );
+ else
+ return ( dataItem()->isDir() ? QString("1") : QString("0") )
+ + QString::number( dataItem()->size() ).rightJustify( 16, '0' );
+ }
+
+ if( a )
+ return ( dataItem()->isDir() ? QString("0") : QString("1") ) + text(col);
+ else
+ return ( dataItem()->isDir() ? QString("1") : QString("0") ) + text(col);
+}
+
+
+K3bDataDirViewItem::K3bDataDirViewItem( K3bDirItem* dir, QListView* parent )
+ : K3bDataViewItem( dir, parent )
+{
+ m_dirItem = dir;
+ setPixmap( 0, dir->depth() > 7 ? SmallIcon( "folder_red" ) : SmallIcon( "folder" ) );
+}
+
+
+K3bDataDirViewItem::K3bDataDirViewItem( K3bDirItem* dir, QListViewItem* parent )
+ : K3bDataViewItem( dir, parent )
+{
+ m_dirItem = dir;
+ setPixmap( 0, dir->depth() > 7 ? SmallIcon( "folder_red" ) : SmallIcon( "folder" ) );
+}
+
+
+K3bDataDirViewItem::~K3bDataDirViewItem()
+{
+}
+
+
+void K3bDataDirViewItem::dragEntered()
+{
+ setOpen( true );
+}
+
+
+QString K3bDataDirViewItem::text( int index ) const
+{
+ switch( index ) {
+ case 0:
+ return m_dirItem->k3bName();
+ case 1:
+ return i18n("Directory");
+ case 2:
+ return KIO::convertSize( m_dirItem->size() );
+ default:
+ return "";
+ }
+}
+
+
+void K3bDataDirViewItem::highlightIcon( bool b )
+{
+ if( m_pixmap.isNull() )
+ m_pixmap = *pixmap(0);
+
+ if( b )
+ setPixmap( 0, KPixmapEffect::selectedPixmap( m_pixmap, listView()->colorGroup().highlight() ) );
+ else
+ setPixmap( 0, m_pixmap );
+}
+
+
+
+K3bDataFileViewItem::K3bDataFileViewItem( K3bFileItem* file, QListView* parent )
+ : K3bDataViewItem( file, parent )
+{
+ init( file );
+}
+
+
+K3bDataFileViewItem::K3bDataFileViewItem( K3bFileItem* file, QListViewItem* parent )
+ : K3bDataViewItem( file, parent )
+{
+ init( file );
+}
+
+
+void K3bDataFileViewItem::init( K3bFileItem* file )
+{
+ m_fileItem = file;
+
+ // determine the mimetype
+ m_pMimeType = KMimeType::findByURL( KURL::fromPathOrURL(file->localPath()) );
+ if( !m_pMimeType )
+ setPixmap( 0, DesktopIcon( "unknown", 16, KIcon::DefaultState ) );
+ else
+ setPixmap( 0, m_pMimeType->pixmap( KURL::fromPathOrURL(file->localPath()), KIcon::Desktop, 16, KIcon::DefaultState ) );
+}
+
+
+QString K3bDataFileViewItem::text( int index ) const
+{
+ switch( index ) {
+ case 0:
+ return m_fileItem->k3bName();
+ case 1:
+ {
+ QString comment = m_pMimeType->comment( KURL::fromPathOrURL(m_fileItem->localPath()), true );
+ if( comment.isEmpty() )
+ comment = m_pMimeType->name();
+
+ if( m_fileItem->isSymLink() )
+ return i18n("Link to %1").arg(comment);
+ else
+ return comment;
+ }
+ case 2:
+ return KIO::convertSize( m_fileItem->size() );
+ case 3:
+ return m_fileItem->localPath();
+ case 4: {
+ if( !m_fileItem->isSymLink() ) {
+ return QString::null;
+ }
+
+ QString s;
+ if ( m_fileItem->doc()->isoOptions().followSymbolicLinks() ) {
+ s = K3b::resolveLink( m_fileItem->localPath() );
+ }
+ else {
+ s = QFileInfo( m_fileItem->localPath() ).readLink();
+ }
+
+ if( !m_fileItem->isValid() ) {
+ s += " (" + i18n("outside of project") + ")";
+ }
+
+ return s;
+ }
+ default:
+ return "";
+ }
+}
+
+
+
+K3bDataRootViewItem::K3bDataRootViewItem( K3bDataDoc* doc, QListView* parent )
+ : K3bDataDirViewItem( doc->root(), parent )
+{
+ m_doc = doc;
+ setPixmap( 0, SmallIcon( "cdrom_unmount" ) );
+ setValidator( 0, new K3bLatin1Validator() );
+}
+
+
+K3bDataRootViewItem::~K3bDataRootViewItem()
+{
+ delete validator(0);
+}
+
+
+QString K3bDataRootViewItem::text( int index ) const
+{
+ switch( index ) {
+ case 0:
+ return ( m_doc->isoOptions().volumeID().isEmpty() ? i18n("root") : m_doc->isoOptions().volumeID() );
+ default:
+ return "";
+ }
+}
+
+
+void K3bDataRootViewItem::setText( int col, const QString& text )
+{
+ if( col == 0 )
+ m_doc->setVolumeID( text );
+
+ K3bDataViewItem::setText( col, text );
+}
+
+
+K3bSpecialDataViewItem::K3bSpecialDataViewItem( K3bSpecialDataItem* item, QListView* parent )
+ : K3bDataViewItem( item, parent )
+{
+ setPixmap( 0, SmallIcon("unknown") );
+}
+
+QString K3bSpecialDataViewItem::text( int col ) const
+{
+ switch( col ) {
+ case 0:
+ return dataItem()->k3bName();
+ case 1:
+ return ((K3bSpecialDataItem*)dataItem())->mimeType();
+ case 2:
+ return KIO::convertSize( dataItem()->size() );
+ default:
+ return "";
+ }
+}
+
+
+
+K3bSessionImportViewItem::K3bSessionImportViewItem( K3bSessionImportItem* item, QListView* parent )
+ : K3bDataViewItem( item, parent )
+{
+ setPixmap( 0, SmallIcon("unknown") );
+}
+
+QString K3bSessionImportViewItem::text( int col ) const
+{
+ switch( col ) {
+ case 0:
+ return dataItem()->k3bName();
+ case 1:
+ return i18n("From previous session");
+ case 2:
+ return KIO::convertSize( dataItem()->size() );
+ default:
+ return "";
+ }
+}
diff --git a/src/projects/k3bdataviewitem.h b/src/projects/k3bdataviewitem.h
new file mode 100644
index 0000000..60d68d2
--- /dev/null
+++ b/src/projects/k3bdataviewitem.h
@@ -0,0 +1,135 @@
+/*
+ *
+ * $Id: k3bdataviewitem.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3BDATAVIEWITEM_H
+#define K3BDATAVIEWITEM_H
+
+#include <k3blistview.h>
+#include <kmimetype.h>
+
+class K3bDataItem;
+class K3bFileItem;
+class K3bDirItem;
+class K3bDataDoc;
+class K3bSpecialDataItem;
+class K3bSessionImportItem;
+
+class QPainter;
+class QColorGroup;
+
+
+
+class K3bDataViewItem : public K3bListViewItem
+{
+ public:
+ K3bDataViewItem( K3bDataItem*, QListView* parent );
+ K3bDataViewItem( K3bDataItem*, QListViewItem* parent );
+ virtual ~K3bDataViewItem();
+
+ virtual K3bDataItem* dataItem() const { return m_dataItem; }
+
+ void setText( int col, const QString& text );
+
+ /**
+ * reimplemented to have directories always sorted before files
+ */
+ QString key( int, bool ) const;
+
+ virtual void paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int align );
+
+ private:
+ void init();
+
+ K3bDataItem* m_dataItem;
+};
+
+
+class K3bDataDirViewItem : public K3bDataViewItem
+{
+ public:
+ K3bDataDirViewItem( K3bDirItem* dir, QListView* parent );
+ K3bDataDirViewItem( K3bDirItem* dir, QListViewItem* parent );
+ ~K3bDataDirViewItem();
+
+ virtual QString text( int ) const;
+
+ K3bDirItem* dirItem() const { return m_dirItem; }
+
+ void highlightIcon( bool );
+
+ protected:
+ virtual void dragEntered();
+
+ private:
+ K3bDirItem* m_dirItem;
+ QPixmap m_pixmap;
+};
+
+
+class K3bDataFileViewItem : public K3bDataViewItem
+{
+ public:
+ K3bDataFileViewItem( K3bFileItem*, QListView* parent );
+ K3bDataFileViewItem( K3bFileItem*, QListViewItem* parent );
+ ~K3bDataFileViewItem() {}
+
+ QString text( int ) const;
+
+ K3bFileItem* fileItem() const { return m_fileItem; }
+
+ const KMimeType::Ptr mimeType() const { return m_pMimeType; }
+
+ private:
+ void init( K3bFileItem* );
+
+ K3bFileItem* m_fileItem;
+ KMimeType::Ptr m_pMimeType;
+};
+
+
+class K3bDataRootViewItem : public K3bDataDirViewItem
+{
+ public:
+ K3bDataRootViewItem( K3bDataDoc*, QListView* parent );
+ ~K3bDataRootViewItem();
+
+ QString text( int ) const;
+
+ /** reimplemented from QListViewItem */
+ void setText(int col, const QString& text );
+
+ private:
+ K3bDataDoc* m_doc;
+};
+
+
+class K3bSpecialDataViewItem : public K3bDataViewItem
+{
+ public:
+ K3bSpecialDataViewItem( K3bSpecialDataItem*, QListView* );
+
+ QString text( int ) const;
+};
+
+
+class K3bSessionImportViewItem : public K3bDataViewItem
+{
+ public:
+ K3bSessionImportViewItem( K3bSessionImportItem*, QListView* );
+
+ QString text( int ) const;
+};
+
+#endif
diff --git a/src/projects/k3bdatavolumedescwidget.cpp b/src/projects/k3bdatavolumedescwidget.cpp
new file mode 100644
index 0000000..1edbc7b
--- /dev/null
+++ b/src/projects/k3bdatavolumedescwidget.cpp
@@ -0,0 +1,93 @@
+/*
+ *
+ * $Id: k3bdatavolumedescwidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdatavolumedescwidget.h"
+
+#include "k3bisooptions.h"
+#include <k3bvalidators.h>
+
+#include <qlineedit.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+
+
+K3bDataVolumeDescWidget::K3bDataVolumeDescWidget( QWidget* parent, const char* name )
+ : base_K3bDataVolumeDescWidget( parent, name )
+{
+ // the maximal number of characters that can be inserted are set in the ui file!
+
+ QValidator* isoValidator = new K3bLatin1Validator( this );
+
+ m_editVolumeName->setValidator( isoValidator );
+ m_editVolumeSetName->setValidator( isoValidator );
+ m_editPublisher->setValidator( isoValidator );
+ m_editPreparer->setValidator( isoValidator );
+ m_editSystem->setValidator( isoValidator );
+ m_editApplication->setValidator( isoValidator );
+
+ connect( m_spinVolumeSetSize, SIGNAL(valueChanged(int)),
+ this, SLOT(slotVolumeSetSizeChanged(int)) );
+
+ // for now we hide the volume set size stuff since it's not working anymore in mkisofs 2.01a34
+ textLabel1->hide();
+ textLabel2->hide();
+ m_spinVolumeSetSize->hide();
+ m_spinVolumeSetNumber->hide();
+
+ // FIXME: show the buttons and allow the selection of a file from the project
+ m_buttonFindAbstract->hide();
+ m_buttonFindCopyright->hide();
+ m_buttonFindBiblio->hide();
+}
+
+
+K3bDataVolumeDescWidget::~K3bDataVolumeDescWidget()
+{
+}
+
+
+void K3bDataVolumeDescWidget::load( const K3bIsoOptions& o )
+{
+ m_editVolumeName->setText( o.volumeID() );
+ m_editVolumeSetName->setText( o.volumeSetId() );
+ m_spinVolumeSetSize->setValue( o.volumeSetSize() );
+ m_spinVolumeSetNumber->setValue( o.volumeSetNumber() );
+ m_editPublisher->setText( o.publisher() );
+ m_editPreparer->setText( o.preparer() );
+ m_editSystem->setText( o.systemId() );
+ m_editApplication->setText( o.applicationID() );
+}
+
+
+void K3bDataVolumeDescWidget::save( K3bIsoOptions& o )
+{
+ o.setVolumeID( m_editVolumeName->text() );
+ o.setVolumeSetId( m_editVolumeSetName->text() );
+ o.setVolumeSetSize( 1/*m_spinVolumeSetSize->value() */);
+ o.setVolumeSetNumber( 1/*m_spinVolumeSetNumber->value() */);
+ o.setPublisher( m_editPublisher->text() );
+ o.setPreparer( m_editPreparer->text() );
+ o.setSystemId( m_editSystem->text() );
+ o.setApplicationID( m_editApplication->text() );
+}
+
+
+void K3bDataVolumeDescWidget::slotVolumeSetSizeChanged( int i )
+{
+ m_spinVolumeSetNumber->setMaxValue( i );
+}
+
+#include "k3bdatavolumedescwidget.moc"
diff --git a/src/projects/k3bdatavolumedescwidget.h b/src/projects/k3bdatavolumedescwidget.h
new file mode 100644
index 0000000..8b4a388
--- /dev/null
+++ b/src/projects/k3bdatavolumedescwidget.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * $Id: k3bdatavolumedescwidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3B_DATA_VOLUMEDESC_WIDGET_H
+#define K3B_DATA_VOLUMEDESC_WIDGET_H
+
+
+#include "base_k3bdatavolumedescwidget.h"
+
+class K3bIsoOptions;
+
+
+class K3bDataVolumeDescWidget : public base_K3bDataVolumeDescWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bDataVolumeDescWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bDataVolumeDescWidget();
+
+ void load( const K3bIsoOptions& );
+ void save( K3bIsoOptions& );
+
+ private slots:
+ void slotVolumeSetSizeChanged( int );
+};
+
+#endif
diff --git a/src/projects/k3bdvdburndialog.cpp b/src/projects/k3bdvdburndialog.cpp
new file mode 100644
index 0000000..873afbf
--- /dev/null
+++ b/src/projects/k3bdvdburndialog.cpp
@@ -0,0 +1,300 @@
+/*
+ *
+ * $Id: k3bdvdburndialog.cpp 690207 2007-07-20 10:40:19Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdvdburndialog.h"
+#include "k3bdvddoc.h"
+#include "k3bdatamultisessioncombobox.h"
+
+#include <k3bdevice.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bcore.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bglobals.h>
+#include <k3bdataimagesettingswidget.h>
+#include <k3bisooptions.h>
+#include <k3bstdguiitems.h>
+#include <k3bglobalsettings.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kio/global.h>
+#include <kmessagebox.h>
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qspinbox.h>
+
+
+K3bDvdBurnDialog::K3bDvdBurnDialog( K3bDvdDoc* doc, QWidget *parent, const char *name, bool modal )
+ : K3bProjectBurnDialog( doc, parent, name, modal, true ),
+ m_doc( doc )
+{
+ prepareGui();
+
+ setTitle( i18n("DVD Project"), i18n("Size: %1").arg( KIO::convertSize(doc->size()) ) );
+
+ // for now we just put the verify checkbox on the main page...
+ m_checkVerify = K3bStdGuiItems::verifyCheckBox( m_optionGroup );
+ m_optionGroupLayout->addWidget( m_checkVerify );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ // create image settings tab
+ m_imageSettingsWidget = new K3bDataImageSettingsWidget( this );
+ addPage( m_imageSettingsWidget, i18n("Filesystem") );
+
+ setupSettingsTab();
+
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY|K3bDevice::STATE_INCOMPLETE );
+
+ QString path = doc->tempDir();
+ if( !path.isEmpty() ) {
+ m_tempDirSelectionWidget->setTempPath( path );
+ }
+ if( !doc->isoOptions().volumeID().isEmpty() ) {
+ m_tempDirSelectionWidget->setDefaultImageFileName( doc->isoOptions().volumeID() + ".iso" );
+ }
+
+ connect( m_imageSettingsWidget->m_editVolumeName, SIGNAL(textChanged(const QString&)),
+ m_tempDirSelectionWidget, SLOT(setDefaultImageFileName(const QString&)) );
+}
+
+
+K3bDvdBurnDialog::~K3bDvdBurnDialog()
+{
+}
+
+
+void K3bDvdBurnDialog::setupSettingsTab()
+{
+ QWidget* frame = new QWidget( this );
+ QGridLayout* frameLayout = new QGridLayout( frame );
+ frameLayout->setSpacing( spacingHint() );
+ frameLayout->setMargin( marginHint() );
+
+ // Multisession
+ // ////////////////////////////////////////////////////////////////////////
+ QGroupBox* groupMultiSession = new QGroupBox( 1, Qt::Vertical, i18n("Multisession Mode"), frame );
+ m_comboMultisession = new K3bDataMultiSessionCombobox( groupMultiSession );
+
+ frameLayout->addWidget( groupMultiSession, 0, 0 );
+ frameLayout->setRowStretch( 1, 1 );
+
+ addPage( frame, i18n("Misc") );
+
+ connect( m_comboMultisession, SIGNAL(activated(int)),
+ this, SLOT(slotMultiSessionModeChanged()) );
+}
+
+
+void K3bDvdBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ // save iso image settings
+ K3bIsoOptions o = m_doc->isoOptions();
+ m_imageSettingsWidget->save( o );
+ m_doc->setIsoOptions( o );
+
+ // save image file path
+ m_doc->setTempDir( m_tempDirSelectionWidget->tempPath() );
+
+ // save multisession settings
+ m_doc->setMultiSessionMode( m_comboMultisession->multiSessionMode() );
+
+ m_doc->setVerifyData( m_checkVerify->isChecked() );
+}
+
+
+void K3bDvdBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ // read multisession
+ m_comboMultisession->setMultiSessionMode( m_doc->multiSessionMode() );
+
+ if( !doc()->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( doc()->tempDir() );
+ else
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() + doc()->name() + ".iso" );
+
+ m_checkVerify->setChecked( m_doc->verifyData() );
+
+ m_imageSettingsWidget->load( m_doc->isoOptions() );
+
+ // for now we do not support dual layer multisession (growisofs does not handle layer jump yet)
+ // in case overburn is enabled we allow some made up max size
+ // before we force a DL medium
+ if( doc()->size() > 4700372992LL &&
+ ( !k3bcore->globalSettings()->overburn() ||
+ doc()->size() > 4900000000LL ) )
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD_DL );
+ else
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD );
+
+ toggleAll();
+}
+
+
+void K3bDvdBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ // Multisession in DAO is not possible
+ if( m_writingModeWidget->writingMode() == K3b::DAO ) {
+ if( m_comboMultisession->multiSessionMode() == K3bDataDoc::START ||
+ m_comboMultisession->multiSessionMode() == K3bDataDoc::CONTINUE ||
+ m_comboMultisession->multiSessionMode() == K3bDataDoc::FINISH )
+ KMessageBox::information( this, i18n("It is not possible to write multisession DVDs in DAO mode."
+ "Multisession has been disabled."),
+ i18n("DVD multisession"),
+ "dvd_multisession_no_dao" );
+
+ m_comboMultisession->setEnabled(false);
+ }
+ else {
+// // for some reason I don't know yet when writing multisession volume set size needs to be 1
+// if( m_comboMultisession->multiSessionMode() != K3bDataDoc::NONE ) {
+// m_volumeDescWidget->m_spinVolumeSetSize->setValue( 1 );
+// m_volumeDescWidget->m_spinVolumeSetSize->setEnabled( false );
+// }
+// else {
+// m_volumeDescWidget->m_spinVolumeSetSize->setEnabled( true );
+// }
+
+ m_comboMultisession->setEnabled(true);
+
+// if( !m_checkOnTheFly->isChecked() ) {
+// // no continue and finish multisession in non-the-fly mode since
+// // we can only continue ms with growisofsimager
+// if( m_comboMultisession->multiSessionMode() == K3bDataDoc::START ||
+// m_comboMultisession->multiSessionMode() == K3bDataDoc::FINISH ||
+// m_comboMultisession->multiSessionMode() == K3bDataDoc::CONTINUE ) {
+// KMessageBox::information( this, i18n("K3b does only support writing multisession DVDs on-the-fly. "
+// "Multisession has been disabled."),
+// i18n("DVD Multisession"),
+// "dvd_multisession_only_on_the_fly" );
+// }
+// m_comboMultisession->setForceNoMultisession( true );
+// }
+// else {
+// m_comboMultisession->setForceNoMultisession( false );
+// }
+ }
+
+ if( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() ) {
+ m_checkVerify->setChecked(false);
+ m_checkVerify->setEnabled(false);
+ }
+ else
+ m_checkVerify->setEnabled(true);
+}
+
+
+void K3bDvdBurnDialog::slotMultiSessionModeChanged()
+{
+ if( m_comboMultisession->multiSessionMode() == K3bDataDoc::CONTINUE ||
+ m_comboMultisession->multiSessionMode() == K3bDataDoc::FINISH )
+ m_spinCopies->setEnabled(false);
+
+ // wait for the proper medium
+ // we have to do this in another slot than toggleAllOptions to avoid an endless loop
+ if( m_comboMultisession->multiSessionMode() == K3bDataDoc::NONE )
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY );
+ else if( m_comboMultisession->multiSessionMode() == K3bDataDoc::CONTINUE ||
+ m_comboMultisession->multiSessionMode() == K3bDataDoc::FINISH )
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_INCOMPLETE );
+ else
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY|K3bDevice::STATE_INCOMPLETE );
+}
+
+
+void K3bDvdBurnDialog::loadK3bDefaults()
+{
+ K3bProjectBurnDialog::loadK3bDefaults();
+
+ m_imageSettingsWidget->load( K3bIsoOptions::defaults() );
+ m_checkVerify->setChecked( false );
+
+ m_comboMultisession->setMultiSessionMode( K3bDataDoc::AUTO );
+
+ toggleAll();
+}
+
+
+void K3bDvdBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults(c);
+
+ K3bIsoOptions o = K3bIsoOptions::load( c );
+ m_imageSettingsWidget->load( o );
+
+ m_comboMultisession->loadConfig( c );
+
+ m_checkVerify->setChecked( c->readBoolEntry( "verify data", false ) );
+
+ toggleAll();
+}
+
+
+void K3bDvdBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults(c);
+
+ K3bIsoOptions o;
+ m_imageSettingsWidget->save( o );
+ o.save( c );
+
+ m_comboMultisession->saveConfig( c );
+
+ c->writeEntry( "verify data", m_checkVerify->isChecked() );
+}
+
+
+void K3bDvdBurnDialog::slotStartClicked()
+{
+ if( m_checkOnlyCreateImage->isChecked() ||
+ m_checkCacheImage->isChecked() ) {
+ QFileInfo fi( m_tempDirSelectionWidget->tempPath() );
+ if( fi.isDir() )
+ m_tempDirSelectionWidget->setTempPath( fi.filePath() + "/image.iso" );
+
+ if( QFile::exists( m_tempDirSelectionWidget->tempPath() ) ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(m_tempDirSelectionWidget->tempPath()),
+ i18n("File Exists"), i18n("Overwrite") )
+ == KMessageBox::Continue ) {
+ // delete the file here to avoid problems with free space in K3bProjectBurnDialog::slotStartClicked
+ QFile::remove( m_tempDirSelectionWidget->tempPath() );
+ }
+ else
+ return;
+ }
+ }
+
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+#include "k3bdvdburndialog.moc"
diff --git a/src/projects/k3bdvdburndialog.h b/src/projects/k3bdvdburndialog.h
new file mode 100644
index 0000000..deb9620
--- /dev/null
+++ b/src/projects/k3bdvdburndialog.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * $Id: k3bdvdburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_DVD_BURNDIALOG_H_
+#define _K3B_DVD_BURNDIALOG_H_
+
+#include "k3bprojectburndialog.h"
+
+
+class K3bDvdDoc;
+class K3bDataImageSettingsWidget;
+class QGroupBox;
+class QRadioButton;
+class QButtonGroup;
+class QCheckBox;
+class K3bDataMultiSessionCombobox;
+
+
+class K3bDvdBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bDvdBurnDialog( K3bDvdDoc*, QWidget *parent = 0, const char *name = 0, bool modal = true );
+ ~K3bDvdBurnDialog();
+
+ protected slots:
+ void slotMultiSessionModeChanged();
+
+ void saveSettings();
+ void readSettings();
+
+ protected:
+ void slotStartClicked();
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void toggleAll();
+
+ private:
+ void setupSettingsTab();
+
+ // --- settings tab ---------------------------
+ K3bDataImageSettingsWidget* m_imageSettingsWidget;
+ // ----------------------------------------------
+
+ // --- multisession tab -------------------------
+ K3bDataMultiSessionCombobox* m_comboMultisession;
+ // ---------------------------------------------
+
+ QCheckBox* m_checkVerify;
+
+ K3bDvdDoc* m_doc;
+};
+
+#endif
diff --git a/src/projects/k3bdvdview.cpp b/src/projects/k3bdvdview.cpp
new file mode 100644
index 0000000..512ec4b
--- /dev/null
+++ b/src/projects/k3bdvdview.cpp
@@ -0,0 +1,48 @@
+/*
+ *
+ * $Id: k3bdvdview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bdvdview.h"
+#include "k3bdvddoc.h"
+#include "k3bdvdburndialog.h"
+#include <k3bfillstatusdisplay.h>
+#include <k3bdatafileview.h>
+
+#include <klocale.h>
+
+
+K3bDvdView::K3bDvdView( K3bDvdDoc* doc, QWidget *parent, const char *name )
+ : K3bDataView( doc, parent, name )
+{
+ m_doc = doc;
+
+ fillStatusDisplay()->showDvdSizes(true);
+
+ m_dataFileView->setNoItemText( i18n("Use drag'n'drop to add files and directories to the project.\n"
+ "To remove or rename files use the context menu.\n"
+ "After that press the burn button to write the DVD.") );
+}
+
+
+K3bDvdView::~K3bDvdView()
+{
+}
+
+
+K3bProjectBurnDialog* K3bDvdView::newBurnDialog( QWidget* parent, const char* name )
+{
+ return new K3bDvdBurnDialog( m_doc, parent, name, true );
+}
+
+#include "k3bdvdview.moc"
diff --git a/src/projects/k3bdvdview.h b/src/projects/k3bdvdview.h
new file mode 100644
index 0000000..d9f30f3
--- /dev/null
+++ b/src/projects/k3bdvdview.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * $Id: k3bdvdview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_DVDVIEW_H_
+#define _K3B_DVDVIEW_H_
+
+#include <k3bdataview.h>
+
+class K3bDvdDoc;
+
+
+class K3bDvdView : public K3bDataView
+{
+ Q_OBJECT
+
+ public:
+ K3bDvdView( K3bDvdDoc* doc, QWidget *parent = 0, const char *name = 0 );
+ ~K3bDvdView();
+
+ protected:
+ virtual K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ private:
+ K3bDvdDoc* m_doc;
+};
+
+#endif
diff --git a/src/projects/k3bencodingconverter.cpp b/src/projects/k3bencodingconverter.cpp
new file mode 100644
index 0000000..460abbe
--- /dev/null
+++ b/src/projects/k3bencodingconverter.cpp
@@ -0,0 +1,130 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3bencodingconverter.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+
+#include <kdebug.h>
+
+#ifdef HAVE_ICONV_H
+#include <langinfo.h>
+#include <iconv.h>
+#endif
+
+
+class K3bEncodingConverter::Private
+{
+ public:
+ iconv_t ic;
+ QString localEncoding;
+ QString lastEncoding;
+};
+
+
+K3bEncodingConverter::K3bEncodingConverter()
+{
+ d = new Private;
+#ifdef HAVE_ICONV_H
+ char* codec = nl_langinfo( CODESET );
+ d->localEncoding = QString::fromLocal8Bit( codec );
+ kdDebug() << "(K3bDataUrlAddingDialog) using locale codec: " << codec << endl;
+ d->ic = ::iconv_open( "UCS-2BE", codec );
+#endif
+}
+
+
+K3bEncodingConverter::~K3bEncodingConverter()
+{
+#ifdef HAVE_ICONV_H
+ ::iconv_close( d->ic );
+#endif
+ delete d;
+}
+
+
+bool K3bEncodingConverter::encodedLocally( const QCString& s )
+{
+#ifdef HAVE_ICONV_H
+ QCString utf8Encoded( s.length()*2 );
+#if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
+ const char* in = s.data();
+#else
+ char* in = s.data();
+#endif
+ char* out = utf8Encoded.data();
+ size_t inSize = s.length();
+ size_t outSize = utf8Encoded.size();
+ return( (size_t)-1 != ::iconv( d->ic, &in, &inSize, &out, &outSize ) );
+#else
+ return true;
+#endif
+}
+
+
+bool K3bEncodingConverter::fixEncoding( const QCString& s, QCString& result, QWidget* parent, bool cache )
+{
+#ifdef IMPLEMENT_THIS_METHOD // HAVE_ICONV_H
+ if( !d->lastEncoding.isEmpty() ) {
+ //
+ // try converting with the last encoding
+ //
+ if( convert( s, result, d->lastEncoding, d->localEncoding )
+ && encodedLocally( result ) ) {
+ return true;
+ }
+ }
+
+
+
+ if( cache ) {
+
+ }
+ else
+ d->lastEncoding = QString::null;
+#else
+ return false;
+#endif
+}
+
+
+bool K3bEncodingConverter::convert( const QCString& s, QCString& result, const QString& from, const QString& to )
+{
+ bool r = false;
+
+#ifdef HAVE_ICONV_H
+ iconv_t ic = ::iconv_open( to.local8Bit(), from.local8Bit() );
+
+ result.resize( s.length() * 2 );
+#if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
+ const char* in = s.data();
+#else
+ char* in = s.data();
+#endif
+ char* out = result.data();
+ size_t inSize = s.length();
+ size_t outSize = result.size();
+
+ if( (size_t)-1 != ::iconv( ic, &in, &inSize, &out, &outSize ) )
+ r = true;
+
+ ::iconv_close( ic );
+#endif
+
+ return r;
+}
diff --git a/src/projects/k3bencodingconverter.h b/src/projects/k3bencodingconverter.h
new file mode 100644
index 0000000..e40003c
--- /dev/null
+++ b/src/projects/k3bencodingconverter.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_ENCODING_CONVERTER_H_
+#define _K3B_ENCODING_CONVERTER_H_
+
+#include <qcstring.h>
+#include <qstring.h>
+
+class QWidget;
+
+class K3bEncodingConverter
+{
+ public:
+ K3bEncodingConverter();
+ ~K3bEncodingConverter();
+
+ /**
+ * Check if a string is encoded using the local codeset
+ *
+ * \return True if the string is encoded in the local encoding.
+ */
+ bool encodedLocally( const QCString& );
+
+ /**
+ * Tries to fix the encoding of a string to fit the local
+ * encoding.
+ * It presents a dialog to the user that let's them choose
+ * the proper encoding based on example conversions.
+ *
+ * \param s The string to be fixed.
+ * \param parent The parent widget to be used when showing the encoding selection dialog.
+ * \param cacheEncoding If true the codeset used for successful conversion is cached and
+ * reused for the next call to fixEncoding.
+ *
+ * \return True if the conversion was successful.
+ */
+ bool fixEncoding( const QCString& s, QCString& result, QWidget* parent = 0, bool cacheEncoding = true );
+
+ private:
+ bool convert( const QCString& s, QCString& result, const QString& from, const QString& to );
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/projects/k3bfillstatusdisplay.cpp b/src/projects/k3bfillstatusdisplay.cpp
new file mode 100644
index 0000000..2d39bc7
--- /dev/null
+++ b/src/projects/k3bfillstatusdisplay.cpp
@@ -0,0 +1,759 @@
+/*
+ *
+ * $Id: k3bfillstatusdisplay.cpp 768504 2008-01-30 08:53:22Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bfillstatusdisplay.h"
+#include "k3bdoc.h"
+
+#include <k3bapplication.h>
+#include <k3bmediaselectiondialog.h>
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bdevice.h>
+#include <k3bmsf.h>
+#include <k3bradioaction.h>
+#include <k3bmediacache.h>
+
+#include <qevent.h>
+#include <qpainter.h>
+#include <qcolor.h>
+#include <qrect.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qvalidator.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qtimer.h>
+
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kio/global.h>
+#include <kmessagebox.h>
+#include <kglobal.h>
+#include <kpixmapeffect.h>
+
+
+static const int DEFAULT_CD_SIZE_74 = 74*60*75;
+static const int DEFAULT_CD_SIZE_80 = 80*60*75;
+static const int DEFAULT_CD_SIZE_100 = 100*60*75;
+static const int DEFAULT_DVD_SIZE_4_4 = 2295104;
+static const int DEFAULT_DVD_SIZE_8_0 = 4173824;
+
+class K3bFillStatusDisplayWidget::Private
+{
+public:
+ K3b::Msf cdSize;
+ bool showTime;
+ K3bDoc* doc;
+};
+
+
+K3bFillStatusDisplayWidget::K3bFillStatusDisplayWidget( K3bDoc* doc, QWidget* parent )
+ : QWidget( parent, 0, WRepaintNoErase )
+{
+ d = new Private();
+ d->doc = doc;
+ setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred ) );
+}
+
+
+K3bFillStatusDisplayWidget::~K3bFillStatusDisplayWidget()
+{
+ delete d;
+}
+
+
+const K3b::Msf& K3bFillStatusDisplayWidget::cdSize() const
+{
+ return d->cdSize;
+}
+
+
+void K3bFillStatusDisplayWidget::setShowTime( bool b )
+{
+ d->showTime = b;
+ update();
+}
+
+
+void K3bFillStatusDisplayWidget::setCdSize( const K3b::Msf& size )
+{
+ d->cdSize = size;
+ update();
+}
+
+
+QSize K3bFillStatusDisplayWidget::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+
+QSize K3bFillStatusDisplayWidget::minimumSizeHint() const
+{
+ int margin = 2;
+ QFontMetrics fm( font() );
+ return QSize( -1, fm.height() + 2 * margin );
+}
+
+
+void K3bFillStatusDisplayWidget::mousePressEvent( QMouseEvent* e )
+{
+ if( e->button() == Qt::RightButton )
+ emit contextMenu( e->globalPos() );
+}
+
+
+void K3bFillStatusDisplayWidget::paintEvent( QPaintEvent* )
+{
+ // double buffer
+ QPixmap buffer( size() );
+ buffer.fill( colorGroup().base() );
+ QPainter p;
+ p.begin( &buffer, this );
+ p.setPen( Qt::black ); // we use a fixed bar color (which is not very nice btw, so we also fix the text color)
+
+ long long docSize;
+ long long cdSize;
+ long long maxValue;
+ long tolerance;
+
+ if( d->showTime ) {
+ docSize = d->doc->length().totalFrames() / 75 / 60;
+ cdSize = d->cdSize.totalFrames() / 75 / 60;
+ maxValue = (cdSize > docSize ? cdSize : docSize) + 10;
+ tolerance = 1;
+ }
+ else {
+ docSize = d->doc->size()/1024/1024;
+ cdSize = d->cdSize.mode1Bytes()/1024/1024;
+ maxValue = (cdSize > docSize ? cdSize : docSize) + 100;
+ tolerance = 10;
+ }
+
+ // so split width() in maxValue pieces
+ double one = (double)rect().width() / (double)maxValue;
+ QRect crect( rect() );
+ crect.setWidth( (int)(one*(double)docSize) );
+
+ p.setClipping(true);
+ p.setClipRect(crect);
+
+ p.fillRect( crect, Qt::green );
+
+ QRect oversizeRect(crect);
+ // draw yellow if cdSize - tolerance < docSize
+ if( docSize > cdSize - tolerance ) {
+ oversizeRect.setLeft( oversizeRect.left() + (int)(one * (cdSize - tolerance)) );
+ p.fillRect( oversizeRect, Qt::yellow );
+ KPixmap pix;
+ pix.resize( rect().height()*2, rect().height() );
+ KPixmapEffect::gradient( pix, green, yellow, KPixmapEffect::HorizontalGradient, 0 );
+ p.drawPixmap( oversizeRect.left() - pix.width()/2, 0, pix );
+ }
+
+ // draw red if docSize > cdSize + tolerance
+ if( docSize > cdSize + tolerance ) {
+ oversizeRect.setLeft( oversizeRect.left() + (int)(one * tolerance*2) );
+ p.fillRect( oversizeRect, Qt::red );
+ KPixmap pix;
+ pix.resize( rect().height()*2, rect().height() );
+ KPixmapEffect::gradient( pix, yellow, red, KPixmapEffect::HorizontalGradient, 0 );
+ p.drawPixmap( oversizeRect.left() - pix.width()/2, 0, pix );
+ }
+
+ p.setClipping(false);
+
+ // ====================================================================================
+ // Now the colored bar is painted
+ // Continue with the texts
+ // ====================================================================================
+
+ // first we determine the text to display
+ // ====================================================================================
+ QString docSizeText;
+ if( d->showTime )
+ docSizeText = d->doc->length().toString(false) + " " + i18n("min");
+ else
+ docSizeText = KIO::convertSize( d->doc->size() );
+
+ QString overSizeText;
+ if( d->cdSize.mode1Bytes() >= d->doc->size() )
+ overSizeText = i18n("Available: %1 of %2")
+ .arg( d->showTime
+ ? i18n("%1 min").arg((K3b::Msf( cdSize*60*75 ) - d->doc->length()).toString(false))
+ : KIO::convertSize( QMAX( (cdSize * 1024LL * 1024LL) - (long long)d->doc->size(), 0LL ) ) )
+ .arg( d->showTime
+ ? i18n("%1 min").arg(K3b::Msf( cdSize*60*75 ).toString(false))
+ : KIO::convertSizeFromKB( cdSize * 1024 ) );
+ else
+ overSizeText = i18n("Capacity exceeded by %1")
+ .arg( d->showTime
+ ? i18n("%1 min").arg( (d->doc->length() - K3b::Msf( cdSize*60*75 ) ).toString(false))
+ : KIO::convertSize( (long long)d->doc->size() - (cdSize * 1024LL * 1024LL) ) );
+ // ====================================================================================
+
+ // draw the medium size marker
+ // ====================================================================================
+ int mediumSizeMarkerPos = rect().left() + (int)(one*cdSize);
+ p.drawLine( mediumSizeMarkerPos, rect().bottom(),
+ mediumSizeMarkerPos, rect().top() + ((rect().bottom()-rect().top())/2) );
+ // ====================================================================================
+
+
+
+ // we want to draw the docSizeText centered in the filled area
+ // if there is not enough space we just align it left
+ // ====================================================================================
+ int docSizeTextPos = 0;
+ int docSizeTextLength = fontMetrics().width(docSizeText);
+ if( docSizeTextLength + 5 > crect.width() ) {
+ docSizeTextPos = crect.left() + 5; // a little margin
+ }
+ else {
+ docSizeTextPos = ( crect.width() - docSizeTextLength ) / 2;
+
+ // make sure the text does not cross the medium size marker
+ if( docSizeTextPos <= mediumSizeMarkerPos && mediumSizeMarkerPos <= docSizeTextPos + docSizeTextLength )
+ docSizeTextPos = QMAX( crect.left() + 5, mediumSizeMarkerPos - docSizeTextLength - 5 );
+ }
+ // ====================================================================================
+
+ // draw the over size text
+ // ====================================================================================
+ QFont fnt(font());
+ fnt.setPointSize( QMAX( 8, fnt.pointSize()-4 ) );
+ fnt.setBold(false);
+
+ QRect overSizeTextRect( rect() );
+ int overSizeTextLength = QFontMetrics(fnt).width(overSizeText);
+ if( overSizeTextLength + 5 > overSizeTextRect.width() - (int)(one*cdSize) ) {
+ // we don't have enough space on the right, so we paint to the left of the line
+ overSizeTextRect.setLeft( (int)(one*cdSize) - overSizeTextLength - 5 );
+ }
+ else {
+ overSizeTextRect.setLeft( mediumSizeMarkerPos + 5 );
+ }
+
+ // make sure the two text do not overlap (this does not cover all cases though)
+ if( overSizeTextRect.left() < docSizeTextPos + docSizeTextLength )
+ docSizeTextPos = QMAX( crect.left() + 5, QMIN( overSizeTextRect.left() - docSizeTextLength - 5, mediumSizeMarkerPos - docSizeTextLength - 5 ) );
+
+ QRect docTextRect( rect() );
+ docTextRect.setLeft( docSizeTextPos );
+ p.drawText( docTextRect, Qt::AlignLeft | Qt::AlignVCenter, docSizeText );
+
+ p.setFont(fnt);
+ p.drawText( overSizeTextRect, Qt::AlignLeft | Qt::AlignVCenter, overSizeText );
+ // ====================================================================================
+
+ p.end();
+
+ bitBlt( this, 0, 0, &buffer );
+}
+
+
+
+// ----------------------------------------------------------------------------------------------------
+
+
+class K3bFillStatusDisplay::ToolTip : public QToolTip
+{
+public:
+ ToolTip( K3bDoc* doc, QWidget* parent )
+ : QToolTip( parent, 0 ),
+ m_doc(doc) {
+ }
+
+ void maybeTip( const QPoint& ) {
+ tip( parentWidget()->rect(),
+ KIO::convertSize( m_doc->size() ) +
+ " (" + KGlobal::locale()->formatNumber( m_doc->size(), 0 ) + "), " +
+ m_doc->length().toString(false) + " " + i18n("min") +
+ " (" + i18n("Right click for media sizes") + ")");
+ }
+
+private:
+ K3bDoc* m_doc;
+};
+
+class K3bFillStatusDisplay::Private
+{
+public:
+ KActionCollection* actionCollection;
+ KRadioAction* actionShowMinutes;
+ KRadioAction* actionShowMegs;
+ KRadioAction* actionAuto;
+ KRadioAction* action74Min;
+ KRadioAction* action80Min;
+ KRadioAction* action100Min;
+ KRadioAction* actionDvd4_7GB;
+ KRadioAction* actionDvdDoubleLayer;
+ K3bRadioAction* actionCustomSize;
+ K3bRadioAction* actionDetermineSize;
+ KAction* actionSaveUserDefaults;
+ KAction* actionLoadUserDefaults;
+
+ KPopupMenu* popup;
+ KPopupMenu* dvdPopup;
+
+ QToolButton* buttonMenu;
+
+ K3bFillStatusDisplayWidget* displayWidget;
+
+ bool showDvdSizes;
+ bool showTime;
+
+ K3bDoc* doc;
+
+ QTimer updateTimer;
+};
+
+
+K3bFillStatusDisplay::K3bFillStatusDisplay( K3bDoc* doc, QWidget *parent, const char *name )
+ : QFrame(parent,name)
+{
+ d = new Private;
+ d->doc = doc;
+
+ m_toolTip = new ToolTip( doc, this );
+
+ setFrameStyle( Panel | Sunken );
+
+ d->displayWidget = new K3bFillStatusDisplayWidget( doc, this );
+// d->buttonMenu = new QToolButton( this );
+// d->buttonMenu->setIconSet( SmallIconSet("cdrom_unmount") );
+// d->buttonMenu->setAutoRaise(true);
+// QToolTip::add( d->buttonMenu, i18n("Fill display properties") );
+// connect( d->buttonMenu, SIGNAL(clicked()), this, SLOT(slotMenuButtonClicked()) );
+
+ QGridLayout* layout = new QGridLayout( this );
+ layout->setSpacing(5);
+ layout->setMargin(frameWidth());
+ layout->addWidget( d->displayWidget, 0, 0 );
+ // layout->addWidget( d->buttonMenu, 0, 1 );
+ layout->setColStretch( 0, 1 );
+
+ setupPopupMenu();
+
+ showDvdSizes( false );
+
+ connect( d->doc, SIGNAL(changed()), this, SLOT(slotDocChanged()) );
+ connect( &d->updateTimer, SIGNAL(timeout()), this, SLOT(slotUpdateDisplay()) );
+ connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3bDevice::Device*)),
+ this, SLOT(slotMediumChanged(K3bDevice::Device*)) );
+}
+
+K3bFillStatusDisplay::~K3bFillStatusDisplay()
+{
+ delete d;
+ delete m_toolTip;
+}
+
+
+void K3bFillStatusDisplay::setupPopupMenu()
+{
+ d->actionCollection = new KActionCollection( this );
+
+ // we use a nother popup for the dvd sizes
+ d->popup = new KPopupMenu( this, "popup" );
+ d->dvdPopup = new KPopupMenu( this, "dvdpopup" );
+
+ d->actionShowMinutes = new KRadioAction( i18n("Minutes"), 0, this, SLOT(showTime()),
+ d->actionCollection, "fillstatus_show_minutes" );
+ d->actionShowMegs = new KRadioAction( i18n("Megabytes"), 0, this, SLOT(showSize()),
+ d->actionCollection, "fillstatus_show_megabytes" );
+
+ d->actionShowMegs->setExclusiveGroup( "show_size_in" );
+ d->actionShowMinutes->setExclusiveGroup( "show_size_in" );
+
+ d->actionAuto = new KRadioAction( i18n("Auto"), 0, this, SLOT(slotAutoSize()),
+ d->actionCollection, "fillstatus_auto" );
+ d->action74Min = new KRadioAction( i18n("%1 MB").arg(650), 0, this, SLOT(slot74Minutes()),
+ d->actionCollection, "fillstatus_74minutes" );
+ d->action80Min = new KRadioAction( i18n("%1 MB").arg(700), 0, this, SLOT(slot80Minutes()),
+ d->actionCollection, "fillstatus_80minutes" );
+ d->action100Min = new KRadioAction( i18n("%1 MB").arg(880), 0, this, SLOT(slot100Minutes()),
+ d->actionCollection, "fillstatus_100minutes" );
+ d->actionDvd4_7GB = new KRadioAction( KIO::convertSizeFromKB((int)(4.4*1024.0*1024.0)), 0, this, SLOT(slotDvd4_7GB()),
+ d->actionCollection, "fillstatus_dvd_4_7gb" );
+ d->actionDvdDoubleLayer = new KRadioAction( KIO::convertSizeFromKB((int)(8.0*1024.0*1024.0)),
+ 0, this, SLOT(slotDvdDoubleLayer()),
+ d->actionCollection, "fillstatus_dvd_double_layer" );
+ d->actionCustomSize = new K3bRadioAction( i18n("Custom..."), 0, this, SLOT(slotCustomSize()),
+ d->actionCollection, "fillstatus_custom_size" );
+ d->actionCustomSize->setAlwaysEmitActivated(true);
+ d->actionDetermineSize = new K3bRadioAction( i18n("From Medium..."), "cdrom_unmount", 0,
+ this, SLOT(slotDetermineSize()),
+ d->actionCollection, "fillstatus_size_from_disk" );
+ d->actionDetermineSize->setAlwaysEmitActivated(true);
+
+ d->actionAuto->setExclusiveGroup( "cd_size" );
+ d->action74Min->setExclusiveGroup( "cd_size" );
+ d->action80Min->setExclusiveGroup( "cd_size" );
+ d->action100Min->setExclusiveGroup( "cd_size" );
+ d->actionDvd4_7GB->setExclusiveGroup( "cd_size" );
+ d->actionDvdDoubleLayer->setExclusiveGroup( "cd_size" );
+ d->actionCustomSize->setExclusiveGroup( "cd_size" );
+ d->actionDetermineSize->setExclusiveGroup( "cd_size" );
+
+ d->actionLoadUserDefaults = new KAction( i18n("User Defaults"), "", 0,
+ this, SLOT(slotLoadUserDefaults()),
+ d->actionCollection, "load_user_defaults" );
+ d->actionSaveUserDefaults = new KAction( i18n("Save User Defaults"), "", 0,
+ this, SLOT(slotSaveUserDefaults()),
+ d->actionCollection, "save_user_defaults" );
+
+ KAction* dvdSizeInfoAction = new KAction( i18n("Why 4.4 instead of 4.7?"), "", 0,
+ this, SLOT(slotWhy44()),
+ d->actionCollection, "why_44_gb" );
+
+ d->popup->insertTitle( i18n("Show Size In") );
+ d->actionShowMinutes->plug( d->popup );
+ d->actionShowMegs->plug( d->popup );
+ d->popup->insertTitle( i18n("CD Size") );
+ d->actionAuto->plug( d->popup );
+ d->action74Min->plug( d->popup );
+ d->action80Min->plug( d->popup );
+ d->action100Min->plug( d->popup );
+ d->actionCustomSize->plug( d->popup );
+ d->actionDetermineSize->plug( d->popup );
+ d->popup->insertSeparator();
+ d->actionLoadUserDefaults->plug( d->popup );
+ d->actionSaveUserDefaults->plug( d->popup );
+
+ d->dvdPopup->insertTitle( i18n("DVD Size") );
+ dvdSizeInfoAction->plug( d->dvdPopup );
+ d->actionAuto->plug( d->dvdPopup );
+ d->actionDvd4_7GB->plug( d->dvdPopup );
+ d->actionDvdDoubleLayer->plug( d->dvdPopup );
+ d->actionCustomSize->plug( d->dvdPopup );
+ d->actionDetermineSize->plug( d->dvdPopup );
+ d->dvdPopup->insertSeparator();
+ d->actionLoadUserDefaults->plug( d->dvdPopup );
+ d->actionSaveUserDefaults->plug( d->dvdPopup );
+
+ connect( d->displayWidget, SIGNAL(contextMenu(const QPoint&)), this, SLOT(slotPopupMenu(const QPoint&)) );
+}
+
+
+void K3bFillStatusDisplay::showSize()
+{
+ d->actionShowMegs->setChecked( true );
+
+ d->action74Min->setText( i18n("%1 MB").arg(650) );
+ d->action80Min->setText( i18n("%1 MB").arg(700) );
+ d->action100Min->setText( i18n("%1 MB").arg(880) );
+
+ d->showTime = false;
+ d->displayWidget->setShowTime(false);
+}
+
+void K3bFillStatusDisplay::showTime()
+{
+ d->actionShowMinutes->setChecked( true );
+
+ d->action74Min->setText( i18n("unused", "%n minutes", 74) );
+ d->action80Min->setText( i18n("unused", "%n minutes", 80) );
+ d->action100Min->setText( i18n("unused", "%n minutes", 100) );
+
+ d->showTime = true;
+ d->displayWidget->setShowTime(true);
+}
+
+
+void K3bFillStatusDisplay::showDvdSizes( bool b )
+{
+ d->showDvdSizes = b;
+ slotLoadUserDefaults();
+}
+
+
+void K3bFillStatusDisplay::slotAutoSize()
+{
+ slotMediumChanged( 0 );
+}
+
+
+void K3bFillStatusDisplay::slot74Minutes()
+{
+ d->displayWidget->setCdSize( DEFAULT_CD_SIZE_74 );
+}
+
+
+void K3bFillStatusDisplay::slot80Minutes()
+{
+ d->displayWidget->setCdSize( DEFAULT_CD_SIZE_80 );
+}
+
+
+void K3bFillStatusDisplay::slot100Minutes()
+{
+ d->displayWidget->setCdSize( DEFAULT_CD_SIZE_100 );
+}
+
+
+void K3bFillStatusDisplay::slotDvd4_7GB()
+{
+ d->displayWidget->setCdSize( DEFAULT_DVD_SIZE_4_4 );
+}
+
+
+void K3bFillStatusDisplay::slotDvdDoubleLayer()
+{
+ d->displayWidget->setCdSize( DEFAULT_DVD_SIZE_8_0 );
+}
+
+
+void K3bFillStatusDisplay::slotWhy44()
+{
+ QWhatsThis::display( i18n("<p><b>Why does K3b offer 4.4 GB and 8.0 GB instead of 4.7 and 8.5 like "
+ "it says on the media?</b>"
+ "<p>A single layer DVD media has a capacity of approximately "
+ "4.4 GB which equals 4.4*1024<sup>3</sup> bytes. Media producers just "
+ "calculate with 1000 instead of 1024 for advertising reasons.<br>"
+ "This results in 4.4*1024<sup>3</sup>/1000<sup>3</sup> = 4.7 GB.") );
+}
+
+
+void K3bFillStatusDisplay::slotCustomSize()
+{
+ // allow the units to be translated
+ QString gbS = i18n("gb");
+ QString mbS = i18n("mb");
+ QString minS = i18n("min");
+
+ QRegExp rx( "(\\d+\\" + KGlobal::locale()->decimalSymbol() + "?\\d*)(" + gbS + "|" + mbS + "|" + minS + ")?" );
+ bool ok;
+ QString size = KInputDialog::getText( i18n("Custom Size"),
+ i18n("<p>Please specify the size of the media. Use suffixes <b>gb</b>,<b>mb</b>, "
+ "and <b>min</b> for <em>gigabytes</em>, <em>megabytes</em>, and <em>minutes</em>"
+ " respectively."),
+ d->showDvdSizes ? QString("4%14%2").arg(KGlobal::locale()->decimalSymbol()).arg(gbS) :
+ (d->showTime ? QString("74")+minS : QString("650")+mbS),
+ &ok, this, (const char*)0,
+ new QRegExpValidator( rx, this ) );
+ if( ok ) {
+ // determine size
+ if( rx.exactMatch( size ) ) {
+ QString valStr = rx.cap(1);
+ if( valStr.endsWith( KGlobal::locale()->decimalSymbol() ) )
+ valStr += "0";
+ double val = KGlobal::locale()->readNumber( valStr, &ok );
+ if( ok ) {
+ QString s = rx.cap(2);
+ if( s == gbS || (s.isEmpty() && d->showDvdSizes) )
+ val *= 1024*512;
+ else if( s == mbS || (s.isEmpty() && !d->showTime) )
+ val *= 512;
+ else
+ val *= 60*75;
+ d->displayWidget->setCdSize( (int)val );
+ update();
+ }
+ }
+ }
+}
+
+
+void K3bFillStatusDisplay::slotMenuButtonClicked()
+{
+ QSize size = d->showDvdSizes ? d->dvdPopup->sizeHint() : d->popup->sizeHint();
+ slotPopupMenu( d->buttonMenu->mapToGlobal(QPoint(d->buttonMenu->width(), 0)) +
+ QPoint(-1*size.width(), -1*size.height()) );
+}
+
+
+void K3bFillStatusDisplay::slotPopupMenu( const QPoint& p )
+{
+ if( d->showDvdSizes )
+ d->dvdPopup->popup(p);
+ else
+ d->popup->popup(p);
+}
+
+
+void K3bFillStatusDisplay::slotDetermineSize()
+{
+ bool canceled = false;
+ K3bDevice::Device* dev = K3bMediaSelectionDialog::selectMedium( d->showDvdSizes ? K3bDevice::MEDIA_WRITABLE_DVD : K3bDevice::MEDIA_WRITABLE_CD,
+ K3bDevice::STATE_EMPTY|K3bDevice::STATE_INCOMPLETE,
+ parentWidget(),
+ QString::null, QString::null, &canceled );
+
+ if( dev ) {
+ K3b::Msf size = k3bappcore->mediaCache()->diskInfo( dev ).capacity();
+ if( size > 0 ) {
+ d->displayWidget->setCdSize( size );
+ d->actionCustomSize->setChecked(true);
+ update();
+ }
+ else
+ KMessageBox::error( parentWidget(), i18n("Medium is not empty.") );
+ }
+ else if( !canceled )
+ KMessageBox::error( parentWidget(), i18n("No usable medium found.") );
+}
+
+
+void K3bFillStatusDisplay::slotLoadUserDefaults()
+{
+ // load project specific values
+ KConfig* c = k3bcore->config();
+ c->setGroup( "default " + d->doc->typeString() + " settings" );
+
+ // defaults to megabytes
+ d->showTime = c->readBoolEntry( "show minutes", false );
+ d->displayWidget->setShowTime(d->showTime);
+ d->actionShowMegs->setChecked( !d->showTime );
+ d->actionShowMinutes->setChecked( d->showTime );
+
+
+ long size = c->readNumEntry( "default media size", 0 );
+
+ switch( size ) {
+ case 0:
+ // automatic mode
+ d->actionAuto->setChecked( true );
+ break;
+ case 74:
+ d->action74Min->setChecked( true );
+ break;
+ case 80:
+ d->action80Min->setChecked( true );
+ break;
+ case 100:
+ d->action100Min->setChecked( true );
+ break;
+ case 510:
+ d->actionDvd4_7GB->setChecked( true );
+ break;
+ default:
+ d->actionCustomSize->setChecked( true );
+ break;
+ }
+
+ if( size == 0 ) {
+ slotMediumChanged( 0 );
+ }
+ else {
+ d->displayWidget->setCdSize( size*60*75 );
+ }
+}
+
+
+void K3bFillStatusDisplay::slotMediumChanged( K3bDevice::Device* )
+{
+ if( d->actionAuto->isChecked() ) {
+ //
+ // now search for a usable medium
+ // if we find exactly one usable or multiple with the same size
+ // we use that size
+ //
+
+ // TODO: once we have only one data project we need to change this to handle both
+
+ K3bDevice::Device* dev = 0;
+ QPtrList<K3bDevice::Device> devs;
+ if( d->showDvdSizes )
+ devs = k3bcore->deviceManager()->dvdWriter();
+ else
+ devs = k3bcore->deviceManager()->cdWriter();
+
+ for( QPtrListIterator<K3bDevice::Device> it( devs ); *it; ++it ) {
+ const K3bMedium& medium = k3bappcore->mediaCache()->medium( *it );
+
+ if( ( medium.diskInfo().empty() ||
+ medium.diskInfo().appendable() ||
+ medium.diskInfo().rewritable() ) &&
+ ( medium.diskInfo().isDvdMedia() == d->showDvdSizes ) &&
+ d->doc->length() <= medium.diskInfo().capacity() ) {
+
+ // first usable medium
+ if( !dev ) {
+ dev = medium.device();
+ }
+
+ // roughly compare the sizes of the two usable media. If they match, carry on.
+ else if( k3bappcore->mediaCache()->diskInfo( dev ).capacity().lba()/75/60
+ != medium.diskInfo().capacity().lba()/75/60 ) {
+ // different usable media -> fallback
+ dev = 0;
+ break;
+ }
+ // else continue;
+ }
+ }
+
+ if( dev ) {
+ d->displayWidget->setCdSize( k3bappcore->mediaCache()->diskInfo( dev ).capacity().lba() );
+ }
+ else {
+ // default fallback
+ if( d->showDvdSizes ) {
+ if( d->doc->length().lba() > DEFAULT_DVD_SIZE_4_4 )
+ d->displayWidget->setCdSize( DEFAULT_DVD_SIZE_8_0 );
+ else
+ d->displayWidget->setCdSize( DEFAULT_DVD_SIZE_4_4 );
+ }
+ else
+ d->displayWidget->setCdSize( DEFAULT_CD_SIZE_80 );
+ }
+ }
+}
+
+
+void K3bFillStatusDisplay::slotSaveUserDefaults()
+{
+ // save project specific values
+ KConfig* c = k3bcore->config();
+ c->setGroup( "default " + d->doc->typeString() + " settings" );
+
+ c->writeEntry( "show minutes", d->showTime );
+ c->writeEntry( "default media size", d->actionAuto->isChecked() ? 0 : d->displayWidget->cdSize().totalFrames() );
+}
+
+
+void K3bFillStatusDisplay::slotUpdateDisplay()
+{
+ if( d->actionAuto->isChecked() ) {
+ //
+ // also update the medium list in case the docs size exceeds the capacity
+ //
+ slotMediumChanged( 0 );
+ }
+ else {
+ d->displayWidget->update();
+ }
+}
+
+
+void K3bFillStatusDisplay::slotDocChanged()
+{
+ // cache updates
+ if( !d->updateTimer.isActive() ) {
+ slotUpdateDisplay();
+ d->updateTimer.start( 500, false );
+ }
+}
+
+#include "k3bfillstatusdisplay.moc"
diff --git a/src/projects/k3bfillstatusdisplay.h b/src/projects/k3bfillstatusdisplay.h
new file mode 100644
index 0000000..f477faa
--- /dev/null
+++ b/src/projects/k3bfillstatusdisplay.h
@@ -0,0 +1,117 @@
+
+/*
+ *
+ * $Id: k3bfillstatusdisplay.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BFILLSTATUSDISPLAY_H
+#define K3BFILLSTATUSDISPLAY_H
+
+#include <qframe.h>
+#include <qtooltip.h>
+
+
+class QPaintEvent;
+class QMouseEvent;
+class K3bDoc;
+class KToggleAction;
+class KAction;
+class KActionCollection;
+class KPopupMenu;
+class QToolButton;
+
+namespace K3bDevice {
+ class Device;
+}
+namespace K3b {
+ class Msf;
+}
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bFillStatusDisplayWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bFillStatusDisplayWidget( K3bDoc* doc, QWidget* parent );
+ ~K3bFillStatusDisplayWidget();
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ const K3b::Msf& cdSize() const;
+
+ public slots:
+ void setShowTime( bool b );
+ void setCdSize( const K3b::Msf& );
+
+ signals:
+ void contextMenu( const QPoint& );
+
+ protected:
+ void mousePressEvent( QMouseEvent* );
+ void paintEvent(QPaintEvent*);
+
+ private:
+ class Private;
+ Private* d;
+};
+
+
+class K3bFillStatusDisplay : public QFrame {
+
+ Q_OBJECT
+
+ public:
+ K3bFillStatusDisplay(K3bDoc* doc, QWidget *parent=0, const char *name=0);
+ ~K3bFillStatusDisplay();
+
+ public slots:
+ void showSize();
+ void showTime();
+ void showDvdSizes( bool );
+
+ protected:
+ void setupPopupMenu();
+
+ private slots:
+ void slotAutoSize();
+ void slot74Minutes();
+ void slot80Minutes();
+ void slot100Minutes();
+ void slotDvd4_7GB();
+ void slotDvdDoubleLayer();
+ void slotWhy44();
+ void slotCustomSize();
+ void slotMenuButtonClicked();
+ void slotPopupMenu(const QPoint&);
+ void slotDetermineSize();
+ void slotDocChanged();
+ void slotMediumChanged( K3bDevice::Device* dev );
+ void slotUpdateDisplay();
+
+ void slotLoadUserDefaults();
+ void slotSaveUserDefaults();
+
+ private:
+ class ToolTip;
+ ToolTip* m_toolTip;
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/projects/k3bmixedburndialog.cpp b/src/projects/k3bmixedburndialog.cpp
new file mode 100644
index 0000000..5d5ad28
--- /dev/null
+++ b/src/projects/k3bmixedburndialog.cpp
@@ -0,0 +1,353 @@
+/*
+ *
+ * $Id: k3bmixedburndialog.cpp 627521 2007-01-26 22:39:53Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmixedburndialog.h"
+#include "k3bmixeddoc.h"
+#include "k3bmixedview.h"
+
+#include <k3bdataimagesettingswidget.h>
+#include <k3bdatadoc.h>
+#include <k3baudiodoc.h>
+#include <k3bdevice.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bisooptions.h>
+#include <k3bglobals.h>
+#include <k3baudiocdtextwidget.h>
+#include <k3bdatamodewidget.h>
+#include <k3bmsf.h>
+#include <k3bstdguiitems.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bversion.h>
+#include <k3bcore.h>
+#include <k3baudiotrackplayer.h>
+#include <k3bintmapcombobox.h>
+
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qframe.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qvbox.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+
+K3bMixedBurnDialog::K3bMixedBurnDialog( K3bMixedDoc* doc, QWidget *parent, const char *name, bool modal )
+ : K3bProjectBurnDialog( doc, parent, name, modal ), m_doc(doc)
+{
+ prepareGui();
+
+ setTitle( i18n("Mixed Project"), i18n("1 track (%1 minutes)",
+ "%n tracks (%1 minutes)",
+ m_doc->numOfTracks()).arg(m_doc->length().toString()) );
+
+ m_checkOnlyCreateImage->hide();
+
+ // create cd-text page
+ m_cdtextWidget = new K3bAudioCdTextWidget( this );
+ addPage( m_cdtextWidget, i18n("CD-Text") );
+
+ // create image settings tab
+ m_imageSettingsWidget = new K3bDataImageSettingsWidget( this );
+ addPage( m_imageSettingsWidget, i18n("Filesystem") );
+
+ setupSettingsPage();
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ connect( m_checkNormalize, SIGNAL(toggled(bool)), this, SLOT(slotNormalizeToggled(bool)) );
+ connect( m_checkCacheImage, SIGNAL(toggled(bool)), this, SLOT(slotCacheImageToggled(bool)) );
+ connect( m_writerSelectionWidget, SIGNAL(writingAppChanged(int)), this, SLOT(slotToggleAll()) );
+ connect( m_writingModeWidget, SIGNAL(writingModeChanged(int)), this, SLOT(slotToggleAll()) );
+}
+
+
+void K3bMixedBurnDialog::setupSettingsPage()
+{
+ QWidget* w = new QWidget( this );
+
+ QGroupBox* groupDataMode = new QGroupBox( 1, Qt::Vertical, i18n("Datatrack Mode"), w );
+ m_dataModeWidget = new K3bDataModeWidget( groupDataMode );
+
+ QGroupBox* groupNormalize = new QGroupBox( 1, Qt::Vertical, i18n("Misc"), w );
+ m_checkNormalize = K3bStdGuiItems::normalizeCheckBox( groupNormalize );
+
+ QGroupBox* groupMixedType = new QGroupBox( 1, Qt::Vertical, i18n("Mixed Mode Type"), w );
+ m_comboMixedModeType = new K3bIntMapComboBox( groupMixedType );
+
+ m_comboMixedModeType->insertItem( K3bMixedDoc::DATA_SECOND_SESSION,
+ i18n("Data in second session (CD-Extra)"),
+ i18n("<em>Blue book CD</em>"
+ "<br>K3b will create a multisession CD with "
+ "2 sessions. The first session will contain all "
+ "audio tracks and the second session will contain "
+ "a mode 2 form 1 data track."
+ "<br>This mode is based on the <em>Blue book</em> "
+ "standard (also known as <em>Extended Audio CD</em>, "
+ "<em>CD-Extra</em>, or <em>CD Plus</em>) "
+ "and has the advantage that a hifi audio "
+ "CD player will only recognize the first session "
+ "and ignore the second session with the data track."
+ "<br>If the CD is intended to be used in a hifi audio CD player "
+ "this is the recommended mode."
+ "<br>Some older CD-ROMs may have problems reading "
+ "a blue book CD since it is a multisession CD.") );
+ m_comboMixedModeType->insertItem( K3bMixedDoc::DATA_FIRST_TRACK,
+ i18n("Data in first track"),
+ i18n("K3b will write the data track before all "
+ "audio tracks.") );
+ m_comboMixedModeType->insertItem( K3bMixedDoc::DATA_LAST_TRACK,
+ i18n("Data in last track"),
+ i18n("K3b will write the data track after all "
+ "audio tracks.") );
+ m_comboMixedModeType->addGlobalWhatsThisText( QString(),
+ i18n("<b>Caution:</b> The last two modes should only be used for CDs that are unlikely to "
+ "be played on a hifi audio CD player."
+ "<br>It could lead to problems with some older "
+ "hifi audio CD players that try to play the data track.") );
+
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setMargin( marginHint() );
+ grid->setSpacing( spacingHint() );
+ grid->addWidget( groupMixedType, 0, 0 );
+ grid->addWidget( groupDataMode, 1, 0 );
+ grid->addWidget( groupNormalize, 2, 0 );
+ grid->setRowStretch( 3, 1 );
+
+ addPage( w, i18n("Misc") );
+}
+
+
+void K3bMixedBurnDialog::slotStartClicked()
+{
+ // FIXME: this should not be done via the doc. So remove all gui stuff from the doc
+ static_cast<K3bMixedView*>(m_doc->view())->player()->stop();
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+
+void K3bMixedBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ m_doc->setMixedType( (K3bMixedDoc::MixedType)m_comboMixedModeType->selectedValue() );
+
+ m_cdtextWidget->save( m_doc->audioDoc() );
+
+ m_doc->audioDoc()->setNormalize( m_checkNormalize->isChecked() );
+
+ // save iso image settings
+ K3bIsoOptions o = m_doc->dataDoc()->isoOptions();
+ m_imageSettingsWidget->save( o );
+ m_doc->dataDoc()->setIsoOptions( o );
+
+ m_doc->dataDoc()->setDataMode( m_dataModeWidget->dataMode() );
+
+ // save image file path
+ m_doc->setTempDir( m_tempDirSelectionWidget->tempPath() );
+}
+
+
+void K3bMixedBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ m_checkNormalize->setChecked( m_doc->audioDoc()->normalize() );
+
+ if( !m_doc->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( m_doc->tempDir() );
+
+ m_comboMixedModeType->setSelectedValue( m_doc->mixedType() );
+
+ m_cdtextWidget->load( m_doc->audioDoc() );
+
+ m_imageSettingsWidget->load( m_doc->dataDoc()->isoOptions() );
+
+ m_dataModeWidget->setDataMode( m_doc->dataDoc()->dataMode() );
+
+ toggleAll();
+}
+
+
+void K3bMixedBurnDialog::loadK3bDefaults()
+{
+ K3bProjectBurnDialog::loadK3bDefaults();
+
+ m_cdtextWidget->setChecked( false );
+ m_checkNormalize->setChecked( false );
+
+ m_comboMixedModeType->setSelectedValue( K3bMixedDoc::DATA_SECOND_SESSION );
+
+ m_dataModeWidget->setDataMode( K3b::DATA_MODE_AUTO );
+
+ m_imageSettingsWidget->load( K3bIsoOptions::defaults() );
+
+ toggleAll();
+}
+
+
+void K3bMixedBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults( c );
+
+ m_cdtextWidget->setChecked( c->readBoolEntry( "cd_text", false ) );
+ m_checkNormalize->setChecked( c->readBoolEntry( "normalize", false ) );
+
+ // load mixed type
+ if( c->readEntry( "mixed_type" ) == "last_track" )
+ m_comboMixedModeType->setSelectedValue( K3bMixedDoc::DATA_LAST_TRACK );
+ else if( c->readEntry( "mixed_type" ) == "first_track" )
+ m_comboMixedModeType->setSelectedValue( K3bMixedDoc::DATA_FIRST_TRACK );
+ else
+ m_comboMixedModeType->setSelectedValue( K3bMixedDoc::DATA_SECOND_SESSION );
+
+ m_dataModeWidget->loadConfig(c);
+
+ K3bIsoOptions o = K3bIsoOptions::load( c );
+ m_imageSettingsWidget->load( o );
+
+ toggleAll();
+}
+
+
+void K3bMixedBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults(c);
+
+ c->writeEntry( "cd_text", m_cdtextWidget->isChecked() );
+ c->writeEntry( "normalize", m_checkNormalize->isChecked() );
+
+ // save mixed type
+ switch( m_comboMixedModeType->selectedValue() ) {
+ case K3bMixedDoc::DATA_LAST_TRACK:
+ c->writeEntry( "mixed_type", "last_track" );
+ break;
+ case K3bMixedDoc::DATA_FIRST_TRACK:
+ c->writeEntry( "mixed_type", "first_track" );
+ break;
+ default:
+ c->writeEntry( "mixed_type", "second_session" );
+ }
+
+ m_dataModeWidget->saveConfig(c);
+
+ K3bIsoOptions o;
+ m_imageSettingsWidget->save( o );
+ o.save( c );
+
+ if( m_tempDirSelectionWidget->isEnabled() ) {
+ m_tempDirSelectionWidget->saveConfig();
+ }
+}
+
+
+void K3bMixedBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ bool cdrecordOnTheFly = false;
+ bool cdrecordCdText = false;
+ if ( k3bcore->externalBinManager()->binObject("cdrecord") ) {
+ cdrecordOnTheFly = k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "audio-stdin" );
+ cdrecordCdText = k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "cdtext" );
+ }
+
+ // cdrdao always knows onthefly and cdtext
+ bool onTheFly = true;
+ bool cdText = true;
+ if( m_writingModeWidget->writingMode() == K3b::TAO ||
+ m_writingModeWidget->writingMode() == K3b::RAW ||
+ m_writerSelectionWidget->writingApp() == K3b::CDRECORD ) {
+ onTheFly = cdrecordOnTheFly;
+ cdText = cdrecordCdText;
+ }
+
+ m_checkCacheImage->setEnabled( !m_checkOnlyCreateImage->isChecked() &&
+ onTheFly );
+ if( !onTheFly )
+ m_checkCacheImage->setChecked( true );
+
+ m_cdtextWidget->setEnabled( !m_checkOnlyCreateImage->isChecked() &&
+ cdText &&
+ m_writingModeWidget->writingMode() != K3b::TAO );
+ if( !cdText || m_writingModeWidget->writingMode() == K3b::TAO )
+ m_cdtextWidget->setChecked( false );
+}
+
+
+void K3bMixedBurnDialog::slotNormalizeToggled( bool on )
+{
+ if( on ) {
+ // we are not able to normalize in on-the-fly mode
+ if( !k3bcore->externalBinManager()->foundBin( "normalize" ) ) {
+ KMessageBox::sorry( this, i18n("<p><b>External program <em>normalize-audio</em> is not installed.</b>"
+ "<p>K3b uses <em>normalize-audio</em> (http://www1.cs.columbia.edu/~cvaill/normalize/) "
+ "to normalize audio tracks. In order to "
+ "use this functionality, please install it first (sudo apt-get install normalize-audio.") );
+ m_checkNormalize->setChecked( false );
+ }
+ else if( !m_checkCacheImage->isChecked() && !m_checkOnlyCreateImage->isChecked() ) {
+ if( KMessageBox::warningYesNo( this, i18n("<p>K3b is not able to normalize audio tracks when burning on-the-fly. "
+ "The external program used for this task only supports normalizing a set "
+ "of audio files."),
+ QString::null,
+ i18n("Disable normalization"),
+ i18n("Disable on-the-fly burning"),
+ "audioProjectNormalizeOrOnTheFly" ) == KMessageBox::Yes )
+ m_checkNormalize->setChecked( false );
+ else
+ m_checkCacheImage->setChecked( true );
+ }
+ }
+}
+
+
+void K3bMixedBurnDialog::slotCacheImageToggled( bool on )
+{
+ if( on ) {
+ if( m_checkNormalize->isChecked() ) {
+ if( KMessageBox::warningYesNo( this, i18n("<p>K3b is not able to normalize audio tracks when burning on-the-fly. "
+ "The external program used for this task only supports normalizing a set "
+ "of audio files."),
+ QString::null,
+ i18n("Disable normalization"),
+ i18n("Disable on-the-fly burning"),
+ "audioProjectNormalizeOrOnTheFly" ) == KMessageBox::Yes )
+ m_checkNormalize->setChecked( false );
+ else
+ m_checkCacheImage->setChecked( true );
+ }
+ }
+}
+
+
+#include "k3bmixedburndialog.moc"
+
diff --git a/src/projects/k3bmixedburndialog.h b/src/projects/k3bmixedburndialog.h
new file mode 100644
index 0000000..363d26e
--- /dev/null
+++ b/src/projects/k3bmixedburndialog.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * $Id: k3bmixedburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BMIXEDBURNDIALOG_H
+#define K3BMIXEDBURNDIALOG_H
+
+#include "k3bprojectburndialog.h"
+
+class QCheckBox;
+class K3bWriterSelectionWidget;
+class K3bTempDirSelectionWidget;
+class K3bMixedDoc;
+class K3bDataImageSettingsWidget;
+class QButtonGroup;
+class QRadioButton;
+class K3bAudioCdTextWidget;
+class K3bDataModeWidget;
+class K3bIntMapComboBox;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bMixedBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bMixedBurnDialog( K3bMixedDoc*, QWidget *parent=0, const char *name=0, bool modal = true );
+
+ protected:
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void toggleAll();
+
+ K3bDataImageSettingsWidget* m_imageSettingsWidget;
+ K3bAudioCdTextWidget* m_cdtextWidget;
+
+ protected slots:
+ /**
+ * Reimplemented for internal reasons (shut down the audio player)
+ */
+ void slotStartClicked();
+ void saveSettings();
+ void readSettings();
+
+ void slotCacheImageToggled( bool on );
+ void slotNormalizeToggled( bool on );
+
+ private:
+ void setupSettingsPage();
+ K3bMixedDoc* m_doc;
+
+ K3bIntMapComboBox* m_comboMixedModeType;
+ QRadioButton* m_radioMixedTypeFirstTrack;
+ QRadioButton* m_radioMixedTypeLastTrack;
+ QRadioButton* m_radioMixedTypeSessions;
+
+ QCheckBox* m_checkNormalize;
+
+ K3bDataModeWidget* m_dataModeWidget;
+};
+
+#endif
diff --git a/src/projects/k3bmixeddirtreeview.cpp b/src/projects/k3bmixeddirtreeview.cpp
new file mode 100644
index 0000000..50d818a
--- /dev/null
+++ b/src/projects/k3bmixeddirtreeview.cpp
@@ -0,0 +1,103 @@
+/*
+ *
+ * $Id: k3bmixeddirtreeview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bmixeddirtreeview.h"
+
+#include "k3bmixeddoc.h"
+#include "k3baudiotrackaddingdialog.h"
+#include <k3blistview.h>
+#include <k3baudiodoc.h>
+#include <k3bdataviewitem.h>
+
+#include <qevent.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kurldrag.h>
+#include <klocale.h>
+
+
+class K3bMixedDirTreeView::PrivateAudioRootViewItem : public K3bListViewItem
+{
+public:
+ PrivateAudioRootViewItem( K3bMixedDoc* doc, QListView* parent, QListViewItem* after )
+ : K3bListViewItem( parent, after ),
+ m_doc(doc)
+ {
+ setPixmap( 0, SmallIcon("sound") );
+ }
+
+ QString text( int col ) const {
+ if( col == 0 )
+ return i18n("Audio Tracks") + QString(" (%1)").arg(m_doc->audioDoc()->numOfTracks());
+ else
+ return QString::null;
+ }
+
+ private:
+ K3bMixedDoc* m_doc;
+};
+
+
+K3bMixedDirTreeView::K3bMixedDirTreeView( K3bView* view, K3bMixedDoc* doc, QWidget* parent, const char* )
+ : K3bDataDirTreeView( view, doc->dataDoc(), parent ), m_doc(doc)
+{
+ m_audioRootItem = new PrivateAudioRootViewItem( doc, this, root() );
+
+ connect( this, SIGNAL(selectionChanged(QListViewItem*)),
+ this, SLOT(slotSelectionChanged(QListViewItem*)) );
+ connect( m_doc->audioDoc(), SIGNAL(changed()), this, SLOT(slotNewAudioTracks()) );
+}
+
+
+K3bMixedDirTreeView::~K3bMixedDirTreeView()
+{
+}
+
+
+void K3bMixedDirTreeView::slotDropped( QDropEvent* e, QListViewItem* parent, QListViewItem* after )
+{
+ if( !e->isAccepted() )
+ return;
+
+ QListViewItem* droppedItem = itemAt(e->pos());
+ if( droppedItem == m_audioRootItem ) {
+ KURL::List urls;
+ if( KURLDrag::decode( e, urls ) ) {
+ K3bAudioTrackAddingDialog::addUrls( urls, m_doc->audioDoc(), 0, 0, 0, this );
+ }
+ }
+ else
+ K3bDataDirTreeView::slotDropped( e, parent, after );
+}
+
+
+void K3bMixedDirTreeView::slotSelectionChanged( QListViewItem* i )
+{
+ if( i == m_audioRootItem )
+ emit audioTreeSelected();
+ else
+ emit dataTreeSelected();
+}
+
+
+void K3bMixedDirTreeView::slotNewAudioTracks()
+{
+ // update the tracknumber
+ m_audioRootItem->repaint();
+}
+
+#include "k3bmixeddirtreeview.moc"
diff --git a/src/projects/k3bmixeddirtreeview.h b/src/projects/k3bmixeddirtreeview.h
new file mode 100644
index 0000000..8a8bfe9
--- /dev/null
+++ b/src/projects/k3bmixeddirtreeview.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * $Id: k3bmixeddirtreeview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef _K3B_MIXED_DIRTREEVIEW_H_
+#define _K3B_MIXED_DIRTREEVIEW_H_
+
+#include <k3bdatadirtreeview.h>
+
+class K3bView;
+class K3bMixedDoc;
+class QDropEvent;
+class QListViewItem;
+
+
+class K3bMixedDirTreeView : public K3bDataDirTreeView
+{
+ Q_OBJECT
+
+ public:
+ K3bMixedDirTreeView( K3bView* view, K3bMixedDoc* doc, QWidget* parent = 0, const char* name = 0 );
+ ~K3bMixedDirTreeView();
+
+ signals:
+ void audioTreeSelected();
+ void dataTreeSelected();
+
+ protected slots:
+ void slotDropped( QDropEvent* e, QListViewItem* after, QListViewItem* parent );
+
+ private slots:
+ void slotSelectionChanged( QListViewItem* i );
+ void slotNewAudioTracks();
+
+ private:
+ K3bMixedDoc* m_doc;
+
+ class PrivateAudioRootViewItem;
+ PrivateAudioRootViewItem* m_audioRootItem;
+};
+
+
+#endif
diff --git a/src/projects/k3bmixedview.cpp b/src/projects/k3bmixedview.cpp
new file mode 100644
index 0000000..68900c7
--- /dev/null
+++ b/src/projects/k3bmixedview.cpp
@@ -0,0 +1,155 @@
+/*
+ *
+ * $Id: k3bmixedview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmixedview.h"
+
+#include "k3bmixeddoc.h"
+#include "k3bmixedburndialog.h"
+#include "k3bmixeddirtreeview.h"
+#include "k3baudiotrackaddingdialog.h"
+#include "k3bdataurladdingdialog.h"
+
+#include <k3baudiotrackplayer.h>
+#include <k3baudiodoc.h>
+#include <k3bdataviewitem.h>
+#include <k3bdatafileview.h>
+#include <k3bdatadoc.h>
+#include <k3baudiotrackview.h>
+#include <k3bfillstatusdisplay.h>
+#include <k3btoolbox.h>
+#include <k3bprojectplugin.h>
+
+#include <qwidgetstack.h>
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qvaluelist.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kactionclasses.h>
+
+
+K3bMixedView::K3bMixedView( K3bMixedDoc* doc, QWidget* parent, const char* name )
+ : K3bView( doc, parent, name ), m_doc(doc)
+{
+ QSplitter* splitter = new QSplitter( this );
+ m_mixedDirTreeView = new K3bMixedDirTreeView( this, doc, splitter );
+ m_widgetStack = new QWidgetStack( splitter );
+ m_dataFileView = new K3bDataFileView( this, m_mixedDirTreeView, doc->dataDoc(), m_widgetStack );
+ m_mixedDirTreeView->setFileView( m_dataFileView );
+ m_audioListView = new K3bAudioTrackView( doc->audioDoc(), m_widgetStack );
+
+ setMainWidget( splitter );
+
+ connect( m_mixedDirTreeView, SIGNAL(audioTreeSelected()),
+ this, SLOT(slotAudioTreeSelected()) );
+ connect( m_mixedDirTreeView, SIGNAL(dataTreeSelected()),
+ this, SLOT(slotDataTreeSelected()) );
+
+ m_widgetStack->raiseWidget( m_dataFileView );
+
+ toolBox()->addButton( m_audioListView->player()->action( K3bAudioTrackPlayer::ACTION_PLAY ) );
+ toolBox()->addButton( m_audioListView->player()->action( K3bAudioTrackPlayer::ACTION_PAUSE ) );
+ toolBox()->addButton( m_audioListView->player()->action( K3bAudioTrackPlayer::ACTION_STOP ) );
+ toolBox()->addSpacing();
+ toolBox()->addButton( m_audioListView->player()->action( K3bAudioTrackPlayer::ACTION_PREV ) );
+ toolBox()->addButton( m_audioListView->player()->action( K3bAudioTrackPlayer::ACTION_NEXT ) );
+ toolBox()->addSpacing();
+ toolBox()->addWidgetAction( static_cast<KWidgetAction*>(m_audioListView->player()->action( K3bAudioTrackPlayer::ACTION_SEEK )) );
+ toolBox()->addSeparator();
+
+#ifdef HAVE_MUSICBRAINZ
+ toolBox()->addButton( m_audioListView->actionCollection()->action( "project_audio_musicbrainz" ) );
+ toolBox()->addSeparator();
+#endif
+
+ addPluginButtons( K3bProjectPlugin::MIXED_CD );
+
+ toolBox()->addStretch();
+
+ m_mixedDirTreeView->checkForNewItems();
+ m_dataFileView->checkForNewItems();
+}
+
+
+K3bMixedView::~K3bMixedView()
+{
+}
+
+
+K3bAudioTrackPlayer* K3bMixedView::player() const
+{
+ return m_audioListView->player();
+}
+
+
+void K3bMixedView::slotAudioTreeSelected()
+{
+ m_widgetStack->raiseWidget( m_audioListView );
+}
+
+
+void K3bMixedView::slotDataTreeSelected()
+{
+ m_widgetStack->raiseWidget( m_dataFileView );
+}
+
+
+K3bDirItem* K3bMixedView::currentDir() const
+{
+ if( m_widgetStack->visibleWidget() == m_dataFileView )
+ return m_dataFileView->currentDir();
+ else
+ return 0;
+}
+
+
+void K3bMixedView::slotBurn()
+{
+ if( m_doc->audioDoc()->numOfTracks() == 0 || m_doc->dataDoc()->size() == 0 ) {
+ KMessageBox::information( this, i18n("Please add files and audio titles to your project first."),
+ i18n("No Data to Burn"), QString::null, false );
+ }
+ else {
+ K3bProjectBurnDialog* dlg = newBurnDialog( this );
+ if( dlg ) {
+ dlg->execBurnDialog(true);
+ delete dlg;
+ }
+ else {
+ kdDebug() << "(K3bDoc) Error: no burndialog available." << endl;
+ }
+ }
+}
+
+
+K3bProjectBurnDialog* K3bMixedView::newBurnDialog( QWidget* parent, const char* name )
+{
+ return new K3bMixedBurnDialog( m_doc, parent, name, true );
+}
+
+
+void K3bMixedView::addUrls( const KURL::List& urls )
+{
+ if( m_widgetStack->visibleWidget() == m_dataFileView )
+ K3bDataUrlAddingDialog::addUrls( urls, currentDir() );
+ else
+ K3bAudioTrackAddingDialog::addUrls( urls, m_doc->audioDoc(), 0, 0, 0, this );
+}
+
+#include "k3bmixedview.moc"
diff --git a/src/projects/k3bmixedview.h b/src/projects/k3bmixedview.h
new file mode 100644
index 0000000..8e52df7
--- /dev/null
+++ b/src/projects/k3bmixedview.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * $Id: k3bmixedview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3B_MIXED_VIEW_H
+#define K3B_MIXED_VIEW_H
+
+#include <k3bview.h>
+
+#include <kurl.h>
+
+class K3bMixedDoc;
+class QWidgetStack;
+class K3bDataFileView;
+class K3bMixedDirTreeView;
+class K3bAudioTrackView;
+class QListViewItem;
+class K3bDirItem;
+class K3bAudioTrackPlayer;
+
+
+class K3bMixedView : public K3bView
+{
+ Q_OBJECT
+
+ public:
+ K3bMixedView( K3bMixedDoc* doc, QWidget* parent = 0, const char* name = 0 );
+ ~K3bMixedView();
+
+ K3bDirItem* currentDir() const;
+
+ K3bAudioTrackPlayer* player() const;
+
+ public slots:
+ void slotBurn();
+ void addUrls( const KURL::List& );
+
+ protected:
+ K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ private slots:
+ void slotAudioTreeSelected();
+ void slotDataTreeSelected();
+
+ private:
+ K3bMixedDoc* m_doc;
+
+ QWidgetStack* m_widgetStack;
+
+ K3bMixedDirTreeView* m_mixedDirTreeView;
+ K3bDataFileView* m_dataFileView;
+ K3bAudioTrackView* m_audioListView;
+};
+
+#endif
diff --git a/src/projects/k3bmovixburndialog.cpp b/src/projects/k3bmovixburndialog.cpp
new file mode 100644
index 0000000..94238a7
--- /dev/null
+++ b/src/projects/k3bmovixburndialog.cpp
@@ -0,0 +1,265 @@
+/*
+ *
+ * $Id: k3bmovixburndialog.cpp 690207 2007-07-20 10:40:19Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bmovixburndialog.h"
+#include "k3bmovixdoc.h"
+#include "k3bmovixprogram.h"
+#include "k3bmovixoptionswidget.h"
+
+#include <k3bdataimagesettingswidget.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bstdguiitems.h>
+#include <k3bglobals.h>
+#include <k3bdatamodewidget.h>
+#include <k3bisooptions.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bcore.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kio/global.h>
+#include <kapplication.h>
+#include <kconfig.h>
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qfileinfo.h>
+
+
+K3bMovixBurnDialog::K3bMovixBurnDialog( K3bMovixDoc* doc, QWidget* parent, const char* name, bool modal )
+ : K3bProjectBurnDialog( doc, parent, name, modal ),
+ m_doc(doc)
+{
+ prepareGui();
+
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+
+ setTitle( i18n("eMovix CD Project"),
+ i18n("1 file (%1)", "%n files (%1)", m_doc->movixFileItems().count()).arg(KIO::convertSize(m_doc->size())) );
+
+ m_movixOptionsWidget = new K3bMovixOptionsWidget( this );
+ addPage( m_movixOptionsWidget, i18n("eMovix") );
+
+ // create image settings tab
+ m_imageSettingsWidget = new K3bDataImageSettingsWidget( this );
+ addPage( m_imageSettingsWidget, i18n("Filesystem") );
+
+ setupSettingsPage();
+
+ // for now we just put the verify checkbox on the main page...
+ m_checkVerify = K3bStdGuiItems::verifyCheckBox( m_optionGroup );
+ m_optionGroupLayout->addWidget( m_checkVerify );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+ QString path = m_doc->tempDir();
+ if( !path.isEmpty() ) {
+ m_tempDirSelectionWidget->setTempPath( path );
+ }
+ if( !m_doc->isoOptions().volumeID().isEmpty() ) {
+ m_tempDirSelectionWidget->setDefaultImageFileName( m_doc->isoOptions().volumeID() + ".iso" );
+ }
+
+ connect( m_imageSettingsWidget->m_editVolumeName, SIGNAL(textChanged(const QString&)),
+ m_tempDirSelectionWidget, SLOT(setDefaultImageFileName(const QString&)) );
+}
+
+
+K3bMovixBurnDialog::~K3bMovixBurnDialog()
+{
+}
+
+
+void K3bMovixBurnDialog::setupSettingsPage()
+{
+ QWidget* frame = new QWidget( this );
+ QGridLayout* frameLayout = new QGridLayout( frame );
+ frameLayout->setSpacing( spacingHint() );
+ frameLayout->setMargin( marginHint() );
+
+ QGroupBox* groupDataMode = new QGroupBox( 1, Qt::Vertical, i18n("Datatrack Mode"), frame );
+ m_dataModeWidget = new K3bDataModeWidget( groupDataMode );
+
+ QGroupBox* groupMultisession = new QGroupBox( 1, Qt::Vertical, i18n("Multisession"), frame );
+ m_checkStartMultiSesssion = K3bStdGuiItems::startMultisessionCheckBox( groupMultisession );
+
+ frameLayout->addWidget( groupDataMode, 0, 0 );
+ frameLayout->addWidget( groupMultisession, 1, 0 );
+ frameLayout->setRowStretch( 2, 1 );
+
+ addPage( frame, i18n("Misc") );
+}
+
+
+void K3bMovixBurnDialog::loadK3bDefaults()
+{
+ K3bProjectBurnDialog::loadK3bDefaults();
+
+ m_checkStartMultiSesssion->setChecked( false );
+ m_dataModeWidget->setDataMode( K3b::DATA_MODE_AUTO );
+
+ m_imageSettingsWidget->load( K3bIsoOptions::defaults() );
+
+ m_movixOptionsWidget->loadDefaults();
+
+ m_checkVerify->setChecked( false );
+
+ toggleAll();
+}
+
+
+void K3bMovixBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults(c);
+
+ m_checkStartMultiSesssion->setChecked( c->readBoolEntry( "start_multisession", false ) );
+
+ m_dataModeWidget->loadConfig(c);
+
+ K3bIsoOptions o = K3bIsoOptions::load( c );
+ m_imageSettingsWidget->load( o );
+
+ m_movixOptionsWidget->loadConfig(c);
+
+ m_checkVerify->setChecked( c->readBoolEntry( "verify data", false ) );
+
+ toggleAll();
+}
+
+
+void K3bMovixBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults(c);
+
+ c->writeEntry( "start_multisession", m_checkStartMultiSesssion->isChecked() );
+
+ m_dataModeWidget->saveConfig(c);
+
+ K3bIsoOptions o;
+ m_imageSettingsWidget->save( o );
+ o.save( c );
+
+ c->writeEntry( "verify data", m_checkVerify->isChecked() );
+
+ m_movixOptionsWidget->saveConfig(c);
+}
+
+
+void K3bMovixBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ m_movixOptionsWidget->saveSettings( m_doc );
+
+ m_doc->setMultiSessionMode( m_checkStartMultiSesssion->isChecked() ? K3bDataDoc::START : K3bDataDoc::NONE );
+
+ // save iso image settings
+ K3bIsoOptions o = m_doc->isoOptions();
+ m_imageSettingsWidget->save( o );
+ m_doc->setIsoOptions( o );
+
+ m_doc->setDataMode( m_dataModeWidget->dataMode() );
+
+ // save image file path
+ m_doc->setTempDir( m_tempDirSelectionWidget->tempPath() );
+
+ m_doc->setVerifyData( m_checkVerify->isChecked() );
+}
+
+
+void K3bMovixBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ m_checkStartMultiSesssion->setChecked( m_doc->multiSessionMode() == K3bDataDoc::START );
+
+ m_checkVerify->setChecked( m_doc->verifyData() );
+
+ m_imageSettingsWidget->load( m_doc->isoOptions() );
+
+ m_dataModeWidget->setDataMode( m_doc->dataMode() );
+
+ if( !doc()->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( doc()->tempDir() );
+ else
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() + doc()->name() + ".iso" );
+
+ // first of all we need a movix installation object
+ const K3bMovixBin* bin = dynamic_cast<const K3bMovixBin*>( k3bcore->externalBinManager()->binObject("eMovix") );
+ if( bin ) {
+ m_movixOptionsWidget->init( bin );
+ m_movixOptionsWidget->readSettings( m_doc );
+ }
+ else {
+ KMessageBox::error( this, i18n("Could not find a valid eMovix installation.") );
+ slotCancelClicked();
+ }
+}
+
+
+void K3bMovixBurnDialog::slotStartClicked()
+{
+ if( m_checkOnlyCreateImage->isChecked() ||
+ m_checkCacheImage->isChecked() ) {
+ QFileInfo fi( m_tempDirSelectionWidget->tempPath() );
+ if( fi.isDir() )
+ m_tempDirSelectionWidget->setTempPath( fi.filePath() + "/image.iso" );
+
+ if( QFile::exists( m_tempDirSelectionWidget->tempPath() ) ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(m_tempDirSelectionWidget->tempPath()),
+ i18n("File Exists"), i18n("Overwrite") )
+ != KMessageBox::Continue )
+ return;
+ }
+ }
+
+ if( m_writingModeWidget->writingMode() == K3b::DAO &&
+ m_checkStartMultiSesssion->isChecked() &&
+ m_writerSelectionWidget->writingApp() == K3b::CDRECORD )
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Most writers do not support writing "
+ "multisession CDs in DAO mode.") )
+ == KMessageBox::Cancel )
+ return;
+
+
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+
+void K3bMovixBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ if( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() ) {
+ m_checkVerify->setChecked(false);
+ m_checkVerify->setEnabled(false);
+ }
+ else
+ m_checkVerify->setEnabled(true);
+
+ m_dataModeWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_checkStartMultiSesssion->setDisabled( m_checkOnlyCreateImage->isChecked() );
+}
+
+#include "k3bmovixburndialog.moc"
diff --git a/src/projects/k3bmovixburndialog.h b/src/projects/k3bmovixburndialog.h
new file mode 100644
index 0000000..ff237c0
--- /dev/null
+++ b/src/projects/k3bmovixburndialog.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * $Id: k3bmovixburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef _K3B_MOVIX_BURN_DIALOG_H_
+#define _K3B_MOVIX_BURN_DIALOG_H_
+
+#include "k3bprojectburndialog.h"
+
+class K3bMovixDoc;
+class K3bMovixOptionsWidget;
+class K3bDataImageSettingsWidget;
+class QCheckBox;
+class K3bDataModeWidget;
+
+
+class K3bMovixBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bMovixBurnDialog( K3bMovixDoc* doc, QWidget* parent = 0, const char* name = 0, bool modal = true );
+ ~K3bMovixBurnDialog();
+
+ protected slots:
+ void slotStartClicked();
+
+ protected:
+ void saveSettings();
+ void readSettings();
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void toggleAll();
+
+ private:
+ void setupSettingsPage();
+
+ K3bMovixDoc* m_doc;
+ K3bMovixOptionsWidget* m_movixOptionsWidget;
+ K3bDataImageSettingsWidget* m_imageSettingsWidget;
+
+ QCheckBox* m_checkStartMultiSesssion;
+ K3bDataModeWidget* m_dataModeWidget;
+
+ QCheckBox* m_checkVerify;
+};
+
+
+#endif
+
diff --git a/src/projects/k3bmovixdvdburndialog.cpp b/src/projects/k3bmovixdvdburndialog.cpp
new file mode 100644
index 0000000..3707e3a
--- /dev/null
+++ b/src/projects/k3bmovixdvdburndialog.cpp
@@ -0,0 +1,219 @@
+/*
+ *
+ * $Id: k3bmovixdvdburndialog.cpp 690207 2007-07-20 10:40:19Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bmovixdvdburndialog.h"
+#include "k3bmovixdvddoc.h"
+
+#include <k3bmovixprogram.h>
+#include <k3bmovixoptionswidget.h>
+
+#include <k3bdataimagesettingswidget.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bstdguiitems.h>
+#include <k3bglobals.h>
+#include <k3bdatamodewidget.h>
+#include <k3bisooptions.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bcore.h>
+#include <k3bglobalsettings.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/global.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qfileinfo.h>
+
+
+K3bMovixDvdBurnDialog::K3bMovixDvdBurnDialog( K3bMovixDvdDoc* doc, QWidget* parent, const char* name, bool modal )
+ : K3bProjectBurnDialog( doc, parent, name, modal, true ),
+ m_doc(doc)
+{
+ prepareGui();
+
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+
+ setTitle( i18n("eMovix DVD Project"),
+ i18n("1 file (%1)", "%n files (%1)", m_doc->movixFileItems().count()).arg(KIO::convertSize(m_doc->size())) );
+
+ m_movixOptionsWidget = new K3bMovixOptionsWidget( this );
+ addPage( m_movixOptionsWidget, i18n("eMovix") );
+
+ // create image settings tab
+ m_imageSettingsWidget = new K3bDataImageSettingsWidget( this );
+ addPage( m_imageSettingsWidget, i18n("Filesystem") );
+
+ // for now we just put the verify checkbox on the main page...
+ m_checkVerify = K3bStdGuiItems::verifyCheckBox( m_optionGroup );
+ m_optionGroupLayout->addWidget( m_checkVerify );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+ QString path = m_doc->tempDir();
+ if( !path.isEmpty() ) {
+ m_tempDirSelectionWidget->setTempPath( path );
+ }
+ if( !m_doc->isoOptions().volumeID().isEmpty() ) {
+ m_tempDirSelectionWidget->setDefaultImageFileName( m_doc->isoOptions().volumeID() + ".iso" );
+ }
+
+ connect( m_imageSettingsWidget->m_editVolumeName, SIGNAL(textChanged(const QString&)),
+ m_tempDirSelectionWidget, SLOT(setDefaultImageFileName(const QString&)) );
+}
+
+
+K3bMovixDvdBurnDialog::~K3bMovixDvdBurnDialog()
+{
+}
+
+
+void K3bMovixDvdBurnDialog::loadK3bDefaults()
+{
+ K3bProjectBurnDialog::loadK3bDefaults();
+
+ m_imageSettingsWidget->load( K3bIsoOptions::defaults() );
+
+ m_movixOptionsWidget->loadDefaults();
+
+ m_checkVerify->setChecked( false );
+
+ toggleAll();
+}
+
+
+void K3bMovixDvdBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults(c);
+
+ K3bIsoOptions o = K3bIsoOptions::load( c );
+ m_imageSettingsWidget->load( o );
+
+ m_movixOptionsWidget->loadConfig(c);
+
+ m_checkVerify->setChecked( c->readBoolEntry( "verify data", false ) );
+
+ toggleAll();
+}
+
+
+void K3bMovixDvdBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults(c);
+
+ K3bIsoOptions o;
+ m_imageSettingsWidget->save( o );
+ o.save( c );
+
+ c->writeEntry( "verify data", m_checkVerify->isChecked() );
+
+ m_movixOptionsWidget->saveConfig(c);
+}
+
+
+void K3bMovixDvdBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ m_movixOptionsWidget->saveSettings( m_doc );
+
+ // save iso image settings
+ K3bIsoOptions o = m_doc->isoOptions();
+ m_imageSettingsWidget->save( o );
+ m_doc->setIsoOptions( o );
+
+ m_doc->setVerifyData( m_checkVerify->isChecked() );
+
+ // save image file path
+ m_doc->setTempDir( m_tempDirSelectionWidget->tempPath() );
+}
+
+
+void K3bMovixDvdBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ m_imageSettingsWidget->load( m_doc->isoOptions() );
+
+ m_checkVerify->setChecked( m_doc->verifyData() );
+
+ if( !doc()->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( doc()->tempDir() );
+ else
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() + doc()->name() + ".iso" );
+
+ // first of all we need a movix installation object
+ const K3bMovixBin* bin = dynamic_cast<const K3bMovixBin*>( k3bcore->externalBinManager()->binObject("eMovix") );
+ if( bin ) {
+ m_movixOptionsWidget->init( bin );
+ m_movixOptionsWidget->readSettings( m_doc );
+ }
+ else {
+ KMessageBox::error( this, i18n("Could not find a valid eMovix installation.") );
+ slotCancelClicked();
+ }
+
+ if( doc()->size() > 4700372992LL &&
+ ( !k3bcore->globalSettings()->overburn() ||
+ doc()->size() > 4900000000LL ) )
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD_DL );
+ else
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD );
+}
+
+
+void K3bMovixDvdBurnDialog::slotStartClicked()
+{
+ if( m_checkOnlyCreateImage->isChecked() ||
+ m_checkCacheImage->isChecked() ) {
+ QFileInfo fi( m_tempDirSelectionWidget->tempPath() );
+ if( fi.isDir() )
+ m_tempDirSelectionWidget->setTempPath( fi.filePath() + "/image.iso" );
+
+ if( QFile::exists( m_tempDirSelectionWidget->tempPath() ) ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(m_tempDirSelectionWidget->tempPath()),
+ i18n("File Exists"), i18n("Overwrite") )
+ != KMessageBox::Continue )
+ return;
+ }
+ }
+
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+
+void K3bMovixDvdBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ if( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() ) {
+ m_checkVerify->setChecked(false);
+ m_checkVerify->setEnabled(false);
+ }
+ else
+ m_checkVerify->setEnabled(true);
+}
+
+#include "k3bmovixdvdburndialog.moc"
diff --git a/src/projects/k3bmovixdvdburndialog.h b/src/projects/k3bmovixdvdburndialog.h
new file mode 100644
index 0000000..df7b456
--- /dev/null
+++ b/src/projects/k3bmovixdvdburndialog.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * $Id: k3bmovixdvdburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef _K3B_MOVIX_DVD_BURN_DIALOG_H_
+#define _K3B_MOVIX_DVD_BURN_DIALOG_H_
+
+#include "k3bprojectburndialog.h"
+
+class K3bMovixDvdDoc;
+class K3bMovixOptionsWidget;
+class K3bDataImageSettingsWidget;
+class QCheckBox;
+
+
+class K3bMovixDvdBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bMovixDvdBurnDialog( K3bMovixDvdDoc* doc, QWidget* parent = 0, const char* name = 0, bool modal = true );
+ ~K3bMovixDvdBurnDialog();
+
+ protected slots:
+ void slotStartClicked();
+
+ protected:
+ void saveSettings();
+ void readSettings();
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void toggleAll();
+
+ private:
+ K3bMovixDvdDoc* m_doc;
+ K3bMovixOptionsWidget* m_movixOptionsWidget;
+ K3bDataImageSettingsWidget* m_imageSettingsWidget;
+
+ QCheckBox* m_checkVerify;
+};
+
+#endif
+
diff --git a/src/projects/k3bmovixdvdview.cpp b/src/projects/k3bmovixdvdview.cpp
new file mode 100644
index 0000000..8173199
--- /dev/null
+++ b/src/projects/k3bmovixdvdview.cpp
@@ -0,0 +1,48 @@
+/*
+ *
+ * $Id: k3bmovixdvdview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bmovixdvdview.h"
+#include "k3bmovixdvddoc.h"
+#include "k3bmovixdvdburndialog.h"
+#include <k3bmovixlistview.h>
+#include <k3bfillstatusdisplay.h>
+
+#include <klocale.h>
+
+
+K3bMovixDvdView::K3bMovixDvdView( K3bMovixDvdDoc* doc, QWidget *parent, const char *name )
+ : K3bMovixView( doc, parent, name )
+{
+ m_doc = doc;
+
+ fillStatusDisplay()->showDvdSizes(true);
+
+ m_listView->setNoItemText( i18n("Use drag'n'drop to add files to the project.") +"\n"
+ + i18n("To remove or rename files use the context menu.") + "\n"
+ + i18n("After that press the burn button to write the DVD.") );
+}
+
+
+K3bMovixDvdView::~K3bMovixDvdView()
+{
+}
+
+
+K3bProjectBurnDialog* K3bMovixDvdView::newBurnDialog( QWidget* parent, const char* name )
+{
+ return new K3bMovixDvdBurnDialog( m_doc, parent, name, true );
+}
+
+#include "k3bmovixdvdview.moc"
diff --git a/src/projects/k3bmovixdvdview.h b/src/projects/k3bmovixdvdview.h
new file mode 100644
index 0000000..643b259
--- /dev/null
+++ b/src/projects/k3bmovixdvdview.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * $Id: k3bmovixdvdview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_MOVIX_DVD_VIEW_H_
+#define _K3B_MOVIX_DVD_VIEW_H_
+
+#include <k3bmovixview.h>
+
+class K3bMovixDvdDoc;
+
+
+class K3bMovixDvdView : public K3bMovixView
+{
+ Q_OBJECT
+
+ public:
+ K3bMovixDvdView( K3bMovixDvdDoc* doc, QWidget *parent = 0, const char *name = 0 );
+ ~K3bMovixDvdView();
+
+ protected:
+ K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ private:
+ K3bMovixDvdDoc* m_doc;
+};
+
+#endif
diff --git a/src/projects/k3bmovixlistview.cpp b/src/projects/k3bmovixlistview.cpp
new file mode 100644
index 0000000..9b943d3
--- /dev/null
+++ b/src/projects/k3bmovixlistview.cpp
@@ -0,0 +1,327 @@
+/*
+ *
+ * $Id: k3bmovixlistview.cpp 628165 2007-01-29 11:01:22Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bmovixlistview.h"
+#include "k3bmovixdoc.h"
+#include "k3bmovixfileitem.h"
+#include <k3bdiritem.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kio/global.h>
+#include <kurldrag.h>
+
+#include <qdragobject.h>
+#include <qptrlist.h>
+#include <qevent.h>
+#include <qheader.h>
+
+
+K3bMovixListViewItem::K3bMovixListViewItem( K3bMovixDoc* doc,
+ K3bMovixFileItem* item,
+ QListView* parent,
+ QListViewItem* after )
+ : K3bListViewItem( parent, after ),
+ m_doc(doc),
+ m_fileItem(item)
+{
+}
+
+
+K3bMovixListViewItem::K3bMovixListViewItem( K3bMovixDoc* doc,
+ K3bMovixFileItem* item,
+ QListViewItem* parent )
+ : K3bListViewItem( parent ),
+ m_doc(doc),
+ m_fileItem(item)
+{
+}
+
+
+K3bMovixListViewItem::~K3bMovixListViewItem()
+{
+}
+
+
+K3bMovixFileViewItem::K3bMovixFileViewItem( K3bMovixDoc* doc,
+ K3bMovixFileItem* item,
+ QListView* parent,
+ QListViewItem* after )
+ : K3bMovixListViewItem( doc, item, parent, after ),
+ KFileItem( 0, 0, KURL::fromPathOrURL(item->localPath()) )
+{
+ setPixmap( 1, KFileItem::pixmap( 16, KIcon::DefaultState ) );
+ setEditor( 1, LINE );
+}
+
+
+QString K3bMovixFileViewItem::text( int col ) const
+{
+ //
+ // We add two spaces after all strings (except the once renamable)
+ // to increase readability
+ //
+
+ switch( col ) {
+ case 0:
+ // allowing 999 files to be added.
+ return QString::number( doc()->indexOf( fileItem() ) ).rightJustify( 3, ' ' );
+ case 1:
+ return fileItem()->k3bName();
+ case 2:
+ {
+ if( fileItem()->isSymLink() )
+ return i18n("Link to %1").arg(const_cast<K3bMovixFileViewItem*>(this)->mimeComment()) + " ";
+ else
+ return const_cast<K3bMovixFileViewItem*>(this)->mimeComment() + " ";
+ }
+ case 3:
+ return KIO::convertSize( fileItem()->size() ) + " ";
+ case 4:
+ return fileItem()->localPath() + " ";
+ case 5:
+ return ( fileItem()->isValid() ? fileItem()->linkDest() : fileItem()->linkDest() + i18n(" (broken)") );
+ default:
+ return "";
+ }
+}
+
+
+void K3bMovixFileViewItem::setText( int col, const QString& text )
+{
+ if( col == 1 )
+ fileItem()->setK3bName( text );
+
+ K3bMovixListViewItem::setText( col, text );
+}
+
+
+QString K3bMovixFileViewItem::key( int, bool ) const
+{
+ return QString::number( doc()->indexOf( fileItem() ) ).rightJustify( 10, '0' );
+}
+
+
+
+
+K3bMovixSubTitleViewItem::K3bMovixSubTitleViewItem( K3bMovixDoc* doc,
+ K3bMovixFileItem* item,
+ K3bMovixListViewItem* parent )
+ : K3bMovixListViewItem( doc, item, parent ),
+ KFileItem( 0, 0, KURL::fromPathOrURL(item->subTitleItem()->localPath()) )
+{
+}
+
+
+K3bMovixSubTitleViewItem::~K3bMovixSubTitleViewItem()
+{
+}
+
+
+QString K3bMovixSubTitleViewItem::text( int c ) const
+{
+ switch( c ) {
+ case 1:
+ return fileItem()->subTitleItem()->k3bName();
+ case 2:
+ {
+ if( fileItem()->subTitleItem()->isSymLink() )
+ return i18n("Link to %1").arg(const_cast<K3bMovixSubTitleViewItem*>(this)->mimeComment());
+ else
+ return const_cast<K3bMovixSubTitleViewItem*>(this)->mimeComment();
+ }
+ case 3:
+ return KIO::convertSize( fileItem()->subTitleItem()->size() );
+ case 4:
+ return fileItem()->subTitleItem()->localPath();
+ case 5:
+ return ( fileItem()->subTitleItem()->isValid() ?
+ fileItem()->subTitleItem()->linkDest() :
+ fileItem()->subTitleItem()->linkDest() + i18n(" (broken)") );
+ default:
+ return "";
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+K3bMovixListView::K3bMovixListView( K3bMovixDoc* doc, QWidget* parent, const char* name )
+ : K3bListView( parent, name ),
+ m_doc(doc)
+{
+ addColumn( i18n("No.") );
+ addColumn( i18n("Name") );
+ addColumn( i18n("Type") );
+ addColumn( i18n("Size") );
+ addColumn( i18n("Local Path") );
+ addColumn( i18n("Link") );
+
+ setAcceptDrops( true );
+ setDropVisualizer( true );
+ setAllColumnsShowFocus( true );
+ setDragEnabled( true );
+ setItemsMovable( false );
+ setSelectionModeExt( KListView::Extended );
+ setSorting(0);
+
+ setNoItemText( i18n("Use drag'n'drop to add files to the project.") +"\n"
+ + i18n("To remove or rename files use the context menu.") + "\n"
+ + i18n("After that press the burn button to write the CD.") );
+
+ connect( m_doc, SIGNAL(changed()), this, SLOT(slotChanged()) );
+ connect( m_doc, SIGNAL(newMovixFileItems()), this, SLOT(slotNewFileItems()) );
+ connect( m_doc, SIGNAL(movixItemRemoved(K3bMovixFileItem*)), this, SLOT(slotFileItemRemoved(K3bMovixFileItem*)) );
+ connect( m_doc, SIGNAL(subTitleItemRemoved(K3bMovixFileItem*)), this, SLOT(slotSubTitleItemRemoved(K3bMovixFileItem*)) );
+ connect( this, SIGNAL(dropped(KListView*, QDropEvent*, QListViewItem*)),
+ this, SLOT(slotDropped(KListView*, QDropEvent*, QListViewItem*)) );
+
+ // let's see what the doc already has
+ slotNewFileItems();
+ slotChanged();
+}
+
+
+K3bMovixListView::~K3bMovixListView()
+{
+}
+
+
+bool K3bMovixListView::acceptDrag(QDropEvent* e) const
+{
+ // the first is for built-in item moving, the second for dropping urls
+ return ( K3bListView::acceptDrag(e) || KURLDrag::canDecode(e) );
+}
+
+
+void K3bMovixListView::slotNewFileItems()
+{
+ K3bMovixFileItem* lastItem = 0;
+ for( QPtrListIterator<K3bMovixFileItem> it( m_doc->movixFileItems() ); it.current(); ++it ) {
+ K3bMovixFileItem* item = it.current();
+ if( !m_itemMap.contains( item ) )
+ m_itemMap.insert( item, new K3bMovixFileViewItem( m_doc, item, this, lastItem ? m_itemMap[lastItem] : 0L ) );
+
+ if( item->subTitleItem() ) {
+ K3bMovixFileViewItem* vi = m_itemMap[item];
+ if( vi->childCount() <= 0 ) {
+ (void)new K3bMovixSubTitleViewItem( m_doc, item, vi );
+ vi->setOpen(true);
+ }
+ }
+
+ lastItem = item;
+ }
+
+ // arghhh
+ sort();
+}
+
+
+void K3bMovixListView::slotFileItemRemoved( K3bMovixFileItem* item )
+{
+ if( m_itemMap.contains( item ) ) {
+ K3bMovixFileViewItem* vi = m_itemMap[item];
+ m_itemMap.erase(item);
+ delete vi;
+ }
+}
+
+
+void K3bMovixListView::slotSubTitleItemRemoved( K3bMovixFileItem* item )
+{
+ if( m_itemMap.contains( item ) ) {
+ K3bMovixFileViewItem* vi = m_itemMap[item];
+ if( vi->childCount() >= 1 )
+ delete vi->firstChild();
+ }
+}
+
+
+void K3bMovixListView::slotDropped( KListView*, QDropEvent* e, QListViewItem* after )
+{
+ if( !e->isAccepted() )
+ return;
+
+ int pos;
+ if( after == 0L )
+ pos = 0;
+ else
+ pos = m_doc->indexOf( ((K3bMovixListViewItem*)after)->fileItem() );
+
+ if( e->source() == viewport() ) {
+ QPtrList<QListViewItem> sel = selectedItems();
+ QPtrListIterator<QListViewItem> it(sel);
+ K3bMovixFileItem* itemAfter = ( after ? ((K3bMovixListViewItem*)after)->fileItem() : 0 );
+ while( it.current() ) {
+ K3bMovixListViewItem* vi = (K3bMovixListViewItem*)it.current();
+ if( vi->isMovixFileItem() ) {
+ K3bMovixFileItem* item = vi->fileItem();
+ m_doc->moveMovixItem( item, itemAfter );
+ itemAfter = item;
+ }
+ else
+ kdDebug() << "(K3bMovixListView) I don't move subtitle items!" << endl;
+
+ ++it;
+ }
+
+ sort(); // This is so lame!
+ }
+ else {
+ KURL::List urls;
+ KURLDrag::decode( e, urls );
+
+ for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it ) {
+ m_doc->addMovixFile( *it, pos++ );
+ }
+ }
+
+ // now grab that focus
+ setFocus();
+}
+
+
+QDragObject* K3bMovixListView::dragObject()
+{
+ QPtrList<QListViewItem> list = selectedItems();
+
+ if( list.isEmpty() )
+ return 0;
+
+ QPtrListIterator<QListViewItem> it(list);
+ KURL::List urls;
+
+ for( ; it.current(); ++it )
+ urls.append( KURL( ((K3bMovixListViewItem*)it.current())->fileItem()->localPath() ) );
+
+ return KURLDrag::newDrag( urls, viewport() );
+}
+
+
+void K3bMovixListView::slotChanged()
+{
+ header()->setShown( m_doc->root()->numFiles() > 0 );
+}
+
+#include "k3bmovixlistview.moc"
diff --git a/src/projects/k3bmovixlistview.h b/src/projects/k3bmovixlistview.h
new file mode 100644
index 0000000..7426ddb
--- /dev/null
+++ b/src/projects/k3bmovixlistview.h
@@ -0,0 +1,100 @@
+/*
+ *
+ * $Id: k3bmovixlistview.h 628165 2007-01-29 11:01:22Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef _K3B_MOVIX_LISTVIEW_H_
+#define _K3B_MOVIX_LISTVIEW_H_
+
+#include <k3blistview.h>
+#include <kfileitem.h>
+
+#include <qmap.h>
+
+
+class K3bMovixDoc;
+class K3bMovixFileItem;
+class K3bFileItem;
+
+
+class K3bMovixListViewItem : public K3bListViewItem
+{
+ public:
+ K3bMovixListViewItem( K3bMovixDoc* doc, K3bMovixFileItem*, QListView* parent, QListViewItem* after );
+ K3bMovixListViewItem( K3bMovixDoc* doc, K3bMovixFileItem*, QListViewItem* parent );
+ ~K3bMovixListViewItem();
+
+ K3bMovixFileItem* fileItem() const { return m_fileItem; }
+ K3bMovixDoc* doc() const { return m_doc; }
+
+ virtual bool isMovixFileItem() const { return true; }
+
+ private:
+ K3bMovixDoc* m_doc;
+ K3bMovixFileItem* m_fileItem;
+};
+
+
+class K3bMovixFileViewItem : public K3bMovixListViewItem, public KFileItem
+{
+ public:
+ K3bMovixFileViewItem( K3bMovixDoc* doc, K3bMovixFileItem*, QListView* parent, QListViewItem* );
+
+ QString text( int ) const;
+ void setText(int col, const QString& text );
+
+ /** always sort according to the playlist order */
+ QString key( int, bool ) const;
+};
+
+class K3bMovixSubTitleViewItem : public K3bMovixListViewItem, public KFileItem
+{
+ public:
+ K3bMovixSubTitleViewItem( K3bMovixDoc*, K3bMovixFileItem* item, K3bMovixListViewItem* parent );
+ ~K3bMovixSubTitleViewItem();
+
+ QString text( int ) const;
+
+ bool isMovixFileItem() const { return false; }
+};
+
+
+class K3bMovixListView : public K3bListView
+{
+ Q_OBJECT
+
+ public:
+ K3bMovixListView( K3bMovixDoc* doc, QWidget* parent = 0, const char* name = 0 );
+ ~K3bMovixListView();
+
+ QDragObject* dragObject();
+
+ protected:
+ bool acceptDrag(QDropEvent* e) const;
+
+ private slots:
+ void slotNewFileItems();
+ void slotFileItemRemoved( K3bMovixFileItem* );
+ void slotSubTitleItemRemoved( K3bMovixFileItem* );
+ void slotDropped( KListView*, QDropEvent* e, QListViewItem* after );
+ void slotChanged();
+
+ private:
+ K3bMovixDoc* m_doc;
+
+ QMap<K3bFileItem*, K3bMovixFileViewItem*> m_itemMap;
+};
+
+#endif
diff --git a/src/projects/k3bmovixoptionswidget.cpp b/src/projects/k3bmovixoptionswidget.cpp
new file mode 100644
index 0000000..131af6b
--- /dev/null
+++ b/src/projects/k3bmovixoptionswidget.cpp
@@ -0,0 +1,243 @@
+/*
+ *
+ * $Id: k3bmovixoptionswidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bmovixoptionswidget.h"
+#include "k3bmovixdoc.h"
+#include "k3bmovixprogram.h"
+
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qlabel.h>
+
+
+class K3bMovixOptionsWidget::LanguageSelectionHelper
+{
+public:
+ LanguageSelectionHelper( QComboBox* box )
+ : m_box(box) {
+ }
+
+ void insertLanguages( const QStringList& langs ) {
+ m_box->clear();
+ m_langMap.clear();
+
+ for( QStringList::const_iterator it = langs.begin(); it != langs.end(); ++it ) {
+ if( *it == i18n("default") )
+ m_box->insertItem( *it );
+ else {
+ QString lang = KGlobal::locale()->twoAlphaToLanguageName( *it );
+ if( lang.isEmpty() )
+ lang = *it;
+
+ m_langMap[m_box->count()] = *it;
+ m_indexMap[*it] = m_box->count();
+ m_box->insertItem( lang );
+ }
+ }
+ }
+
+ QString selectedLanguage() const {
+ if( m_box->currentItem() == 0 )
+ return i18n("default");
+ else
+ return m_langMap[m_box->currentItem()];
+ }
+
+ void setLanguage( const QString& l ) {
+ QMap<QString,int>::const_iterator it = m_indexMap.find(l);
+ if( it == m_indexMap.end() )
+ m_box->setCurrentItem( 0 );
+ else
+ m_box->setCurrentItem( it.data() );
+ }
+
+private:
+ QComboBox* m_box;
+ QMap<int,QString> m_langMap;
+ QMap<QString,int> m_indexMap;
+};
+
+
+K3bMovixOptionsWidget::K3bMovixOptionsWidget( QWidget* parent, const char* name )
+ : base_K3bMovixOptionsWidget( parent, name )
+{
+ m_keyboardLangHelper = new LanguageSelectionHelper( m_comboKeyboardLayout );
+ m_helpLangHelper = new LanguageSelectionHelper( m_comboBootMessageLanguage );
+}
+
+
+K3bMovixOptionsWidget::~K3bMovixOptionsWidget()
+{
+ delete m_keyboardLangHelper;
+ delete m_helpLangHelper;
+}
+
+
+void K3bMovixOptionsWidget::init( const K3bMovixBin* bin )
+{
+ m_labelAudioBackground->setShown( bin->hasFeature( "newfiles" ) );
+ m_comboAudioBackground->setShown( bin->hasFeature( "newfiles" ) );
+ m_labelKeyboardLayout->setShown( bin->hasFeature( "newfiles" ) );
+ m_comboKeyboardLayout->setShown( bin->hasFeature( "newfiles" ) );
+
+ m_comboSubtitleFontset->insertStringList( bin->supportedSubtitleFonts() );
+ m_helpLangHelper->insertLanguages( bin->supportedLanguages() );
+ m_comboDefaultBootLabel->insertStringList( bin->supportedBootLabels() );
+ m_keyboardLangHelper->insertLanguages( bin->supportedKbdLayouts() );
+ m_comboAudioBackground->insertStringList( bin->supportedBackgrounds() );
+}
+
+
+void K3bMovixOptionsWidget::readSettings( K3bMovixDoc* doc )
+{
+ m_comboSubtitleFontset->setCurrentItem( doc->subtitleFontset(), false );
+ m_spinLoop->setValue( doc->loopPlaylist() );
+ m_editAdditionalMplayerOptions->setText( doc->additionalMPlayerOptions() );
+ m_editUnwantedMplayerOptions->setText( doc->unwantedMPlayerOptions() );
+ m_helpLangHelper->setLanguage( doc->bootMessageLanguage() );
+ m_comboDefaultBootLabel->setCurrentItem( doc->defaultBootLabel(), false );
+ m_comboAudioBackground->setCurrentItem( doc->audioBackground(), false );
+ m_keyboardLangHelper->setLanguage( doc->keyboardLayout() );
+ m_checkShutdown->setChecked( doc->shutdown() );
+ m_checkReboot->setChecked( doc->reboot() );
+ m_checkEject->setChecked( doc->ejectDisk() );
+ m_checkRandomPlay->setChecked( doc->randomPlay() );
+ m_checkNoDma->setChecked( doc->noDma() );
+}
+
+
+void K3bMovixOptionsWidget::saveSettings( K3bMovixDoc* doc )
+{
+ doc->setShutdown( m_checkShutdown->isChecked() );
+ doc->setReboot( m_checkReboot->isChecked() );
+ doc->setEjectDisk( m_checkEject->isChecked() );
+ doc->setSubtitleFontset( m_comboSubtitleFontset->currentText() );
+ doc->setBootMessageLanguage( m_helpLangHelper->selectedLanguage() );
+ doc->setDefaultBootLabel( m_comboDefaultBootLabel->currentText() );
+ doc->setKeyboardLayout( m_keyboardLangHelper->selectedLanguage() );
+ doc->setAudioBackground( m_comboAudioBackground->currentText() );
+ doc->setAdditionalMPlayerOptions( m_editAdditionalMplayerOptions->text() );
+ doc->setUnwantedMPlayerOptions( m_editUnwantedMplayerOptions->text() );
+ doc->setLoopPlaylist( m_spinLoop->value() );
+ doc->setRandomPlay( m_checkRandomPlay->isChecked() );
+ doc->setNoDma( m_checkNoDma->isChecked() );
+}
+
+
+void K3bMovixOptionsWidget::loadDefaults()
+{
+ m_comboSubtitleFontset->setCurrentItem( 0 ); // default
+ m_comboAudioBackground->setCurrentItem( 0 ); // default
+ m_comboKeyboardLayout->setCurrentItem( 0 ); // default
+ m_spinLoop->setValue( 1 );
+ m_editAdditionalMplayerOptions->setText( QString::null );
+ m_editUnwantedMplayerOptions->setText( QString::null );
+ m_comboBootMessageLanguage->setCurrentItem( 0 ); // default
+ m_comboDefaultBootLabel->setCurrentItem( 0 ); // default
+ m_checkShutdown->setChecked( false );
+ m_checkReboot->setChecked( false );
+ m_checkEject->setChecked( false );
+ m_checkRandomPlay->setChecked( false );
+ m_checkNoDma->setChecked( false );
+}
+
+
+void K3bMovixOptionsWidget::loadConfig( KConfigBase* c )
+{
+ QString s = c->readEntry("subtitle_fontset");
+ if( !s.isEmpty() && s != "none" && m_comboSubtitleFontset->contains(s) )
+ m_comboSubtitleFontset->setCurrentItem( s, false );
+ else
+ m_comboSubtitleFontset->setCurrentItem( 0 ); // none
+
+ m_spinLoop->setValue( c->readNumEntry("loop", 1 ) );
+ m_editAdditionalMplayerOptions->setText( c->readEntry( "additional_mplayer_options" ) );
+ m_editUnwantedMplayerOptions->setText( c->readEntry( "unwanted_mplayer_options" ) );
+
+ s = c->readEntry("boot_message_language");
+ m_helpLangHelper->setLanguage( s == "default" ? QString::null : s );
+
+ s = c->readEntry( "default_boot_label" );
+ if( !s.isEmpty() && s != "default" && m_comboDefaultBootLabel->contains(s) )
+ m_comboDefaultBootLabel->setCurrentItem( s, false );
+ else
+ m_comboDefaultBootLabel->setCurrentItem( 0 ); // default
+
+ s = c->readEntry("audio_background");
+ if( !s.isEmpty() && s != "default" && m_comboAudioBackground->contains(s) )
+ m_comboAudioBackground->setCurrentItem( s, false );
+ else
+ m_comboAudioBackground->setCurrentItem( 0 ); // default
+
+ s = c->readEntry("keyboard_layout");
+ m_keyboardLangHelper->setLanguage( s == "default" ? QString::null : s );
+
+ m_checkShutdown->setChecked( c->readBoolEntry( "shutdown", false) );
+ m_checkReboot->setChecked( c->readBoolEntry( "reboot", false ) );
+ m_checkEject->setChecked( c->readBoolEntry( "eject", false ) );
+ m_checkRandomPlay->setChecked( c->readBoolEntry( "random_play", false ) );
+ m_checkNoDma->setChecked( c->readBoolEntry( "no_dma", false ) );
+}
+
+
+void K3bMovixOptionsWidget::saveConfig( KConfigBase* c )
+{
+ if( m_comboSubtitleFontset->currentItem() == 0 )
+ c->writeEntry( "subtitle_fontset", "none" );
+ else
+ c->writeEntry( "subtitle_fontset", m_comboSubtitleFontset->currentText() );
+
+ c->writeEntry( "loop", m_spinLoop->value() );
+ c->writeEntry( "additional_mplayer_options", m_editAdditionalMplayerOptions->text() );
+ c->writeEntry( "unwanted_mplayer_options", m_editUnwantedMplayerOptions->text() );
+
+ if( m_comboBootMessageLanguage->currentItem() == 0 )
+ c->writeEntry( "boot_message_language", "default" );
+ else
+ c->writeEntry( "boot_message_language", m_helpLangHelper->selectedLanguage() );
+
+ if( m_comboDefaultBootLabel->currentItem() == 0 )
+ c->writeEntry( "default_boot_label", "default" );
+ else
+ c->writeEntry( "default_boot_label", m_comboDefaultBootLabel->currentText() );
+
+ if( m_comboAudioBackground->currentItem() == 0 )
+ c->writeEntry( "audio_background", "default" );
+ else
+ c->writeEntry( "audio_background", m_comboAudioBackground->currentText() );
+
+ if( m_comboKeyboardLayout->currentItem() == 0 )
+ c->writeEntry( "keyboard_layout", "default" );
+ else
+ c->writeEntry( "keyboard_layout", m_keyboardLangHelper->selectedLanguage() );
+
+ c->writeEntry( "shutdown", m_checkShutdown->isChecked() );
+ c->writeEntry( "reboot", m_checkReboot->isChecked() );
+ c->writeEntry( "eject", m_checkEject->isChecked() );
+ c->writeEntry( "random_play", m_checkRandomPlay->isChecked() );
+ c->writeEntry( "no_dma", m_checkNoDma->isChecked() );
+}
+
+#include "k3bmovixoptionswidget.moc"
+
diff --git a/src/projects/k3bmovixoptionswidget.h b/src/projects/k3bmovixoptionswidget.h
new file mode 100644
index 0000000..3b9e367
--- /dev/null
+++ b/src/projects/k3bmovixoptionswidget.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * $Id: k3bmovixoptionswidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_MOVIX_OPTIONSWIDGET_H_
+#define _K3B_MOVIX_OPTIONSWIDGET_H_
+
+#include "base_k3bmovixoptionswidget.h"
+
+class K3bMovixDoc;
+class K3bMovixBin;
+class KConfigBase;
+
+
+class K3bMovixOptionsWidget : public base_K3bMovixOptionsWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bMovixOptionsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bMovixOptionsWidget();
+
+ public slots:
+ void init( const K3bMovixBin* );
+ void readSettings( K3bMovixDoc* );
+ void saveSettings( K3bMovixDoc* );
+ void loadConfig( KConfigBase* c );
+ void saveConfig( KConfigBase* c );
+ void loadDefaults();
+
+ private:
+ class LanguageSelectionHelper;
+ LanguageSelectionHelper* m_keyboardLangHelper;
+ LanguageSelectionHelper* m_helpLangHelper;
+};
+
+
+#endif
diff --git a/src/projects/k3bmovixview.cpp b/src/projects/k3bmovixview.cpp
new file mode 100644
index 0000000..825b10b
--- /dev/null
+++ b/src/projects/k3bmovixview.cpp
@@ -0,0 +1,192 @@
+/*
+ *
+ * $Id: k3bmovixview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bmovixview.h"
+#include "k3bmovixdoc.h"
+#include "k3bmovixlistview.h"
+#include "k3bmovixburndialog.h"
+#include "k3bmovixfileitem.h"
+
+#include <k3bfillstatusdisplay.h>
+#include <k3bdatapropertiesdialog.h>
+#include <k3bprojectplugin.h>
+#include <k3btoolbox.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+
+
+K3bMovixView::K3bMovixView( K3bMovixDoc* doc, QWidget* parent, const char* name )
+ : K3bView( doc, parent, name ),
+ m_doc(doc)
+{
+ m_listView = new K3bMovixListView( m_doc, this );
+ setMainWidget( m_listView );
+
+ connect( m_listView, SIGNAL(contextMenuRequested( QListViewItem*, const QPoint& , int )),
+ this, SLOT(slotContextMenuRequested(QListViewItem*, const QPoint& , int )) );
+
+
+ // setup actions
+ m_actionProperties = new KAction( i18n("Properties"), "misc",
+ 0, this, SLOT(showPropertiesDialog()),
+ actionCollection(), "movix_show_props" );
+ m_actionRemove = new KAction( i18n( "Remove" ), "editdelete",
+ Key_Delete, this, SLOT(slotRemoveItems()),
+ actionCollection(), "movix_remove_item" );
+ m_actionRemoveSubTitle = new KAction( i18n( "Remove Subtitle File" ), "editdelete",
+ 0, this, SLOT(slotRemoveSubTitleItems()),
+ actionCollection(), "movix_remove_subtitle_item" );
+ m_actionAddSubTitle = new KAction( i18n("Add Subtitle File..."), "",
+ 0, this, SLOT(slotAddSubTitleFile()),
+ actionCollection(), "movix_add_subtitle" );
+
+ m_popupMenu = new KPopupMenu( this );
+ m_actionRemove->plug( m_popupMenu );
+ m_actionRemoveSubTitle->plug( m_popupMenu );
+ m_actionAddSubTitle->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ m_actionProperties->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ // k3bMain()->actionCollection()->action("file_burn")->plug( m_popupMenu );
+
+
+ addPluginButtons( K3bProjectPlugin::MOVIX_CD );
+
+ toolBox()->addStretch();
+
+ m_volumeIDEdit = new QLineEdit( doc->isoOptions().volumeID(), toolBox() );
+ toolBox()->addLabel( i18n("Volume Name:") );
+ toolBox()->addSpacing();
+ toolBox()->addWidget( m_volumeIDEdit );
+ connect( m_volumeIDEdit, SIGNAL(textChanged(const QString&)),
+ m_doc,
+ SLOT(setVolumeID(const QString&)) );
+
+ connect( m_doc, SIGNAL(changed()), this, SLOT(slotDocChanged()) );
+}
+
+
+K3bMovixView::~K3bMovixView()
+{
+}
+
+
+void K3bMovixView::slotContextMenuRequested(QListViewItem* item, const QPoint& p, int )
+{
+ if( item ) {
+ m_actionRemove->setEnabled(true);
+ m_actionRemoveSubTitle->setEnabled( true );
+ }
+ else {
+ m_actionRemove->setEnabled(false);
+ m_actionRemoveSubTitle->setEnabled( false );
+ }
+
+ m_popupMenu->popup( p );
+}
+
+
+void K3bMovixView::showPropertiesDialog()
+{
+ K3bFileItem* dataItem = 0;
+
+ // get selected item
+ if( K3bMovixListViewItem* viewItem = dynamic_cast<K3bMovixListViewItem*>( m_listView->selectedItems().first() ) ) {
+ dataItem = viewItem->fileItem();
+ }
+
+ if( dataItem ) {
+ K3bDataPropertiesDialog d( dataItem, this );
+ d.exec();
+ }
+ else
+ slotProperties();
+}
+
+
+void K3bMovixView::slotRemoveItems()
+{
+ QPtrList<QListViewItem> list = m_listView->selectedItems();
+ QPtrListIterator<QListViewItem> it(list);
+
+ if( list.isEmpty() )
+ kdDebug() << "nothing to remove" << endl;
+
+ for( ; it.current(); ++it ) {
+ K3bMovixListViewItem* vi = static_cast<K3bMovixListViewItem*>(*it);
+ if( vi->isMovixFileItem() )
+ m_doc->removeItem( vi->fileItem() );
+ else
+ m_doc->removeSubTitleItem( ((K3bMovixSubTitleViewItem*)*it)->fileItem() );
+ }
+}
+
+
+void K3bMovixView::slotRemoveSubTitleItems()
+{
+ QPtrList<QListViewItem> list = m_listView->selectedItems();
+ QPtrListIterator<QListViewItem> it(list);
+
+ if( list.isEmpty() )
+ kdDebug() << "nothing to remove" << endl;
+
+ for( ; it.current(); ++it ) {
+ K3bMovixListViewItem* vi = static_cast<K3bMovixListViewItem*>(*it);
+ m_doc->removeSubTitleItem( vi->fileItem() );
+ }
+}
+
+
+void K3bMovixView::slotAddSubTitleFile()
+{
+ QListViewItem* item = m_listView->selectedItems().first();
+ if( K3bMovixListViewItem* vi = dynamic_cast<K3bMovixListViewItem*>(item) ) {
+
+ KURL url = KFileDialog::getOpenURL();
+ if( url.isValid() ) {
+ if( url.isLocalFile() )
+ m_doc->addSubTitleItem( vi->fileItem(), url );
+ else
+ KMessageBox::error( 0, i18n("K3b currently only supports local files.") );
+ }
+ }
+}
+
+
+K3bProjectBurnDialog* K3bMovixView::newBurnDialog( QWidget* parent, const char* name )
+{
+ return new K3bMovixBurnDialog( m_doc, parent, name, true );
+}
+
+
+void K3bMovixView::slotDocChanged()
+{
+ // do not update the editor in case it changed the volume id itself
+ if( m_doc->isoOptions().volumeID() != m_volumeIDEdit->text() )
+ m_volumeIDEdit->setText( m_doc->isoOptions().volumeID() );
+}
+
+#include "k3bmovixview.moc"
diff --git a/src/projects/k3bmovixview.h b/src/projects/k3bmovixview.h
new file mode 100644
index 0000000..e174b64
--- /dev/null
+++ b/src/projects/k3bmovixview.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * $Id: k3bmovixview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+
+#ifndef _K3B_MOVIX_VIEW_H_
+#define _K3B_MOVIX_VIEW_H_
+
+#include <k3bview.h>
+
+class K3bMovixDoc;
+class K3bMovixListView;
+class KAction;
+class KPopupMenu;
+class QListViewItem;
+class QPoint;
+class QLineEdit;
+
+
+class K3bMovixView : public K3bView
+{
+ Q_OBJECT
+
+ public:
+ K3bMovixView( K3bMovixDoc* doc, QWidget* parent = 0, const char* name = 0 );
+ virtual ~K3bMovixView();
+
+ private slots:
+ void slotContextMenuRequested(QListViewItem*, const QPoint& , int );
+ void slotRemoveItems();
+ void slotRemoveSubTitleItems();
+ void showPropertiesDialog();
+ void slotAddSubTitleFile();
+ void slotDocChanged();
+
+ protected:
+ virtual K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ K3bMovixListView* m_listView;
+
+ private:
+ K3bMovixDoc* m_doc;
+
+ KAction* m_actionProperties;
+ KAction* m_actionRemove;
+ KAction* m_actionRemoveSubTitle;
+ KAction* m_actionAddSubTitle;
+ KPopupMenu* m_popupMenu;
+
+ QLineEdit* m_volumeIDEdit;
+};
+
+#endif
diff --git a/src/projects/k3bmusicbrainzjob.cpp b/src/projects/k3bmusicbrainzjob.cpp
new file mode 100644
index 0000000..b52c766
--- /dev/null
+++ b/src/projects/k3bmusicbrainzjob.cpp
@@ -0,0 +1,287 @@
+/*
+ *
+ * $Id: k3bmusicbrainzjob.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_MUSICBRAINZ
+
+#include "k3bmusicbrainzjob.h"
+#include "k3btrm.h"
+#include "k3bmusicbrainz.h"
+
+#include <k3bthread.h>
+#include <k3bthreadjob.h>
+#include <k3baudiotrack.h>
+#include <k3baudiodatasource.h>
+#include <k3bsimplejobhandler.h>
+
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+
+
+// determine one trm
+class K3bMusicBrainzJob::TRMThread : public K3bThread
+{
+public:
+ TRMThread();
+
+ void init() {
+ m_canceled = false;
+ }
+ void run();
+ void cancel();
+ const QCString& signature() const {
+ return m_trm.signature();
+ }
+
+ K3bAudioTrack* track;
+
+private:
+ bool m_canceled;
+ K3bTRM m_trm;
+};
+
+
+class K3bMusicBrainzJob::MusicBrainzThread : public K3bThread
+{
+public:
+ MusicBrainzThread() {
+ }
+
+ void run();
+
+ void setSignature( const QCString& sig ) {
+ m_sig = sig;
+ }
+
+ unsigned int results() {
+ return m_results;
+ }
+
+ const QString& title( unsigned int i = 0 ) const {
+ return m_mb.title( i );
+ }
+
+ const QString& artist( unsigned int i = 0 ) const {
+ return m_mb.artist( i );
+ }
+
+private:
+ K3bMusicBrainz m_mb;
+ int m_results;
+ QCString m_sig;
+};
+
+
+K3bMusicBrainzJob::TRMThread::TRMThread()
+ : m_canceled(false)
+{
+}
+
+
+void K3bMusicBrainzJob::TRMThread::run()
+{
+ emitStarted();
+
+ track->seek(0);
+ m_trm.start( track->length() );
+
+ char buffer[2352*10];
+ int len = 0;
+ long long dataRead = 0;
+ while( !m_canceled &&
+ (len = track->read( buffer, 2352*10 )) > 0 ) {
+
+ dataRead += len;
+
+ // swap data
+ char buf;
+ for( int i = 0; i < len-1; i+=2 ) {
+ buf = buffer[i];
+ buffer[i] = buffer[i+1];
+ buffer[i+1] = buf;
+ }
+
+ if( m_trm.generate( buffer, len ) ) {
+ len = 0;
+ break;
+ }
+
+ // FIXME: useless since libmusicbrainz does never need all the data
+ emitPercent( 100*dataRead/track->length().audioBytes() );
+ }
+
+ if( m_canceled ) {
+ emitCanceled();
+ emitFinished( false );
+ }
+ else if( len == 0 ) {
+ emitFinished( m_trm.finalize() );
+ }
+ else
+ emitFinished( false );
+}
+
+
+void K3bMusicBrainzJob::TRMThread::cancel()
+{
+ m_canceled = true;
+}
+
+
+void K3bMusicBrainzJob::MusicBrainzThread::run()
+{
+ emitStarted();
+ m_results = m_mb.query( m_sig );
+ emitFinished( m_results > 0 );
+}
+
+
+
+
+// cannot use this as parent for the K3bSimpleJobHandler since this has not been constructed yet
+K3bMusicBrainzJob::K3bMusicBrainzJob( QWidget* parent, const char* name )
+ : K3bJob( new K3bSimpleJobHandler( 0 ), parent, name ),
+ m_canceled( false )
+{
+ m_trmThread = new TRMThread();
+ m_mbThread = new MusicBrainzThread();
+ m_trmJob = new K3bThreadJob( m_trmThread, this, this );
+ m_mbJob = new K3bThreadJob( m_mbThread, this, this );
+
+ connect( m_trmJob, SIGNAL(percent(int)), this, SIGNAL(subPercent(int)) );
+ connect( m_trmJob, SIGNAL(percent(int)), this, SLOT(slotTrmPercent(int)) );
+ connect( m_trmJob, SIGNAL(finished(bool)), this, SLOT(slotTrmJobFinished(bool)) );
+ connect( m_mbJob, SIGNAL(finished(bool)), this, SLOT(slotMbJobFinished(bool)) );
+}
+
+
+K3bMusicBrainzJob::~K3bMusicBrainzJob()
+{
+ delete m_trmThread;
+ delete m_trmJob;
+ delete m_mbThread;
+ delete m_mbJob;
+ delete jobHandler();
+}
+
+
+void K3bMusicBrainzJob::start()
+{
+ jobStarted();
+
+ m_canceled = false;
+
+ m_trmThread->track = m_tracks.first();
+
+ emit infoMessage( i18n("Generating fingerprint for track %1.")
+ .arg(m_tracks.current()->trackNumber()), INFO );
+
+ m_trmJob->start();
+}
+
+
+void K3bMusicBrainzJob::cancel()
+{
+ m_canceled = true;
+ m_trmJob->cancel();
+ m_mbJob->cancel();
+}
+
+
+void K3bMusicBrainzJob::slotTrmPercent( int p )
+{
+ // the easy way (inaccurate)
+ emit percent( (100*m_tracks.at() + p) / m_tracks.count() );
+}
+
+
+void K3bMusicBrainzJob::slotTrmJobFinished( bool success )
+{
+ if( success ) {
+ // now query musicbrainz
+ m_mbThread->setSignature( m_trmThread->signature() );
+ emit infoMessage( i18n("Querying MusicBrainz for track %1.")
+ .arg(m_tracks.current()->trackNumber()), INFO );
+ m_mbJob->start();
+ }
+ else {
+ if( hasBeenCanceled() )
+ emit canceled();
+ jobFinished(false);
+ }
+}
+
+
+void K3bMusicBrainzJob::slotMbJobFinished( bool success )
+{
+ if( hasBeenCanceled() ) {
+ emit canceled();
+ jobFinished(false);
+ }
+ else {
+ emit trackFinished( m_tracks.current(), success );
+
+ if( success ) {
+ // found entries
+ QStringList resultStrings, resultStringsUnique;
+ for( unsigned int i = 0; i < m_mbThread->results(); ++i )
+ resultStrings.append( m_mbThread->artist(i) + " - " + m_mbThread->title(i) );
+
+ // since we are only using the title and the artist a lot of entries are alike to us
+ // so to not let the user have to choose between two equal entries we trim the list down
+ for( QStringList::const_iterator it = resultStrings.begin();
+ it != resultStrings.end(); ++it )
+ if( resultStringsUnique.find( *it ) == resultStringsUnique.end() )
+ resultStringsUnique.append( *it );
+
+ QString s;
+ bool ok = true;
+ if( resultStringsUnique.count() > 1 )
+ s = KInputDialog::getItem( i18n("MusicBrainz Query"),
+ i18n("Found multiple matches for track %1 (%2). Please select one.")
+ .arg(m_tracks.current()->trackNumber())
+ .arg(m_tracks.current()->firstSource()->sourceComment()),
+ resultStringsUnique,
+ 0,
+ false,
+ &ok,
+ dynamic_cast<QWidget*>(parent()) );
+ else
+ s = resultStringsUnique.first();
+
+ if( ok ) {
+ int i = resultStrings.findIndex( s );
+ m_tracks.current()->setTitle( m_mbThread->title(i) );
+ m_tracks.current()->setArtist( m_mbThread->artist(i) );
+ }
+ }
+
+ // query next track
+ if( m_tracks.next() ) {
+ emit infoMessage( i18n("Generating fingerprint for track %1.")
+ .arg(m_tracks.current()->trackNumber()), INFO );
+ m_trmThread->track = m_tracks.current();
+ m_trmJob->start();
+ }
+ else
+ jobFinished( true );
+ }
+}
+
+#include "k3bmusicbrainzjob.moc"
+
+#endif
diff --git a/src/projects/k3bmusicbrainzjob.h b/src/projects/k3bmusicbrainzjob.h
new file mode 100644
index 0000000..5007a47
--- /dev/null
+++ b/src/projects/k3bmusicbrainzjob.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * $Id: k3bmusicbrainzjob.h 630384 2007-02-05 09:33:17Z mlaurent $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_MUSICBRAINZ_JOB_H_
+#define _K3B_MUSICBRAINZ_JOB_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_MUSICBRAINZ
+
+#include <k3bjob.h>
+
+
+class K3bAudioTrack;
+class K3bThreadJob;
+class QWidget;
+
+
+/**
+ * This job tries to determine K3bAudioTrack's title and artist using
+ * Musicbrainz.
+ */
+class K3bMusicBrainzJob : public K3bJob
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * \param parent since we do not use this job with a normal progressdialog we need a widget
+ * as parent
+ */
+ K3bMusicBrainzJob( QWidget* parent = 0, const char* name = 0 );
+ ~K3bMusicBrainzJob();
+
+ bool hasBeenCanceled() const { return m_canceled; }
+
+ signals:
+ /**
+ * Emitted for each track. This is signal can be used
+ * to display further information.
+ *
+ * \param track The track for which metadata was searched.
+ * \param success True if metadata was found
+ */
+ void trackFinished( K3bAudioTrack* track, bool success );
+
+ public slots:
+ void start();
+ void cancel();
+
+ void setTracks( const QPtrList<K3bAudioTrack>& tracks ) { m_tracks = tracks; }
+
+ private slots:
+ void slotTrmPercent( int p );
+ void slotTrmJobFinished( bool success );
+ void slotMbJobFinished( bool success );
+
+ private:
+ class TRMThread;
+ class MusicBrainzThread;
+ TRMThread* m_trmThread;
+ MusicBrainzThread* m_mbThread;
+
+ K3bThreadJob* m_trmJob;
+ K3bThreadJob* m_mbJob;
+
+ QPtrList<K3bAudioTrack> m_tracks;
+
+ bool m_canceled;
+};
+
+
+#endif
+
+#endif
diff --git a/src/projects/k3bprojectburndialog.cpp b/src/projects/k3bprojectburndialog.cpp
new file mode 100644
index 0000000..09444b0
--- /dev/null
+++ b/src/projects/k3bprojectburndialog.cpp
@@ -0,0 +1,413 @@
+/*
+ *
+ * $Id: k3bprojectburndialog.cpp 630454 2007-02-05 13:06:45Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bprojectburndialog.h"
+#include "k3bdoc.h"
+#include "k3bburnprogressdialog.h"
+#include "k3bjob.h"
+#include "k3btempdirselectionwidget.h"
+#include "k3bwriterselectionwidget.h"
+#include "k3bstdguiitems.h"
+#include "k3bwritingmodewidget.h"
+#include <k3bdevice.h>
+#include <k3bdevicemanager.h>
+#include <k3bglobals.h>
+#include <k3bcore.h>
+
+#include <qstring.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qlayout.h>
+#include <qvbox.h>
+#include <qcheckbox.h>
+#include <qtabwidget.h>
+#include <qgroupbox.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kguiitem.h>
+#include <kstdguiitem.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+
+
+K3bProjectBurnDialog::K3bProjectBurnDialog( K3bDoc* doc, QWidget *parent, const char *name, bool modal, bool dvd )
+ : K3bInteractionDialog( parent, name, i18n("Project"), QString::null,
+ START_BUTTON|SAVE_BUTTON|CANCEL_BUTTON, START_BUTTON,
+ "default " + doc->typeString() + " settings", modal ),
+ m_writerSelectionWidget(0),
+ m_tempDirSelectionWidget(0),
+ m_dvd(dvd)
+{
+ m_doc = doc;
+
+ /**
+ * There is at least one scenario in which this is useful: change the volume id (or rename a file)
+ * without explicit confirmation (by pressing enter for example). Then click the "burn" button.
+ * The "focus out" event which results in a rename in the listviewitem will be processed after the
+ * initialization of the burn dialog. Thus, the burn dialog will read the old volume id.
+ */
+ setDelayedInitialization( true );
+
+ setButtonGui( SAVE_BUTTON,
+ KStdGuiItem::close() );
+ setButtonText( SAVE_BUTTON,
+ i18n("Close"),
+ i18n("Save Settings and close"),
+ i18n("Saves the settings to the project and closes the dialog.") );
+ setButtonGui( CANCEL_BUTTON, KStdGuiItem::cancel() );
+ setButtonText( CANCEL_BUTTON,
+ i18n("Cancel"),
+ i18n("Discard all changes and close"),
+ i18n("Discards all changes made in the dialog and closes it.") );
+
+ m_job = 0;
+}
+
+
+K3bProjectBurnDialog::~K3bProjectBurnDialog(){
+}
+
+
+void K3bProjectBurnDialog::init()
+{
+ readSettings();
+// if( !m_writerSelectionWidget->writerDevice() )
+// m_checkOnlyCreateImage->setChecked(true);
+}
+
+
+void K3bProjectBurnDialog::slotWriterChanged()
+{
+ slotToggleAll();
+}
+
+
+void K3bProjectBurnDialog::slotWritingAppChanged( int )
+{
+ slotToggleAll();
+}
+
+
+void K3bProjectBurnDialog::toggleAll()
+{
+ K3bDevice::Device* dev = m_writerSelectionWidget->writerDevice();
+ if( dev ) {
+ if( m_dvd ) {
+ if( (dev->type() & (K3bDevice::DVDPR|K3bDevice::DVDPRW)) &&
+ !(dev->type() & (K3bDevice::DVDR|K3bDevice::DVDRW)) ) {
+ // no simulation support for DVD+R(W) only drives
+ m_checkSimulate->setChecked(false);
+ m_checkSimulate->setEnabled(false);
+ }
+ else {
+ m_checkSimulate->setEnabled(true);
+ }
+ }
+
+ setButtonEnabled( START_BUTTON, true );
+ }
+ else
+ setButtonEnabled( START_BUTTON, false );
+
+ m_writingModeWidget->determineSupportedModesFromMedium( dev );
+
+ m_writingModeWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_checkSimulate->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_checkCacheImage->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_checkRemoveBufferFiles->setDisabled( m_checkOnlyCreateImage->isChecked() || !m_checkCacheImage->isChecked() );
+ if( m_checkOnlyCreateImage->isChecked() ) {
+ m_checkRemoveBufferFiles->setChecked(false);
+ setButtonEnabled( START_BUTTON, true );
+ }
+ m_tempDirSelectionWidget->setDisabled( !m_checkCacheImage->isChecked() && !m_checkOnlyCreateImage->isChecked() );
+ m_writerSelectionWidget->setDisabled( m_checkOnlyCreateImage->isChecked() );
+ m_spinCopies->setDisabled( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() );
+
+ if( !m_dvd ) {
+ // we only support DAO with cdrdao
+ if( m_writerSelectionWidget->writingApp() == K3b::CDRDAO )
+ m_writingModeWidget->setSupportedModes( K3b::DAO );
+ }
+
+ if( m_checkOnlyCreateImage->isChecked() )
+ setButtonText( START_BUTTON,
+ i18n("Start"),
+ i18n("Start the image creation") );
+ else
+ setButtonText( START_BUTTON, i18n("Burn"),
+ i18n("Start the burning process") );
+}
+
+
+int K3bProjectBurnDialog::execBurnDialog( bool burn )
+{
+ if( burn && m_job == 0 ) {
+ setButtonShown( START_BUTTON, true );
+ setDefaultButton( START_BUTTON );
+ }
+ else {
+ setButtonShown( START_BUTTON, false );
+ setDefaultButton( SAVE_BUTTON );
+ }
+
+ return K3bInteractionDialog::exec(false);
+}
+
+
+void K3bProjectBurnDialog::slotSaveClicked()
+{
+ saveSettings();
+ done( Saved );
+}
+
+
+void K3bProjectBurnDialog::slotCancelClicked()
+{
+ done( Canceled );
+}
+
+
+void K3bProjectBurnDialog::slotStartClicked()
+{
+ saveSettings();
+
+ if( m_tempDirSelectionWidget ) {
+ if( !doc()->onTheFly() || doc()->onlyCreateImages() ) {
+ //
+ // check if the temp dir exists
+ //
+ QString tempDir = m_tempDirSelectionWidget->tempDirectory();
+ if( !QFile::exists( tempDir ) ) {
+ if( KMessageBox::warningYesNo( this, i18n("Image folder '%1' does not exist. Do you want K3b to create it?").arg( tempDir ) )
+ == KMessageBox::Yes ) {
+ if( !KStandardDirs::makeDir( tempDir ) ) {
+ KMessageBox::error( this, i18n("Failed to create folder '%1'.").arg( tempDir ) );
+ return;
+ }
+ }
+ else
+ return;
+ }
+
+ //
+ // check if enough space in tempdir if not on-the-fly
+ //
+ if( doc()->size()/1024 > m_tempDirSelectionWidget->freeTempSpace() ) {
+ if( KMessageBox::warningContinueCancel( this, i18n("There seems to be not enough free space in temporary directory. "
+ "Write anyway?") ) == KMessageBox::Cancel )
+ return;
+ }
+ }
+ }
+
+ K3bJobProgressDialog* dlg = 0;
+ if( m_checkOnlyCreateImage && m_checkOnlyCreateImage->isChecked() )
+ dlg = new K3bJobProgressDialog( parentWidget() );
+ else
+ dlg = new K3bBurnProgressDialog( parentWidget() );
+
+ m_job = m_doc->newBurnJob( dlg );
+
+ if( m_writerSelectionWidget )
+ m_job->setWritingApp( m_writerSelectionWidget->writingApp() );
+ prepareJob( m_job );
+
+ if( !exitLoopOnHide() )
+ hide();
+
+ dlg->startJob(m_job);
+
+ kdDebug() << "(K3bProjectBurnDialog) job done. cleaning up." << endl;
+
+ delete m_job;
+ m_job = 0;
+ delete dlg;
+
+ done( Burn );
+}
+
+
+void K3bProjectBurnDialog::prepareGui()
+{
+ QVBoxLayout* mainLay = new QVBoxLayout( mainWidget() );
+ mainLay->setAutoAdd( true );
+ mainLay->setMargin( 0 );
+ mainLay->setSpacing( KDialog::spacingHint() );
+
+ m_writerSelectionWidget = new K3bWriterSelectionWidget( mainWidget() );
+ m_writerSelectionWidget->setWantedMediumType( m_dvd ? K3bDevice::MEDIA_WRITABLE_DVD : K3bDevice::MEDIA_WRITABLE_CD );
+ m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY );
+
+ m_tabWidget = new QTabWidget( mainWidget() );
+
+ QWidget* w = new QWidget( m_tabWidget );
+ m_tabWidget->addTab( w, i18n("Writing") );
+
+ QGroupBox* groupWritingMode = new QGroupBox( 1, Qt::Vertical, i18n("Writing Mode"), w );
+ groupWritingMode->setInsideMargin( marginHint() );
+ m_writingModeWidget = new K3bWritingModeWidget( groupWritingMode );
+
+ m_optionGroup = new QGroupBox( 0, Qt::Vertical, i18n("Settings"), w );
+ m_optionGroup->layout()->setMargin(0);
+ m_optionGroup->layout()->setSpacing(0);
+ m_optionGroupLayout = new QVBoxLayout( m_optionGroup->layout() );
+ m_optionGroupLayout->setMargin( KDialog::marginHint() );
+ m_optionGroupLayout->setSpacing( KDialog::spacingHint() );
+
+ // add the options
+ m_checkCacheImage = K3bStdGuiItems::createCacheImageCheckbox( m_optionGroup );
+ m_checkSimulate = K3bStdGuiItems::simulateCheckbox( m_optionGroup );
+ m_checkRemoveBufferFiles = K3bStdGuiItems::removeImagesCheckbox( m_optionGroup );
+ m_checkOnlyCreateImage = K3bStdGuiItems::onlyCreateImagesCheckbox( m_optionGroup );
+
+ m_optionGroupLayout->addWidget(m_checkSimulate);
+ m_optionGroupLayout->addWidget(m_checkCacheImage);
+ m_optionGroupLayout->addWidget(m_checkOnlyCreateImage);
+ m_optionGroupLayout->addWidget(m_checkRemoveBufferFiles);
+
+ QGroupBox* groupCopies = new QGroupBox( 2, Qt::Horizontal, i18n("Copies"), w );
+ groupCopies->setInsideSpacing( spacingHint() );
+ groupCopies->setInsideMargin( marginHint() );
+ QLabel* pixLabel = new QLabel( groupCopies );
+ pixLabel->setPixmap( SmallIcon( "cdcopy", KIcon::SizeMedium ) );
+ pixLabel->setScaledContents( false );
+ m_spinCopies = new QSpinBox( 1, 999, 1, groupCopies );
+
+ // arrange it
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setMargin( KDialog::marginHint() );
+ grid->setSpacing( KDialog::spacingHint() );
+
+ grid->addWidget( groupWritingMode, 0, 0 );
+ grid->addMultiCellWidget( m_optionGroup, 0, 2, 1, 1 );
+ grid->addWidget( groupCopies, 2, 0 );
+ // grid->addMultiCellWidget( m_tempDirSelectionWidget, 1, 3, 1, 1 );
+ grid->setRowStretch( 1, 1 );
+ grid->setColStretch( 1, 1 );
+
+ QWidget* tempW = new QWidget( m_tabWidget );
+ grid = new QGridLayout( tempW );
+ grid->setMargin( KDialog::marginHint() );
+ grid->setSpacing( KDialog::spacingHint() );
+ m_tabWidget->addTab( tempW, i18n("Image") );
+ m_tempDirSelectionWidget = new K3bTempDirSelectionWidget( tempW );
+ grid->addWidget( m_tempDirSelectionWidget, 0, 0 );
+ m_tempDirSelectionWidget->setNeededSize( doc()->size() );
+
+ // tab order
+ setTabOrder( m_writerSelectionWidget, m_writingModeWidget );
+ setTabOrder( m_writingModeWidget, groupCopies );
+ setTabOrder( groupCopies, m_optionGroup );
+
+ // some default connections that should always be useful
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged()), this, SLOT(slotWriterChanged()) );
+ connect( m_writerSelectionWidget, SIGNAL(writerChanged(K3bDevice::Device*)),
+ m_writingModeWidget, SLOT(determineSupportedModesFromMedium(K3bDevice::Device*)) );
+ connect( m_writerSelectionWidget, SIGNAL(writingAppChanged(int)), this, SLOT(slotWritingAppChanged(int)) );
+ connect( m_checkCacheImage, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_checkSimulate, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_checkOnlyCreateImage, SIGNAL(toggled(bool)), this, SLOT(slotToggleAll()) );
+ connect( m_writingModeWidget, SIGNAL(writingModeChanged(int)), this, SLOT(slotToggleAll()) );
+}
+
+
+void K3bProjectBurnDialog::addPage( QWidget* page, const QString& title )
+{
+ m_tabWidget->addTab( page, title );
+}
+
+
+void K3bProjectBurnDialog::saveSettings()
+{
+ m_doc->setDummy( m_checkSimulate->isChecked() );
+ m_doc->setOnTheFly( !m_checkCacheImage->isChecked() );
+ m_doc->setOnlyCreateImages( m_checkOnlyCreateImage->isChecked() );
+ m_doc->setRemoveImages( m_checkRemoveBufferFiles->isChecked() );
+ m_doc->setSpeed( m_writerSelectionWidget->writerSpeed() );
+ m_doc->setBurner( m_writerSelectionWidget->writerDevice() );
+ m_doc->setWritingMode( m_writingModeWidget->writingMode() );
+ m_doc->setWritingApp( m_writerSelectionWidget->writingApp() );
+ m_doc->setCopies( m_spinCopies->value() );
+}
+
+
+void K3bProjectBurnDialog::readSettings()
+{
+ m_checkSimulate->setChecked( doc()->dummy() );
+ m_checkCacheImage->setChecked( !doc()->onTheFly() );
+ m_checkOnlyCreateImage->setChecked( m_doc->onlyCreateImages() );
+ m_checkRemoveBufferFiles->setChecked( m_doc->removeImages() );
+ m_writingModeWidget->setWritingMode( doc()->writingMode() );
+ m_writerSelectionWidget->setWriterDevice( doc()->burner() );
+ m_writerSelectionWidget->setSpeed( doc()->speed() );
+ m_writerSelectionWidget->setWritingApp( doc()->writingApp() );
+ m_spinCopies->setValue( m_doc->copies() );
+}
+
+
+void K3bProjectBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ m_writingModeWidget->saveConfig( c );
+ c->writeEntry( "simulate", m_checkSimulate->isChecked() );
+ c->writeEntry( "on_the_fly", !m_checkCacheImage->isChecked() );
+ c->writeEntry( "remove_image", m_checkRemoveBufferFiles->isChecked() );
+ c->writeEntry( "only_create_image", m_checkOnlyCreateImage->isChecked() );
+ c->writeEntry( "copies", m_spinCopies->value() );
+
+ m_tempDirSelectionWidget->saveConfig( c );
+ m_writerSelectionWidget->saveConfig( c );
+}
+
+
+void K3bProjectBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_writingModeWidget->loadConfig( c );
+ m_checkSimulate->setChecked( c->readBoolEntry( "simulate", false ) );
+ m_checkCacheImage->setChecked( !c->readBoolEntry( "on_the_fly", true ) );
+ m_checkRemoveBufferFiles->setChecked( c->readBoolEntry( "remove_image", true ) );
+ m_checkOnlyCreateImage->setChecked( c->readBoolEntry( "only_create_image", false ) );
+ m_spinCopies->setValue( c->readNumEntry( "copies", 1 ) );
+
+ m_tempDirSelectionWidget->readConfig( c );
+ m_writerSelectionWidget->loadConfig( c );
+}
+
+
+void K3bProjectBurnDialog::loadK3bDefaults()
+{
+ m_writerSelectionWidget->loadDefaults();
+ m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO );
+ m_checkSimulate->setChecked( false );
+ m_checkCacheImage->setChecked( false );
+ m_checkRemoveBufferFiles->setChecked( true );
+ m_checkOnlyCreateImage->setChecked( false );
+ m_spinCopies->setValue( 1 );
+
+ if( m_tempDirSelectionWidget->selectionMode() == K3bTempDirSelectionWidget::DIR )
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() );
+ else
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() + doc()->name() + ".iso" );
+}
+
+#include "k3bprojectburndialog.moc"
diff --git a/src/projects/k3bprojectburndialog.h b/src/projects/k3bprojectburndialog.h
new file mode 100644
index 0000000..f011ae8
--- /dev/null
+++ b/src/projects/k3bprojectburndialog.h
@@ -0,0 +1,191 @@
+/*
+ *
+ * $Id: k3bprojectburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BPROJECTBURNDIALOG_H
+#define K3BPROJECTBURNDIALOG_H
+
+#include <k3binteractiondialog.h>
+
+
+class K3bDoc;
+class K3bBurnJob;
+class K3bWriterSelectionWidget;
+class K3bTempDirSelectionWidget;
+class QGroupBox;
+class QCheckBox;
+class QTabWidget;
+class QSpinBox;
+class QVBoxLayout;
+class K3bWritingModeWidget;
+class KConfigBase;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bProjectBurnDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bProjectBurnDialog( K3bDoc* doc, QWidget *parent=0, const char *name=0,
+ bool modal = true, bool dvd = false );
+ ~K3bProjectBurnDialog();
+
+ enum resultCode { Canceled = 0, Saved = 1, Burn = 2 };
+
+ /**
+ * shows the dialog with exec().
+ * Use this instead of K3bInteractionDialog::exec
+ * \param burn If true the dialog shows the Burn-button
+ */
+ int execBurnDialog( bool burn );
+
+ K3bDoc* doc() const { return m_doc; }
+
+ protected slots:
+ /** burn */
+ virtual void slotStartClicked();
+ /** save */
+ virtual void slotSaveClicked();
+ virtual void slotCancelClicked();
+
+ /**
+ * gets called if the user changed the writer
+ * default implementation just calls
+ * toggleAllOptions()
+ */
+ virtual void slotWriterChanged();
+
+ /**
+ * gets called if the user changed the writing app
+ * default implementation just calls
+ * toggleAllOptions()
+ */
+ virtual void slotWritingAppChanged( int );
+
+ signals:
+ void writerChanged();
+
+ protected:
+ /**
+ * The default implementation loads the following defaults:
+ * <ul>
+ * <li>Writing mode</li>
+ * <li>Simulate</li>
+ * <li>on the fly</li>
+ * <li>remove images</li>
+ * <li>only create images</li>
+ * </ul>
+ */
+ virtual void loadK3bDefaults();
+
+ /**
+ * The default implementation loads the following settings from the KConfig.
+ * May be used in subclasses.
+ * <ul>
+ * <li>Writing mode</li>
+ * <li>Simulate</li>
+ * <li>on the fly</li>
+ * <li>remove images</li>
+ * <li>only create images</li>
+ * <li>writer</li>
+ * <li>writing speed</li>
+ * </ul>
+ */
+ virtual void loadUserDefaults( KConfigBase* );
+
+ /**
+ * The default implementation saves the following settings to the KConfig.
+ * May be used in subclasses.
+ * <ul>
+ * <li>Writing mode</li>
+ * <li>Simulate</li>
+ * <li>on the fly</li>
+ * <li>remove images</li>
+ * <li>only create images</li>
+ * <li>writer</li>
+ * <li>writing speed</li>
+ * </ul>
+ */
+ virtual void saveUserDefaults( KConfigBase* );
+
+ /**
+ * The default implementation saves the following settings to the doc and may be called
+ * in subclasses:
+ * <ul>
+ * <li>Writing mode</li>
+ * <li>Simulate</li>
+ * <li>on the fly</li>
+ * <li>remove images</li>
+ * <li>only create images</li>
+ * <li>writer</li>
+ * <li>writing speed</li>
+ * </ul>
+ */
+ virtual void saveSettings();
+
+ /**
+ * The default implementation reads the following settings from the doc and may be called
+ * in subclasses:
+ * <ul>
+ * <li>Writing mode</li>
+ * <li>Simulate</li>
+ * <li>on the fly</li>
+ * <li>remove images</li>
+ * <li>only create images</li>
+ * <li>writer</li>
+ * <li>writing speed</li>
+ * </ul>
+ */
+ virtual void readSettings();
+
+ virtual void toggleAll();
+
+ /**
+ * use this to set additionell stuff in the job
+ */
+ virtual void prepareJob( K3bBurnJob* ) {};
+
+ void prepareGui();
+
+ void addPage( QWidget*, const QString& title );
+
+ /**
+ * Call this if you must reimplement it.
+ * \reimplemented from K3bInteractionDialog
+ */
+ virtual void init();
+
+ K3bWriterSelectionWidget* m_writerSelectionWidget;
+ K3bTempDirSelectionWidget* m_tempDirSelectionWidget;
+ K3bWritingModeWidget* m_writingModeWidget;
+ QGroupBox* m_optionGroup;
+ QVBoxLayout* m_optionGroupLayout;
+ QCheckBox* m_checkCacheImage;
+ QCheckBox* m_checkSimulate;
+ QCheckBox* m_checkRemoveBufferFiles;
+ QCheckBox* m_checkOnlyCreateImage;
+ QSpinBox* m_spinCopies;
+
+ private:
+ K3bDoc* m_doc;
+ K3bBurnJob* m_job;
+ QTabWidget* m_tabWidget;
+ bool m_dvd;
+};
+
+#endif
diff --git a/src/projects/k3bprojectplugindialog.cpp b/src/projects/k3bprojectplugindialog.cpp
new file mode 100644
index 0000000..a28f563
--- /dev/null
+++ b/src/projects/k3bprojectplugindialog.cpp
@@ -0,0 +1,68 @@
+/*
+ *
+ * $Id: k3bprojectplugindialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bprojectplugindialog.h"
+
+#include <k3bprojectplugin.h>
+
+#include <qwidget.h>
+
+
+K3bProjectPluginDialog::K3bProjectPluginDialog( K3bProjectPlugin* plugin, K3bDoc* doc, QWidget* parent, const char* name )
+ : K3bInteractionDialog( parent, name,
+ QString::null,
+ QString::null,
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ plugin->className() ),
+ m_plugin(plugin)
+{
+ m_pluginGui = plugin->createGUI( doc, this, 0 );
+ Q_ASSERT( m_pluginGui );
+ Q_ASSERT( m_pluginGui->qWidget() );
+ setMainWidget( m_pluginGui->qWidget() );
+ setTitle( m_pluginGui->title(), m_pluginGui->subTitle() );
+}
+
+
+K3bProjectPluginDialog::~K3bProjectPluginDialog()
+{
+}
+
+
+void K3bProjectPluginDialog::slotStartClicked()
+{
+ m_pluginGui->activate();
+}
+
+
+void K3bProjectPluginDialog::saveUserDefaults( KConfigBase* config )
+{
+ m_pluginGui->saveSettings( config );
+}
+
+
+void K3bProjectPluginDialog::loadUserDefaults( KConfigBase* config )
+{
+ m_pluginGui->readSettings( config );
+}
+
+
+void K3bProjectPluginDialog::loadK3bDefaults()
+{
+ m_pluginGui->loadDefaults();
+}
+
+#include "k3bprojectplugindialog.moc"
diff --git a/src/projects/k3bprojectplugindialog.h b/src/projects/k3bprojectplugindialog.h
new file mode 100644
index 0000000..f2250d7
--- /dev/null
+++ b/src/projects/k3bprojectplugindialog.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * $Id: k3bprojectplugindialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_PROJECTPLUGIN_DIALOG_H_
+#define _K3B_PROJECTPLUGIN_DIALOG_H_
+
+#include <k3binteractiondialog.h>
+
+class K3bProjectPlugin;
+class K3bProjectPluginGUIBase;
+class K3bDoc;
+class KConfigBase;
+
+
+class K3bProjectPluginDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bProjectPluginDialog( K3bProjectPlugin*, K3bDoc*, QWidget*, const char* name = 0 );
+ ~K3bProjectPluginDialog();
+
+ protected slots:
+ void slotStartClicked();
+ void saveUserDefaults( KConfigBase* config );
+ void loadUserDefaults( KConfigBase* config );
+ void loadK3bDefaults();
+
+ private:
+ K3bProjectPlugin* m_plugin;
+ K3bProjectPluginGUIBase* m_pluginGui;
+};
+
+#endif
diff --git a/src/projects/k3bvcdburndialog.cpp b/src/projects/k3bvcdburndialog.cpp
new file mode 100644
index 0000000..3c45c14
--- /dev/null
+++ b/src/projects/k3bvcdburndialog.cpp
@@ -0,0 +1,1088 @@
+/*
+*
+* $Id: k3bvcdburndialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qspinbox.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qgrid.h>
+#include <qtoolbutton.h>
+#include <qfileinfo.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kio/global.h>
+#include <kapplication.h>
+
+#include "k3bvcdburndialog.h"
+#include "k3bvcddoc.h"
+#include "k3bvcdoptions.h"
+#include <k3bdevice.h>
+#include <k3bcore.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bstdguiitems.h>
+#include <k3bglobals.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bvalidators.h>
+
+K3bVcdBurnDialog::K3bVcdBurnDialog( K3bVcdDoc* _doc, QWidget *parent, const char *name, bool modal )
+ : K3bProjectBurnDialog( _doc, parent, name, modal )
+{
+ m_vcdDoc = _doc;
+
+ prepareGui();
+
+ QString vcdType;
+ switch ( m_vcdDoc->vcdType() ) {
+ case K3bVcdDoc::VCD11:
+ vcdType = i18n( "Video CD (Version 1.1)" );
+ case K3bVcdDoc::VCD20:
+ vcdType = i18n( "Video CD (Version 2.0)" );
+ case K3bVcdDoc::SVCD10:
+ vcdType = i18n( "Super Video CD" );
+ case K3bVcdDoc::HQVCD:
+ vcdType = i18n( "High-Quality Video CD" );
+ default:
+ vcdType = i18n( "Video CD" );
+ }
+
+ setTitle( vcdType, i18n( "1 MPEG (%1)", "%n MPEGs (%1)",
+ m_vcdDoc->tracks() ->count() ).arg( KIO::convertSize( m_vcdDoc->size() ) ) );
+
+ const K3bExternalBin* cdrecordBin = k3bcore->externalBinManager() ->binObject( "cdrecord" );
+ if ( cdrecordBin && cdrecordBin->hasFeature( "cuefile" ) )
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::CDRDAO | K3b::CDRECORD );
+ else
+ m_writerSelectionWidget->setSupportedWritingApps( K3b::CDRDAO );
+
+ m_checkCacheImage->hide();
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ setupVideoCdTab();
+ setupLabelTab();
+ setupAdvancedTab();
+
+ connect( m_spinVolumeCount, SIGNAL( valueChanged( int ) ), this, SLOT( slotSpinVolumeCount() ) );
+ connect( m_groupVcdFormat, SIGNAL( clicked( int ) ), this, SLOT( slotVcdTypeClicked( int ) ) );
+ connect( m_checkCdiSupport, SIGNAL( toggled( bool ) ), this, SLOT( slotCdiSupportChecked( bool ) ) );
+ connect( m_checkAutoDetect, SIGNAL( toggled( bool ) ), this, SLOT( slotAutoDetect( bool ) ) );
+ connect( m_checkGaps, SIGNAL( toggled( bool ) ), this, SLOT( slotGapsChecked( bool ) ) );
+
+ // ToolTips
+ // -------------------------------------------------------------------------
+ QToolTip::add
+ ( m_radioVcd11, i18n( "Select Video CD type %1" ).arg( "(VCD 1.1)" ) );
+ QToolTip::add
+ ( m_radioVcd20, i18n( "Select Video CD type %1" ).arg( "(VCD 2.0)" ) );
+ QToolTip::add
+ ( m_radioSvcd10, i18n( "Select Video CD type %1" ).arg( "(SVCD 1.0)" ) );
+ QToolTip::add
+ ( m_radioHqVcd10, i18n( "Select Video CD type %1" ).arg( "(HQ-VCD 1.0)" ) );
+ QToolTip::add
+ ( m_checkAutoDetect, i18n( "Automatic video type recognition." ) );
+ QToolTip::add
+ ( m_checkNonCompliant, i18n( "Non-compliant compatibility mode for broken devices" ) );
+ QToolTip::add
+ ( m_checkVCD30interpretation, i18n( "Chinese VCD3.0 track interpretation" ) );
+ QToolTip::add
+ ( m_check2336, i18n( "Use 2336 byte sectors for output" ) );
+
+ QToolTip::add
+ ( m_editVolumeId, i18n( "Specify ISO volume label for Video CD" ) );
+ QToolTip::add
+ ( m_editAlbumId, i18n( "Specify album id for VideoCD set" ) );
+ QToolTip::add
+ ( m_spinVolumeNumber, i18n( "Specify album set sequence number ( <= volume-count )" ) );
+ QToolTip::add
+ ( m_spinVolumeCount, i18n( "Specify number of volumes in album set" ) );
+
+ QToolTip::add
+ ( m_checkCdiSupport, i18n( "Enable CD-i Application Support for VideoCD Type 1.1 & 2.0" ) );
+ QToolTip::add
+ ( m_editCdiCfg, i18n( "Configuration parameters (only for VCD 2.0)" ) );
+
+ QToolTip::add
+ ( m_checkPbc, i18n( "Playback control, PBC, is available for Video CD 2.0 and Super Video CD 1.0 disc formats." ) );
+ QToolTip::add
+ ( m_checkSegmentFolder, i18n( "Add always an empty `/SEGMENT' directory" ) );
+ QToolTip::add
+ ( m_checkRelaxedAps, i18n( "This controls whether APS constraints are strict or relaxed. " ) );
+ QToolTip::add
+ ( m_checkUpdateScanOffsets, i18n( "This controls whether to update the scan data information contained in the MPEG-2 video streams." ) );
+ QToolTip::add
+ ( m_labelRestriction, i18n( "This element allows to set viewing restrictions which may be interpreted by the playing device." ) );
+
+ QToolTip::add
+ ( m_checkGaps, i18n( "This option allows customization of Gaps and Margins." ) );
+ QToolTip::add
+ ( m_labelPreGapLeadout, i18n( "Used to set the number of empty sectors added before the lead-out area begins." ) );
+ QToolTip::add
+ ( m_labelPreGapTrack, i18n( "Used to set the track pre-gap for all tracks in sectors globally." ) );
+ QToolTip::add
+ ( m_labelFrontMarginTrack, i18n( "Sets the front margin for sequence items." ) );
+ QToolTip::add
+ ( m_labelRearMarginTrack, i18n( "Sets the rear margin for sequence items." ) );
+
+ // What's This info
+ // -------------------------------------------------------------------------
+ QWhatsThis::add
+ ( m_radioVcd11, i18n( "<p>This is the most basic <b>Video CD</b> specification dating back to 1993, which has the following characteristics:"
+ "<ul><li>One mode2 mixed form ISO-9660 track containing file pointers to the information areas.</li>"
+ "<li>Up to 98 multiplex-ed MPEG-1 audio/video streams or CD-DA audio tracks.</li>"
+ "<li>Up to 500 MPEG sequence entry points used as chapter divisions.</li></ul>"
+ "<p>The Video CD specification requires the multiplex-ed MPEG-1 stream to have a CBR of less than 174300 bytes (1394400 bits) per second in order to accommodate single speed CD-ROM drives.<br>"
+ "The specification allows for the following two resolutions:"
+ "<ul><li>352 x 240 @ 29.97 Hz (NTSC SIF).</li>"
+ "<li>352 x 240 @ 23.976 Hz (FILM SIF).</li></ul>"
+ "<p>The CBR MPEG-1, layer II audio stream is fixed at 224 kbps with 1 stereo or 2 mono channels."
+ "<p><b>It is recommended to keep the video bit-rate under 1151929.1 bps.</b>" ) );
+
+ QWhatsThis::add
+ ( m_radioVcd20, i18n( "<p>About two years after the Video CD 1.1 specification came out, an improved <b>Video CD 2.0</b> standard was published in 1995."
+ "<p>This one added the following items to the features already available in the Video CD 1.1 specification:"
+ "<ul><li>Support for MPEG segment play items (<b>\"SPI\"</b>), consisting of still pictures, motion pictures and/or audio (only) streams was added.</li>"
+ "<li>Note Segment Items::.</li>"
+ "<li>Support for interactive playback control (<b>\"PBC\"</b>) was added.</li>"
+ "<li>Support for playing related access by providing a scan point index file was added. (<b>\"/EXT/SCANDATA.DAT\"</b>)</li>"
+ "<li>Support for closed captions.</li>"
+ "<li>Support for mixing NTSC and PAL content.</li></ul>"
+ "<p>By adding PAL support to the Video CD 1.1 specification, the following resolutions became available:"
+ "<ul><li>352 x 240 @ 29.97 Hz (NTSC SIF).</li>"
+ "<li>352 x 240 @ 23.976 Hz (FILM SIF).</li>"
+ "<li>352 x 288 @ 25 Hz (PAL SIF).</li></ul>"
+ "<p>For segment play items the following audio encodings became available:"
+ "<ul><li>Joint stereo, stereo or dual channel audio streams at 128, 192, 224 or 384 kbit/sec bit-rate.</li>"
+ "<li>Mono audio streams at 64, 96 or 192 kbit/sec bit-rate.</li></ul>"
+ "<p>Also the possibility to have audio only streams and still pictures was provided."
+ "<p><b>The bit-rate of multiplex-ed streams should be kept under 174300 bytes/sec (except for single still picture items) in order to accommodate single speed drives.</b>" ) );
+
+ QWhatsThis::add
+ ( m_radioSvcd10, i18n( "<p>With the upcoming of the DVD-V media, a new VCD standard had to be published in order to be able to keep up with technology, so the Super Video CD specification was called into life 1999."
+ "<p>In the midst of 2000 a full subset of this <b>Super Video CD</b> specification was published as <b>IEC-62107</b>."
+ "<p>As the most notable change over Video CD 2.0 is a switch from MPEG-1 CBR to MPEG-2 VBR encoding for the video stream was performed."
+ "<p>The following new features--building upon the Video CD 2.0 specification--are:"
+ "<ul><li>Use of MPEG-2 encoding instead of MPEG-1 for the video stream.</li>"
+ "<li>Allowed VBR encoding of MPEG-1 audio stream.</li>"
+ "<li>Higher resolutions (see below) for video stream resolution.</li>"
+ "<li>Up to 4 overlay graphics and text (<b>\"OGT\"</b>) sub-channels for user switchable subtitle displaying in addition to the already existing closed caption facility.</li>"
+ "<li>Command lists for controlling the SVCD virtual machine.</li></ul>"
+ "<p>For the <b>Super Video CD</b>, only the following two resolutions are supported for motion video and (low resolution) still pictures:"
+ "<ul><li>480 x 480 @ 29.97 Hz (NTSC 2/3 D-2).</li>"
+ "<li>480 x 576 @ 25 Hz (PAL 2/3 D-2).</li></ul>" ) );
+
+ QWhatsThis::add
+ ( m_radioHqVcd10, i18n( "<p>This is actually just a minor variation defined in IEC-62107 on the Super Video CD 1.0 format for compatibility with current products in the market."
+ "<p>It differs from the Super Video CD 1.0 format in the following items:"
+ "<ul><li>The system profile tag field in <b>/SVCD/INFO.SVD</b> is set to <b>1</b> instead of <b>0</b>.</li>"
+ "<li>The system identification field value in <b>/SVCD/INFO.SVD</b> is set to <b>HQ-VCD</b> instead of <b>SUPERVCD</b>.</li>"
+ "<li><b>/EXT/SCANDATA.DAT</b> is mandatory instead of being optional.</li>"
+ "<li><b>/SVCD/SEARCH.DAT</b> is optional instead of being mandatory.</li></ul>" ) );
+
+ QWhatsThis::add
+ ( m_checkAutoDetect, i18n( "<p>If Autodetect is:</p>"
+ "<ul><li>ON then K3b will set the correct VideoCD type.</li>"
+ "<li>OFF then the correct VideoCD type needs to be set by the user.</li></ul>"
+ "<p>If you are not sure about the correct VideoCD type, it is best to turn Autodetect ON.</p>"
+ "<p>If you want to force the VideoCD type, you must turn Autodetect OFF. This is useful for some standalone DVD players without SVCD support.</p>" ) );
+
+ QWhatsThis::add
+ ( m_checkNonCompliant, i18n( "<ul><li>Rename <b>\"/MPEG2\"</b> folder on SVCDs to (non-compliant) \"/MPEGAV\".</li>"
+ "<li>Enables the use of the (deprecated) signature <b>\"ENTRYSVD\"</b> instead of <b>\"ENTRYVCD\"</b> for the file <b>\"/SVCD/ENTRY.SVD\"</b>.</li></ul>" ) );
+ QWhatsThis::add
+ ( m_checkVCD30interpretation, i18n( "<ul><li>Enables the use of the (deprecated) Chinese <b>\"/SVCD/TRACKS.SVD\"</b> format which differs from the format defined in the <b>IEC-62107</b> specification.</li></ul>"
+ "<p><b>The differences are most exposed on SVCDs containing more than one video track.</b>" ) );
+
+ QWhatsThis::add
+ ( m_check2336, i18n( "<p>though most devices will have problems with such an out-of-specification media."
+ "<p><b>You may want use this option for images longer than 80 minutes</b>" ) );
+
+ QWhatsThis::add
+ ( m_checkCdiSupport, i18n( "<p>To allow the play of Video-CDs on a CD-i player, the Video-CD standard requires that a CD-i application program must be present."
+ "<p>This program is designed to:"
+ "<ul><li>provide full play back control as defined in the PSD of the standard</l>"
+ "<li>be extremely simple to use and easy-to-learn for the end-user</li></ul>"
+ "<p>The program runs on CD-i players equipped with the CDRTOS 1.1(.1) operating system and a Digital Video extension cartridge." ) );
+
+ QWhatsThis::add
+ ( m_editCdiCfg, i18n( "<p>Configuration parameters only available for VideoCD 2.0"
+ "<p>The engine works perfectly well when used as-is."
+ "<p>You have the option to configure the VCD application."
+ "<p>You can adapt the color and/or the shape of the cursor and lots more." ) );
+
+
+ QWhatsThis::add
+ ( m_checkPbc, i18n( "<p>Playback control, PBC, is available for Video CD 2.0 and Super Video CD 1.0 disc formats."
+ "<p>PBC allows control of the playback of play items and the possibility of interaction with the user through the remote control or some other input device available." ) );
+
+ QWhatsThis::add
+ ( m_checkSegmentFolder, i18n( "<p>Here you can specify that the folder <b>SEGMENT</b> should always be present."
+ "<p>Some DVD players need the folder to give a faultless rendition." ) );
+
+ QWhatsThis::add
+ ( m_checkRelaxedAps, i18n( "<p>An Access Point Sector, APS, is an MPEG video sector on the VCD/SVCD which is suitable to be jumped to directly."
+ "<p>APS are required for entry points and scantables. APS have to fulfil the requirement to precede every I-frame by a GOP header which shall be preceded by a sequence header in its turn."
+ "<p>The start codes of these 3 items are required to be contained all in the same MPEG pack/sector, thus forming a so-called access point sector."
+ "<p>This requirement can be relaxed by enabling the relaxed aps option, i.e. every sector containing an I-frame will be regarded as an APS."
+ "<p><b>Warning:</b> The sequence header is needed for a playing device to figure out display parameters, such as display resolution and frame rate, relaxing the aps requirement may lead to non-working entry points." ) );
+
+ QWhatsThis::add
+ ( m_checkUpdateScanOffsets, i18n( "<p>According to the specification, it is mandatory for Super Video CDs to encode scan information data into user data blocks in the picture layer of all intra coded picture."
+ "<p>It can be used by playing devices for implementing fast forward & fast reverse scanning."
+ "<p>The already existing scan information data can be updated by enabling the update scan offsets option." ) );
+
+ QWhatsThis::add
+ ( m_labelRestriction, i18n( "<p>Viewing Restriction may be interpreted by the playing device."
+ "<p>The allowed range goes from 0 to 3."
+ "<ul><li>0 = unrestricted, free to view for all</li>"
+ "<li>3 = restricted, content not suitable for ages under 18</li></ul>"
+ "<p>Actually, the exact meaning is not defined and is player dependant."
+ "<p><b>Most players ignore that value.<b>" ) );
+
+ QWhatsThis::add
+ ( m_checkGaps, i18n( "<p>This option allows customization of Gaps and Margins." ) );
+ QWhatsThis::add
+ ( m_labelPreGapLeadout, i18n( "<p>This option allows to set the number of empty sectors added before the lead-out area begins, i.e. the number of post-gap sectors."
+ "<p>The ECMA-130 specification requires the last data track before the lead-out to carry a post-gap of at least 150 sectors, which is used as default for this parameter."
+ "<p>Some operating systems may encounter I/O errors due to read-ahead issues when reading the last MPEG track if this parameter is set too low."
+ "<p>Allowed value content: [0..300]. Default: 150." ) );
+
+ QWhatsThis::add
+ ( m_labelPreGapTrack, i18n( "<p>Used to set the track pre-gap for all tracks in sectors globally."
+ "<p>The specification requires the pre-gaps to be at least 150 sectors long."
+ "<p>Allowed value content: [0..300]. Default: 150." ) );
+
+ QWhatsThis::add
+ ( m_labelFrontMarginTrack, i18n( "Margins are used to compensate for inaccurate sector-addressing issues on CD-ROM media. Interestingly, they have been abandoned for Super Video CDs."
+ "<p>For Video CD 1.0/1.1/2.0 this margin should be at least 15 sectors long."
+ "<p>Allowed value content: [0..150]. Default: 30 for Video CD 1.0/1.1/2.0, otherwise (i.e. Super Video CD 1.0 and HQ-VCD 1.0) 0." ) );
+
+ QWhatsThis::add
+ ( m_labelRearMarginTrack, i18n( "<p>Margins are used to compensate for inaccurate sector-addressing issues on CD-ROM media. Interestingly, they have been abandoned for Super Video CDs."
+ "<p>For Video CD 1.0/1.1/2.0 this margin should be at least 15 sectors long."
+ "<p>Allowed value content: [0..150]. Default: 45 for Video CD 1.0/1.1/2.0, otherwise 0." ) );
+
+}
+
+
+K3bVcdBurnDialog::~K3bVcdBurnDialog()
+{}
+
+void K3bVcdBurnDialog::setupAdvancedTab()
+{
+ QWidget * w = new QWidget( this );
+
+ // ---------------------------------------------------- generic group ----
+ m_groupGeneric = new QGroupBox( 5, Qt::Vertical, i18n( "Generic" ), w );
+
+ m_checkPbc = new QCheckBox( i18n( "Playback Control (PBC)" ), m_groupGeneric );
+ m_checkSegmentFolder = new QCheckBox( i18n( "SEGMENT Folder must always be present" ), m_groupGeneric );
+ m_checkRelaxedAps = new QCheckBox( i18n( "Relaxed aps" ), m_groupGeneric );
+ m_checkUpdateScanOffsets = new QCheckBox( i18n( "Update scan offsets" ), m_groupGeneric );
+ m_checkUpdateScanOffsets->setEnabled( false );
+
+
+ // -------------------------------------------- gaps & margins group ----
+ m_groupGaps = new QGroupBox( 0, Qt::Vertical, i18n( "Gaps" ), w );
+ m_groupGaps->layout() ->setSpacing( spacingHint() );
+ m_groupGaps->layout() ->setMargin( marginHint() );
+
+ QGridLayout* groupGapsLayout = new QGridLayout( m_groupGaps->layout() );
+ groupGapsLayout->setAlignment( Qt::AlignTop );
+
+ m_checkGaps = new QCheckBox( i18n( "Customize gaps and margins" ), m_groupGaps );
+
+ m_labelPreGapLeadout = new QLabel( i18n( "Leadout pre gap (0..300):" ), m_groupGaps, "labelPreGapLeadout" );
+ m_spinPreGapLeadout = new QSpinBox( m_groupGaps, "m_spinPreGapLeadout" );
+ m_spinPreGapLeadout->setMinValue( 0 );
+ m_spinPreGapLeadout->setMaxValue( 300 );
+
+ m_labelPreGapTrack = new QLabel( i18n( "Track pre gap (0..300):" ), m_groupGaps, "labelPreGapTrack" );
+ m_spinPreGapTrack = new QSpinBox( m_groupGaps, "m_spinPreGapTrack" );
+ m_spinPreGapTrack->setMinValue( 0 );
+ m_spinPreGapTrack->setMaxValue( 300 );
+
+ m_labelFrontMarginTrack = new QLabel( i18n( "Track front margin (0..150):" ), m_groupGaps, "labelFrontMarginTrack" );
+ m_spinFrontMarginTrack = new QSpinBox( m_groupGaps, "m_spinFrontMarginTrack" );
+ m_spinFrontMarginTrack->setMinValue( 0 );
+ m_spinFrontMarginTrack->setMaxValue( 150 );
+ m_spinFrontMarginTrackSVCD = new QSpinBox( m_groupGaps, "m_spinFrontMarginTrackSVCD" );
+ m_spinFrontMarginTrackSVCD->setMinValue( 0 );
+ m_spinFrontMarginTrackSVCD->setMaxValue( 150 );
+ m_spinFrontMarginTrackSVCD->setHidden( true );
+
+ m_labelRearMarginTrack = new QLabel( i18n( "Track rear margin (0..150):" ), m_groupGaps, "labelRearMarginTrack" );
+ m_spinRearMarginTrack = new QSpinBox( m_groupGaps, "m_spinRearMarginTrack" );
+ m_spinRearMarginTrack->setMinValue( 0 );
+ m_spinRearMarginTrack->setMaxValue( 150 );
+ m_spinRearMarginTrackSVCD = new QSpinBox( m_groupGaps, "m_spinRearMarginTrackSVCD" );
+ m_spinRearMarginTrackSVCD->setMinValue( 0 );
+ m_spinRearMarginTrackSVCD->setMaxValue( 150 );
+ m_spinRearMarginTrackSVCD->setHidden( true );
+
+ groupGapsLayout->addMultiCellWidget( m_checkGaps, 1, 1, 0, 4 );
+ groupGapsLayout->addWidget( m_labelPreGapLeadout, 2, 0 );
+ groupGapsLayout->addWidget( m_spinPreGapLeadout, 2, 1 );
+ groupGapsLayout->addWidget( m_labelPreGapTrack, 2, 3 );
+ groupGapsLayout->addWidget( m_spinPreGapTrack, 2, 4 );
+
+ groupGapsLayout->addWidget( m_labelFrontMarginTrack, 3, 0 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrack, 3, 1 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrackSVCD, 3, 1 );
+ groupGapsLayout->addWidget( m_labelRearMarginTrack, 3, 3 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrack, 3, 4 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrackSVCD, 3, 4 );
+
+ groupGapsLayout->setRowStretch( 4, 0 );
+
+ groupGapsLayout->addMultiCellWidget( m_checkGaps, 1, 1, 0, 4 );
+ groupGapsLayout->addWidget( m_labelPreGapLeadout, 2, 0 );
+ groupGapsLayout->addWidget( m_spinPreGapLeadout, 2, 1 );
+ groupGapsLayout->addWidget( m_labelPreGapTrack, 2, 3 );
+ groupGapsLayout->addWidget( m_spinPreGapTrack, 2, 4 );
+
+ groupGapsLayout->addWidget( m_labelFrontMarginTrack, 3, 0 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrack, 3, 1 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrackSVCD, 3, 1 );
+ groupGapsLayout->addWidget( m_labelRearMarginTrack, 3, 3 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrack, 3, 4 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrackSVCD, 3, 4 );
+
+ groupGapsLayout->setRowStretch( 4, 0 );
+ groupGapsLayout->addMultiCellWidget( m_checkGaps, 1, 1, 0, 4 );
+ groupGapsLayout->addWidget( m_labelPreGapLeadout, 2, 0 );
+ groupGapsLayout->addWidget( m_spinPreGapLeadout, 2, 1 );
+ groupGapsLayout->addWidget( m_labelPreGapTrack, 2, 3 );
+ groupGapsLayout->addWidget( m_spinPreGapTrack, 2, 4 );
+
+ groupGapsLayout->addWidget( m_labelFrontMarginTrack, 3, 0 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrack, 3, 1 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrackSVCD, 3, 1 );
+ groupGapsLayout->addWidget( m_labelRearMarginTrack, 3, 3 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrack, 3, 4 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrackSVCD, 3, 4 );
+
+ groupGapsLayout->setRowStretch( 4, 0 );
+ groupGapsLayout->addMultiCellWidget( m_checkGaps, 1, 1, 0, 4 );
+ groupGapsLayout->addWidget( m_labelPreGapLeadout, 2, 0 );
+ groupGapsLayout->addWidget( m_spinPreGapLeadout, 2, 1 );
+ groupGapsLayout->addWidget( m_labelPreGapTrack, 2, 3 );
+ groupGapsLayout->addWidget( m_spinPreGapTrack, 2, 4 );
+
+ groupGapsLayout->addWidget( m_labelFrontMarginTrack, 3, 0 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrack, 3, 1 );
+ groupGapsLayout->addWidget( m_spinFrontMarginTrackSVCD, 3, 1 );
+ groupGapsLayout->addWidget( m_labelRearMarginTrack, 3, 3 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrack, 3, 4 );
+ groupGapsLayout->addWidget( m_spinRearMarginTrackSVCD, 3, 4 );
+
+ groupGapsLayout->setRowStretch( 4, 0 );
+
+ // ------------------------------------------------------- misc group ----
+ m_groupMisc = new QGroupBox( 0, Qt::Vertical, i18n( "Misc" ), w );
+ m_groupMisc->layout() ->setSpacing( spacingHint() );
+ m_groupMisc->layout() ->setMargin( marginHint() );
+
+ QGridLayout* groupMiscLayout = new QGridLayout( m_groupMisc->layout() );
+ groupMiscLayout->setAlignment( Qt::AlignTop );
+
+ m_labelRestriction = new QLabel( i18n( "Restriction category (0..3):" ), m_groupMisc, "m_labelRestriction" );
+ m_spinRestriction = new QSpinBox( m_groupMisc, "m_spinRestriction" );
+ m_spinRestriction->setMinValue( 0 );
+ m_spinRestriction->setMaxValue( 3 );
+
+ groupMiscLayout->addWidget( m_labelRestriction, 1, 0 );
+ groupMiscLayout->addMultiCellWidget( m_spinRestriction, 1, 1, 1, 4 );
+ groupMiscLayout->setRowStretch( 2, 0 );
+
+ // ----------------------------------------------------------------------
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setMargin( marginHint() );
+ grid->setSpacing( spacingHint() );
+ grid->addWidget( m_groupGeneric, 0, 0 );
+ grid->addWidget( m_groupGaps, 1, 0 );
+ grid->addWidget( m_groupMisc, 2, 0 );
+
+ addPage( w, i18n( "Advanced" ) );
+}
+
+void K3bVcdBurnDialog::setupVideoCdTab()
+{
+ QWidget * w = new QWidget( this );
+
+ // ---------------------------------------------------- Format group ----
+ m_groupVcdFormat = new QButtonGroup( 4, Qt::Vertical, i18n( "Type" ), w );
+ m_radioVcd11 = new QRadioButton( i18n( "VideoCD 1.1" ), m_groupVcdFormat );
+ m_radioVcd20 = new QRadioButton( i18n( "VideoCD 2.0" ), m_groupVcdFormat );
+ m_radioSvcd10 = new QRadioButton( i18n( "Super-VideoCD" ), m_groupVcdFormat );
+ m_radioHqVcd10 = new QRadioButton( i18n( "HQ-VideoCD" ), m_groupVcdFormat );
+ m_groupVcdFormat->setExclusive( true );
+
+ // ---------------------------------------------------- Options group ---
+
+ m_groupOptions = new QGroupBox( 5, Qt::Vertical, i18n( "Settings" ), w );
+ m_checkAutoDetect = new QCheckBox( i18n( "Autodetect VideoCD type" ), m_groupOptions );
+
+ m_checkNonCompliant = new QCheckBox( i18n( "Enable broken SVCD mode" ), m_groupOptions );
+ // Only available on SVCD Type
+ m_checkNonCompliant->setEnabled( false );
+ m_checkNonCompliant->setChecked( false );
+
+ m_checkVCD30interpretation = new QCheckBox( i18n( "Enable %1 track interpretation" ).arg( "VCD 3.0" ), m_groupOptions );
+ // Only available on SVCD Type
+ m_checkVCD30interpretation->setEnabled( false );
+ m_checkVCD30interpretation->setChecked( false );
+
+ m_check2336 = new QCheckBox( i18n( "Use 2336 byte sectors" ), m_groupOptions );
+
+ m_checkCdiSupport = new QCheckBox( i18n( "Enable CD-i support" ), m_groupOptions );
+
+ // ------------------------------------------------- CD-i Application ---
+ m_groupCdi = new QGroupBox( 4, Qt::Vertical, i18n( "VideoCD on CD-i" ), w );
+ m_editCdiCfg = new QMultiLineEdit( m_groupCdi, "m_editCdiCfg" );
+ m_editCdiCfg->setFrameShape( QTextEdit::NoFrame );
+
+ // ----------------------------------------------------------------------
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setMargin( marginHint() );
+ grid->setSpacing( spacingHint() );
+ grid->addMultiCellWidget( m_groupVcdFormat, 0, 1, 0, 0 );
+ grid->addWidget( m_groupOptions, 0, 1 );
+ grid->addWidget( m_groupCdi, 1, 1 );
+
+ addPage( w, i18n( "Settings" ) );
+}
+
+void K3bVcdBurnDialog::setupLabelTab()
+{
+ QWidget * w = new QWidget( this );
+
+ // ----------------------------------------------------------------------
+ // noEdit
+ QLabel* labelSystemId = new QLabel( i18n( "System:" ), w, "labelSystemId" );
+ QLabel* labelApplicationId = new QLabel( i18n( "Application:" ), w, "labelApplicationId" );
+ QLabel* labelInfoSystemId = new QLabel( vcdDoc() ->vcdOptions() ->systemId(), w, "labelInfoSystemId" );
+ QLabel* labelInfoApplicationId = new QLabel( vcdDoc() ->vcdOptions() ->applicationId(), w, "labelInfoApplicationId" );
+
+ labelInfoSystemId->setFrameShape( QLabel::LineEditPanel );
+ labelInfoSystemId->setFrameShadow( QLabel::Sunken );
+
+ labelInfoApplicationId->setFrameShape( QLabel::LineEditPanel );
+ labelInfoApplicationId->setFrameShadow( QLabel::Sunken );
+ QToolTip::add
+ ( labelInfoApplicationId, i18n( "ISO application id for VideoCD" ) );
+
+ // ----------------------------------------------------------------------
+
+ QLabel* labelVolumeId = new QLabel( i18n( "&Volume name:" ), w, "labelVolumeId" );
+ QLabel* labelAlbumId = new QLabel( i18n( "Volume &set name:" ), w, "labelAlbumId" );
+ QLabel* labelVolumeCount = new QLabel( i18n( "Volume set s&ize:" ), w, "labelVolumeCount" );
+ QLabel* labelVolumeNumber = new QLabel( i18n( "Volume set &number:" ), w, "labelVolumeNumber" );
+ QLabel* labelPublisher = new QLabel( i18n( "&Publisher:" ), w, "labelPublisher" );
+
+
+ m_editVolumeId = new QLineEdit( w, "m_editVolumeId" );
+ m_editAlbumId = new QLineEdit( w, "m_editAlbumId" );
+ m_spinVolumeNumber = new QSpinBox( w, "m_editVolumeNumber" );
+ m_spinVolumeCount = new QSpinBox( w, "m_editVolumeCount" );
+ m_editPublisher = new QLineEdit( w, "m_editPublisher" );
+
+ // only ISO646 d-Characters
+ m_editVolumeId->setValidator( K3bValidators::iso646Validator( K3bValidators::Iso646_d, true, m_editVolumeId ) );
+ m_editAlbumId->setValidator( K3bValidators::iso646Validator( K3bValidators::Iso646_d, true, m_editVolumeId ) );
+
+ m_editVolumeId->setMaxLength( 32 );
+ m_editAlbumId->setMaxLength( 16 );
+ // only ISO646 a-Characters
+ m_editPublisher->setValidator( K3bValidators::iso646Validator( K3bValidators::Iso646_a, true, m_editVolumeId ) );
+ m_editPublisher->setMaxLength( 128 );
+
+ m_spinVolumeNumber->setMinValue( 1 );
+ m_spinVolumeNumber->setMaxValue( 1 );
+ m_spinVolumeCount->setMinValue( 1 );
+
+ QFrame* line = new QFrame( w );
+ line->setFrameShape( QFrame::HLine );
+ line->setFrameShadow( QFrame::Sunken );
+ line->setFrameShape( QFrame::HLine );
+
+
+ // ----------------------------------------------------------------------
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setMargin( marginHint() );
+ grid->setSpacing( spacingHint() );
+
+ grid->addWidget( labelVolumeId, 1, 0 );
+ grid->addMultiCellWidget( m_editVolumeId, 1, 1, 1, 3 );
+ grid->addWidget( labelAlbumId, 2, 0 );
+ grid->addMultiCellWidget( m_editAlbumId, 2, 2, 1, 3 );
+
+ grid->addWidget( labelVolumeCount, 3, 0 );
+ grid->addWidget( m_spinVolumeCount, 3, 1 );
+ grid->addWidget( labelVolumeNumber, 3, 2 );
+ grid->addWidget( m_spinVolumeNumber, 3, 3 );
+
+ grid->addWidget( labelPublisher, 4, 0 );
+ grid->addMultiCellWidget( m_editPublisher, 4, 4, 1, 3 );
+
+ grid->addMultiCellWidget( line, 5, 5, 0, 3 );
+
+ grid->addWidget( labelSystemId, 6, 0 );
+ grid->addMultiCellWidget( labelInfoSystemId, 6, 6, 1, 3 );
+ grid->addWidget( labelApplicationId, 7, 0 );
+ grid->addMultiCellWidget( labelInfoApplicationId, 7, 7, 1, 3 );
+
+ // grid->addRowSpacing( 5, 15 );
+ grid->setRowStretch( 8, 1 );
+
+ // buddies
+ labelVolumeId->setBuddy( m_editVolumeId );
+ labelPublisher->setBuddy( m_editPublisher );
+ labelAlbumId->setBuddy( m_editAlbumId );
+
+ labelVolumeCount->setBuddy( m_spinVolumeCount );
+ labelVolumeNumber->setBuddy( m_spinVolumeNumber );
+
+ // tab order
+ setTabOrder( m_editVolumeId, m_editAlbumId );
+ setTabOrder( m_editAlbumId, m_spinVolumeCount );
+ setTabOrder( m_spinVolumeCount, m_spinVolumeNumber );
+ setTabOrder( m_spinVolumeNumber, m_editPublisher );
+
+ addPage( w, i18n( "Volume Descriptor" ) );
+}
+
+
+void K3bVcdBurnDialog::slotStartClicked()
+{
+
+ if ( QFile::exists( vcdDoc() ->vcdImage() ) ) {
+ if ( KMessageBox::warningContinueCancel( this, i18n( "Do you want to overwrite %1" ).arg( vcdDoc() ->vcdImage() ), i18n( "File Exists" ), i18n("Overwrite") )
+ != KMessageBox::Continue )
+ return ;
+ }
+
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+
+void K3bVcdBurnDialog::loadK3bDefaults()
+{
+ K3bVcdOptions o = K3bVcdOptions::defaults();
+
+ m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO );
+ m_checkSimulate->setChecked( false );
+ m_checkRemoveBufferFiles->setChecked( true );
+ m_checkOnlyCreateImage->setChecked( false );
+
+ m_checkAutoDetect->setChecked( o.AutoDetect() );
+ m_groupVcdFormat->setDisabled( o.AutoDetect() );
+
+ m_check2336->setChecked( o.Sector2336() );
+ m_checkNonCompliant->setChecked( o.NonCompliantMode() );
+ m_checkVCD30interpretation->setChecked( o.VCD30interpretation() );
+ m_spinVolumeCount->setValue( o.volumeCount() );
+ m_spinVolumeNumber->setMaxValue( o.volumeCount() );
+ m_spinVolumeNumber->setValue( o.volumeNumber() );
+
+
+ // to not use i18n for this, so user can not use unsupported letters in her language pack
+ if ( m_radioSvcd10->isChecked() ) {
+ m_checkCdiSupport->setEnabled( false );
+ m_checkCdiSupport->setChecked( false );
+ m_checkUpdateScanOffsets->setEnabled( true );
+ m_editVolumeId->setText( "SUPER_VIDEOCD" );
+ } else if ( m_radioHqVcd10->isChecked() ) {
+ m_checkCdiSupport->setEnabled( false );
+ m_checkCdiSupport->setChecked( false );
+ m_checkUpdateScanOffsets->setEnabled( true );
+ m_editVolumeId->setText( "HQ_VIDEOCD" );
+ } else {
+ m_checkCdiSupport->setEnabled( true );
+ m_checkCdiSupport->setChecked( o.CdiSupport() );
+ m_groupCdi->setEnabled( o.CdiSupport() );
+ m_checkUpdateScanOffsets->setEnabled( false );
+ m_editVolumeId->setText( "VIDEOCD" );
+ }
+
+ m_editPublisher->setText( o.publisher() );
+ m_editAlbumId->setText( o.albumId() );
+
+ m_checkPbc->setChecked( o.PbcEnabled() );
+ m_checkSegmentFolder->setChecked( o.SegmentFolder() );
+ m_checkRelaxedAps->setChecked( o.RelaxedAps() );
+ m_checkUpdateScanOffsets->setChecked( o.UpdateScanOffsets() );
+ m_spinRestriction->setValue( o.Restriction() );
+
+ m_checkGaps->setChecked( o.UseGaps() );
+ m_spinPreGapLeadout->setValue( o.PreGapLeadout() );
+ m_spinPreGapTrack->setValue( o.PreGapTrack() );
+ m_spinFrontMarginTrack->setValue( o.FrontMarginTrack() );
+ m_spinRearMarginTrack->setValue( o.RearMarginTrack() );
+ m_spinFrontMarginTrackSVCD->setValue( o.FrontMarginTrackSVCD() );
+ m_spinRearMarginTrackSVCD->setValue( o.RearMarginTrackSVCD() );
+
+ loadDefaultCdiConfig();
+}
+
+void K3bVcdBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ // set VolumeID if empty
+ setVolumeID();
+
+ doc() ->setTempDir( m_tempDirSelectionWidget->tempPath() );
+ doc() ->setOnTheFly( false );
+
+ // save image file & path (.bin)
+ vcdDoc() ->setVcdImage( m_tempDirSelectionWidget->tempPath() + "/" + m_editVolumeId->text() + ".bin" );
+
+ vcdDoc() ->setVcdType( m_groupVcdFormat->id( m_groupVcdFormat->selected() ) );
+
+ vcdDoc() ->vcdOptions() ->setVolumeId( m_editVolumeId->text() );
+ vcdDoc() ->vcdOptions() ->setPublisher( m_editPublisher->text() );
+ vcdDoc() ->vcdOptions() ->setAlbumId( m_editAlbumId->text() );
+
+ vcdDoc() ->vcdOptions() ->setAutoDetect( m_checkAutoDetect->isChecked() );
+ vcdDoc() ->vcdOptions() ->setNonCompliantMode( m_checkNonCompliant->isChecked() );
+ vcdDoc() ->vcdOptions() ->setVCD30interpretation( m_checkVCD30interpretation->isChecked() );
+ vcdDoc() ->vcdOptions() ->setSector2336( m_check2336->isChecked() );
+
+ vcdDoc() ->vcdOptions() ->setCdiSupport( m_checkCdiSupport->isChecked() );
+ // vcdDoc() ->setOnlyCreateImages( m_checkOnlyCreateImage->isChecked() );
+
+ vcdDoc() ->vcdOptions() ->setVolumeNumber( m_spinVolumeNumber->value() );
+ vcdDoc() ->vcdOptions() ->setVolumeCount( m_spinVolumeCount->value() );
+
+ vcdDoc() ->vcdOptions() ->setPbcEnabled( m_checkPbc->isChecked() );
+ if ( m_checkPbc->isChecked() )
+ vcdDoc() -> setPbcTracks();
+
+ vcdDoc() ->vcdOptions() ->setSegmentFolder( m_checkSegmentFolder->isChecked() );
+ vcdDoc() ->vcdOptions() ->setRelaxedAps( m_checkRelaxedAps->isChecked() );
+ vcdDoc() ->vcdOptions() ->setUpdateScanOffsets( m_checkUpdateScanOffsets->isChecked() );
+ vcdDoc() ->vcdOptions() ->setRestriction( m_spinRestriction->value() );
+
+ vcdDoc() ->vcdOptions() ->setUseGaps( m_checkGaps->isChecked() );
+ vcdDoc() ->vcdOptions() ->setPreGapLeadout( m_spinPreGapLeadout->value() );
+ vcdDoc() ->vcdOptions() ->setPreGapTrack( m_spinPreGapTrack->value() );
+ vcdDoc() ->vcdOptions() ->setFrontMarginTrack( m_spinFrontMarginTrack->value() );
+ vcdDoc() ->vcdOptions() ->setRearMarginTrack( m_spinRearMarginTrack->value() );
+ vcdDoc() ->vcdOptions() ->setFrontMarginTrackSVCD( m_spinFrontMarginTrackSVCD->value() );
+ vcdDoc() ->vcdOptions() ->setRearMarginTrackSVCD( m_spinRearMarginTrackSVCD->value() );
+
+ if ( m_editCdiCfg->edited() )
+ saveCdiConfig();
+}
+
+
+void K3bVcdBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ m_checkNonCompliant->setEnabled( false );
+ m_checkVCD30interpretation->setEnabled( false );
+
+ // read vcdType
+ switch ( ( ( K3bVcdDoc* ) doc() ) ->vcdType() ) {
+ case K3bVcdDoc::VCD11:
+ m_radioVcd11->setChecked( true );
+ break;
+ case K3bVcdDoc::VCD20:
+ m_radioVcd20->setChecked( true );
+ break;
+ case K3bVcdDoc::SVCD10:
+ m_radioSvcd10->setChecked( true );
+ m_checkNonCompliant->setEnabled( true );
+ m_checkVCD30interpretation->setEnabled( true );
+ break;
+ case K3bVcdDoc::HQVCD:
+ m_radioHqVcd10->setChecked( true );
+ break;
+ default:
+ m_radioVcd20->setChecked( true );
+ break;
+ }
+
+ m_spinVolumeCount->setValue( vcdDoc() ->vcdOptions() ->volumeCount() );
+ m_spinVolumeNumber->setMaxValue( vcdDoc() ->vcdOptions() ->volumeCount() );
+ m_spinVolumeNumber->setValue( vcdDoc() ->vcdOptions() ->volumeNumber() );
+
+ m_checkAutoDetect->setChecked( vcdDoc() ->vcdOptions() ->AutoDetect() );
+ m_groupVcdFormat->setDisabled( vcdDoc() ->vcdOptions() ->AutoDetect() );
+
+ m_check2336->setChecked( vcdDoc() ->vcdOptions() ->Sector2336() );
+
+ m_checkCdiSupport->setEnabled( false );
+ m_checkCdiSupport->setChecked( false );
+ m_groupCdi->setEnabled( false );
+
+ if ( m_radioSvcd10->isChecked() ) {
+ m_checkNonCompliant->setChecked( vcdDoc() ->vcdOptions() ->NonCompliantMode() );
+ m_checkUpdateScanOffsets->setEnabled( true );
+ m_checkVCD30interpretation->setChecked( vcdDoc() ->vcdOptions() ->VCD30interpretation() );
+ } else if ( m_radioHqVcd10->isChecked() ) {
+ // NonCompliant only for SVCD
+ m_checkNonCompliant->setChecked( false );
+ m_checkNonCompliant->setEnabled( false );
+ m_checkUpdateScanOffsets->setEnabled( false );
+ m_checkVCD30interpretation->setChecked( false );
+ m_checkVCD30interpretation->setEnabled( false );
+ } else {
+ // NonCompliant only for SVCD
+ m_checkNonCompliant->setChecked( false );
+ m_checkNonCompliant->setEnabled( false );
+ m_checkVCD30interpretation->setChecked( false );
+ m_checkUpdateScanOffsets->setEnabled( false );
+ m_checkVCD30interpretation->setEnabled( false );
+ // CD-I only for VCD and CD-i application was found :)
+ if ( vcdDoc() ->vcdOptions() ->checkCdiFiles() ) {
+ m_checkCdiSupport->setEnabled( true );
+ m_checkCdiSupport->setChecked( vcdDoc() ->vcdOptions() ->CdiSupport() );
+ }
+ }
+
+ // set VolumeID if empty
+ setVolumeID();
+ // m_editVolumeId->setText( vcdDoc() ->vcdOptions() ->volumeId() );
+ m_editPublisher->setText( vcdDoc() ->vcdOptions() ->publisher() );
+ m_editAlbumId->setText( vcdDoc() ->vcdOptions() ->albumId() );
+
+ m_checkPbc->setChecked( vcdDoc() ->vcdOptions() ->PbcEnabled() );
+ m_checkSegmentFolder->setChecked( vcdDoc() ->vcdOptions() ->SegmentFolder() );
+ m_checkRelaxedAps->setChecked( vcdDoc() ->vcdOptions() ->RelaxedAps() );
+ m_checkUpdateScanOffsets->setChecked( vcdDoc() ->vcdOptions() ->UpdateScanOffsets() );
+ m_spinRestriction->setValue( vcdDoc() ->vcdOptions() ->Restriction() );
+
+ m_checkGaps->setChecked( vcdDoc() ->vcdOptions() ->UseGaps() );
+ slotGapsChecked( m_checkGaps->isChecked() ) ;
+ m_spinPreGapLeadout->setValue( vcdDoc() ->vcdOptions() ->PreGapLeadout() );
+ m_spinPreGapTrack->setValue( vcdDoc() ->vcdOptions() ->PreGapTrack() );
+ m_spinFrontMarginTrack->setValue( vcdDoc() ->vcdOptions() ->FrontMarginTrack() );
+ m_spinRearMarginTrack->setValue( vcdDoc() ->vcdOptions() ->RearMarginTrack() );
+ m_spinFrontMarginTrackSVCD->setValue( vcdDoc() ->vcdOptions() ->FrontMarginTrackSVCD() );
+ m_spinRearMarginTrackSVCD->setValue( vcdDoc() ->vcdOptions() ->RearMarginTrackSVCD() );
+
+ if ( !doc() ->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( doc() ->tempDir() );
+
+ loadCdiConfig();
+}
+
+void K3bVcdBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults( c );
+
+ K3bVcdOptions o = K3bVcdOptions::load( c );
+
+ m_checkAutoDetect->setChecked( o.AutoDetect() );
+ m_check2336->setChecked( o.Sector2336() );
+
+ m_checkCdiSupport->setChecked( false );
+ m_checkCdiSupport->setEnabled( false );
+ m_groupCdi->setEnabled( false );
+
+ if ( m_radioSvcd10->isChecked() ) {
+ m_checkNonCompliant->setChecked( o.NonCompliantMode() );
+ m_checkVCD30interpretation->setChecked( o.VCD30interpretation() );
+ } else {
+ m_checkNonCompliant->setChecked( false );
+ m_checkNonCompliant->setEnabled( false );
+ m_checkVCD30interpretation->setChecked( false );
+ m_checkVCD30interpretation->setEnabled( false );
+ if ( vcdDoc() ->vcdOptions() ->checkCdiFiles() ) {
+ m_checkCdiSupport->setEnabled( true );
+ m_checkCdiSupport->setChecked( o.CdiSupport() );
+ }
+ }
+
+ m_spinVolumeCount->setValue( o.volumeCount() );
+ m_spinVolumeNumber->setMaxValue( o.volumeCount() );
+ m_spinVolumeNumber->setValue( o.volumeNumber() );
+
+ m_editVolumeId->setText( o.volumeId() );
+ m_editPublisher->setText( o.publisher() );
+ m_editAlbumId->setText( o.albumId() );
+ m_checkPbc->setChecked( o.PbcEnabled() );
+ m_checkSegmentFolder->setChecked( o.SegmentFolder() );
+ m_checkRelaxedAps->setChecked( o.RelaxedAps() );
+ m_checkUpdateScanOffsets->setChecked( o.UpdateScanOffsets() );
+ m_spinRestriction->setValue( o.Restriction() );
+
+ m_checkGaps->setChecked( o.UseGaps() );
+ m_spinPreGapLeadout->setValue( o.PreGapLeadout() );
+ m_spinPreGapTrack->setValue( o.PreGapTrack() );
+ m_spinFrontMarginTrack->setValue( o.FrontMarginTrack() );
+ m_spinRearMarginTrack->setValue( o.RearMarginTrack() );
+ m_spinFrontMarginTrackSVCD->setValue( o.FrontMarginTrackSVCD() );
+ m_spinRearMarginTrackSVCD->setValue( o.RearMarginTrackSVCD() );
+
+ loadCdiConfig();
+}
+
+
+void K3bVcdBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults( c );
+
+ K3bVcdOptions o;
+
+ o.setVolumeId( m_editVolumeId->text() );
+ o.setPublisher( m_editPublisher->text() );
+ o.setAlbumId( m_editAlbumId->text() );
+ o.setAutoDetect( m_checkAutoDetect->isChecked() );
+ o.setNonCompliantMode( m_checkNonCompliant->isChecked() );
+ o.setVCD30interpretation( m_checkVCD30interpretation->isChecked() );
+ o.setSector2336( m_check2336->isChecked() );
+ o.setVolumeCount( m_spinVolumeCount->value() );
+ o.setVolumeNumber( m_spinVolumeNumber->value() );
+ o.setCdiSupport( m_checkCdiSupport->isChecked() );
+ o.setPbcEnabled( m_checkPbc->isChecked() );
+ o.setSegmentFolder( m_checkSegmentFolder->isChecked() );
+ o.setRelaxedAps( m_checkRelaxedAps->isChecked() );
+ o.setUpdateScanOffsets( m_checkUpdateScanOffsets->isChecked() );
+ o.setRestriction( m_spinRestriction->value() );
+ o.setUseGaps( m_checkGaps->isChecked() );
+ o.setPreGapLeadout( m_spinPreGapLeadout->value() );
+ o.setPreGapTrack( m_spinPreGapTrack->value() );
+ o.setFrontMarginTrack( m_spinFrontMarginTrack->value() );
+ o.setRearMarginTrack( m_spinRearMarginTrack->value() );
+ o.setFrontMarginTrackSVCD( m_spinFrontMarginTrackSVCD->value() );
+ o.setRearMarginTrackSVCD( m_spinRearMarginTrackSVCD->value() );
+
+ o.save( c );
+
+ saveCdiConfig();
+}
+
+void K3bVcdBurnDialog::saveCdiConfig()
+{
+
+ QString filename = locateLocal( "appdata", "cdi/cdi_vcd.cfg" );
+ if ( QFile::exists( filename ) )
+ QFile::remove
+ ( filename );
+
+ QFile cdi( filename );
+ if ( !cdi.open( IO_WriteOnly ) )
+ return ;
+
+ QTextStream s( &cdi );
+ int i = m_editCdiCfg->numLines();
+
+ for ( int j = 0; j < i; j++ )
+ s << QString( "%1" ).arg( m_editCdiCfg->textLine( j ) ) << "\n";
+
+ cdi.close();
+
+ m_editCdiCfg->setEdited( false );
+}
+
+void K3bVcdBurnDialog::loadCdiConfig()
+{
+ QString filename = locateLocal( "appdata", "cdi/cdi_vcd.cfg" );
+ if ( QFile::exists( filename ) ) {
+ QFile cdi( filename );
+ if ( !cdi.open( IO_ReadOnly ) ) {
+ loadDefaultCdiConfig();
+ return ;
+ }
+
+ QTextStream s( &cdi );
+
+ m_editCdiCfg->clear();
+
+ while ( !s.atEnd() )
+ m_editCdiCfg->insertLine( s.readLine() );
+
+ cdi.close();
+ m_editCdiCfg->setEdited( false );
+ m_editCdiCfg->setCursorPosition( 0, 0, false );
+ m_groupCdi->setEnabled( m_checkCdiSupport->isChecked() );
+ } else
+ loadDefaultCdiConfig();
+
+}
+
+void K3bVcdBurnDialog::loadDefaultCdiConfig()
+{
+ QString filename = locate( "data", "k3b/cdi/cdi_vcd.cfg" );
+ if ( QFile::exists( filename ) ) {
+ QFile cdi( filename );
+ if ( !cdi.open( IO_ReadOnly ) ) {
+ m_checkCdiSupport->setChecked( false );
+ m_checkCdiSupport->setEnabled( false );
+ return ;
+ }
+
+ QTextStream s( &cdi );
+
+ m_editCdiCfg->clear();
+
+ while ( !s.atEnd() )
+ m_editCdiCfg->insertLine( s.readLine() );
+
+ cdi.close();
+ m_editCdiCfg->setEdited( false );
+ m_editCdiCfg->setCursorPosition( 0, 0, false );
+ m_groupCdi->setEnabled( m_checkCdiSupport->isChecked() );
+ }
+}
+
+void K3bVcdBurnDialog::setVolumeID()
+{
+ if ( m_editVolumeId->text().length() < 1 ) {
+ if ( m_radioSvcd10->isChecked() )
+ m_editVolumeId->setText( "SUPER_VIDEOCD" );
+ else if ( m_radioHqVcd10->isChecked() )
+ m_editVolumeId->setText( "HQ_VIDEOCD" );
+ else
+ m_editVolumeId->setText( "VIDEOCD" );
+ }
+}
+
+void K3bVcdBurnDialog::slotSpinVolumeCount()
+{
+ m_spinVolumeNumber->setMaxValue( m_spinVolumeCount->value() );
+}
+
+void K3bVcdBurnDialog::slotVcdTypeClicked( int i )
+{
+
+ switch ( i ) {
+ case 0:
+ // vcd 1.1 no support for version 3.x.
+ // v4 work also for vcd 1.1 but without CD-i menus.
+ // Do anybody use vcd 1.1 with cd-i????
+ m_checkCdiSupport->setEnabled( vcdDoc() ->vcdOptions() ->checkCdiFiles() );
+ m_checkCdiSupport->setChecked( false );
+
+ m_checkNonCompliant->setEnabled( false );
+ m_checkNonCompliant->setChecked( false );
+ m_checkVCD30interpretation->setEnabled( false );
+ m_checkVCD30interpretation->setChecked( false );
+ m_checkUpdateScanOffsets->setEnabled( false );
+ m_checkUpdateScanOffsets->setChecked( false );
+ break;
+ case 1:
+ //vcd 2.0
+ m_checkCdiSupport->setEnabled( vcdDoc() ->vcdOptions() ->checkCdiFiles() );
+ m_groupCdi->setEnabled( m_checkCdiSupport->isChecked() );
+
+ m_checkNonCompliant->setEnabled( false );
+ m_checkNonCompliant->setChecked( false );
+ m_checkVCD30interpretation->setEnabled( false );
+ m_checkVCD30interpretation->setChecked( false );
+ m_checkUpdateScanOffsets->setEnabled( false );
+ m_checkUpdateScanOffsets->setChecked( false );
+ break;
+ case 2:
+ //svcd 1.0
+ m_checkCdiSupport->setEnabled( false );
+ m_checkCdiSupport->setChecked( false );
+ m_groupCdi->setEnabled( false );
+
+ m_checkNonCompliant->setEnabled( true );
+ m_checkVCD30interpretation->setEnabled( true );
+ m_checkUpdateScanOffsets->setEnabled( true );
+ break;
+ case 3:
+ //hqvcd 1.0
+ m_checkCdiSupport->setEnabled( false );
+ m_checkCdiSupport->setChecked( false );
+ m_groupCdi->setEnabled( false );
+
+ m_checkNonCompliant->setEnabled( false );
+ m_checkNonCompliant->setChecked( false );
+ m_checkVCD30interpretation->setEnabled( false );
+ m_checkVCD30interpretation->setChecked( false );
+ m_checkUpdateScanOffsets->setEnabled( true );
+ break;
+ }
+
+ MarginChecked( m_checkGaps->isChecked() );
+
+}
+
+void K3bVcdBurnDialog::slotGapsChecked( bool b )
+{
+ m_labelPreGapLeadout->setEnabled( b );
+ m_spinPreGapLeadout->setEnabled( b );
+ m_labelPreGapTrack->setEnabled( b );
+ m_spinPreGapTrack->setEnabled( b );
+ MarginChecked( b );
+}
+
+void K3bVcdBurnDialog::MarginChecked( bool b )
+{
+ if ( m_radioSvcd10->isChecked() || m_radioHqVcd10->isChecked() ) {
+ m_spinFrontMarginTrack->setHidden( true );
+ m_spinFrontMarginTrackSVCD->setHidden( false );
+ m_spinRearMarginTrack->setHidden( true );
+ m_spinRearMarginTrackSVCD->setHidden( false );
+ } else {
+ m_spinFrontMarginTrack->setHidden( false );
+ m_spinFrontMarginTrackSVCD->setHidden( true );
+ m_spinRearMarginTrack->setHidden( false );
+ m_spinRearMarginTrackSVCD->setHidden( true );
+ }
+
+ m_labelFrontMarginTrack->setEnabled( b );
+ m_spinFrontMarginTrack->setEnabled( b );
+ m_spinFrontMarginTrackSVCD->setEnabled( b );
+
+ m_labelRearMarginTrack->setEnabled( b );
+ m_spinRearMarginTrack->setEnabled( b );
+ m_spinRearMarginTrackSVCD->setEnabled( b );
+
+}
+
+void K3bVcdBurnDialog::slotCdiSupportChecked( bool b )
+{
+ m_groupCdi->setEnabled( b );
+}
+
+void K3bVcdBurnDialog::slotAutoDetect( bool b )
+{
+ if ( b ) {
+ m_groupVcdFormat->setButton( vcdDoc() ->vcdOptions() ->mpegVersion() );
+ slotVcdTypeClicked( vcdDoc() ->vcdOptions() ->mpegVersion() );
+ }
+
+ m_groupVcdFormat->setDisabled( b );
+
+}
+
+void K3bVcdBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ m_writingModeWidget->setSupportedModes( K3b::DAO );
+ m_checkRemoveBufferFiles->setDisabled( m_checkOnlyCreateImage->isChecked() );
+}
+
+#include "k3bvcdburndialog.moc"
diff --git a/src/projects/k3bvcdburndialog.h b/src/projects/k3bvcdburndialog.h
new file mode 100644
index 0000000..6f199a9
--- /dev/null
+++ b/src/projects/k3bvcdburndialog.h
@@ -0,0 +1,142 @@
+/*
+*
+* $Id: k3bvcdburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#ifndef K3BVCDBURNDIALOG_H
+#define K3BVCDBURNDIALOG_H
+
+#include "k3bprojectburndialog.h"
+#include <qmultilineedit.h>
+
+class QCheckBox;
+class QGroupBox;
+class QButtonGroup;
+class QSpinBox;
+class QRadioButton;
+class QLabel;
+class QLineEdit;
+class QMultiLineEdit;
+class QToolButton;
+class K3bWriterSelectionWidget;
+class K3bTempDirSelectionWidget;
+class K3bVcdDoc;
+class K3bVcdOptions;
+
+class K3bVcdBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bVcdBurnDialog( K3bVcdDoc* doc, QWidget *parent = 0, const char *name = 0, bool modal = true );
+ ~K3bVcdBurnDialog();
+
+ K3bVcdDoc* vcdDoc() const
+ {
+ return m_vcdDoc;
+ }
+
+ protected:
+ void setupAdvancedTab();
+ void setupVideoCdTab();
+ void setupLabelTab();
+ void saveSettings();
+ void readSettings();
+
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+
+ // -----------------------------------------------------------
+ // the video-cd-tab
+ // -----------------------------------------------------------
+
+ QButtonGroup* m_groupVcdFormat;
+ QRadioButton* m_radioVcd11;
+ QRadioButton* m_radioVcd20;
+ QRadioButton* m_radioSvcd10;
+ QRadioButton* m_radioHqVcd10;
+
+ QGroupBox* m_groupOptions;
+ QCheckBox* m_checkAutoDetect;
+ QCheckBox* m_checkNonCompliant;
+ QCheckBox* m_checkVCD30interpretation;
+ QCheckBox* m_check2336;
+
+ // CD-i
+ QGroupBox* m_groupCdi;
+ QCheckBox* m_checkCdiSupport;
+ QMultiLineEdit* m_editCdiCfg;
+
+
+ // -----------------------------------------------------------
+ // the video-label-tab
+ // -----------------------------------------------------------
+
+ QLineEdit* m_editVolumeId;
+ QLineEdit* m_editPublisher;
+ QLineEdit* m_editAlbumId;
+
+ QSpinBox* m_spinVolumeCount;
+ QSpinBox* m_spinVolumeNumber;
+
+ // -----------------------------------------------------------
+ // the advanced-tab
+ // -----------------------------------------------------------
+
+ QGroupBox* m_groupGeneric;
+ QGroupBox* m_groupGaps;
+ QGroupBox* m_groupMisc;
+
+ QCheckBox* m_checkPbc;
+ QCheckBox* m_checkSegmentFolder;
+ QCheckBox* m_checkRelaxedAps;
+ QCheckBox* m_checkUpdateScanOffsets;
+ QCheckBox* m_checkGaps;
+
+ QSpinBox* m_spinRestriction;
+ QSpinBox* m_spinPreGapLeadout;
+ QSpinBox* m_spinPreGapTrack;
+ QSpinBox* m_spinFrontMarginTrack;
+ QSpinBox* m_spinRearMarginTrack;
+ QSpinBox* m_spinFrontMarginTrackSVCD;
+ QSpinBox* m_spinRearMarginTrackSVCD;
+
+ QLabel* m_labelRestriction;
+ QLabel* m_labelPreGapLeadout;
+ QLabel* m_labelPreGapTrack;
+ QLabel* m_labelFrontMarginTrack;
+ QLabel* m_labelRearMarginTrack;
+
+ // -----------------------------------------------------------
+
+ private:
+ K3bVcdDoc* m_vcdDoc;
+ void setVolumeID( );
+ void MarginChecked( bool );
+ void saveCdiConfig();
+ void loadCdiConfig();
+ void loadDefaultCdiConfig();
+ void toggleAll();
+
+ protected slots:
+ void slotStartClicked();
+
+ void slotGapsChecked( bool );
+ void slotSpinVolumeCount();
+ void slotVcdTypeClicked( int );
+ void slotCdiSupportChecked( bool );
+ void slotAutoDetect( bool );
+};
+
+#endif
diff --git a/src/projects/k3bvcdlistview.cpp b/src/projects/k3bvcdlistview.cpp
new file mode 100644
index 0000000..f61863b
--- /dev/null
+++ b/src/projects/k3bvcdlistview.cpp
@@ -0,0 +1,271 @@
+/*
+*
+* $Id: k3bvcdlistview.cpp 628165 2007-01-29 11:01:22Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#include <qheader.h>
+#include <qtimer.h>
+#include <qdragobject.h>
+#include <qpoint.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qpainter.h>
+#include <qfontmetrics.h>
+
+#include <kiconloader.h>
+#include <kurl.h>
+#include <kurldrag.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kdialog.h>
+
+// K3b Includes
+#include "k3bvcdlistview.h"
+#include "k3bvcdlistviewitem.h"
+#include "k3bvcdtrack.h"
+#include "k3bvcdtrackdialog.h"
+#include "k3bvcddoc.h"
+#include <k3bview.h>
+
+K3bVcdListView::K3bVcdListView( K3bView* view, K3bVcdDoc* doc, QWidget *parent, const char *name )
+ : K3bListView( parent, name ), m_doc( doc ), m_view( view )
+{
+ setAcceptDrops( true );
+ setDropVisualizer( true );
+ setAllColumnsShowFocus( true );
+ setDragEnabled( true );
+ setSelectionModeExt( KListView::Extended );
+ setItemsMovable( false );
+
+ setNoItemText( i18n( "Use drag'n'drop to add MPEG video files to the project." ) + "\n"
+ + i18n( "After that press the burn button to write the CD." ) );
+
+ setSorting( 0 );
+
+ setupActions();
+ setupPopupMenu();
+
+ setupColumns();
+ header() ->setClickEnabled( false );
+
+ connect( this, SIGNAL( dropped( KListView*, QDropEvent*, QListViewItem* ) ),
+ this, SLOT( slotDropped( KListView*, QDropEvent*, QListViewItem* ) ) );
+ connect( this, SIGNAL( contextMenu( KListView*, QListViewItem*, const QPoint& ) ),
+ this, SLOT( showPopupMenu( KListView*, QListViewItem*, const QPoint& ) ) );
+ connect( this, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ),
+ this, SLOT( showPropertiesDialog() ) );
+
+ connect( m_doc, SIGNAL( changed() ), this, SLOT( slotUpdateItems() ) );
+ connect( m_doc, SIGNAL( trackRemoved( K3bVcdTrack* ) ), this, SLOT( slotTrackRemoved( K3bVcdTrack* ) ) );
+
+ slotUpdateItems();
+}
+
+K3bVcdListView::~K3bVcdListView()
+{}
+
+void K3bVcdListView::setupColumns()
+{
+ addColumn( i18n( "No." ) );
+ addColumn( i18n( "Title" ) );
+ addColumn( i18n( "Type" ) );
+ addColumn( i18n( "Resolution" ) );
+ addColumn( i18n( "High Resolution" ) );
+ addColumn( i18n( "Framerate" ) );
+ addColumn( i18n( "Muxrate" ) );
+ addColumn( i18n( "Duration" ) );
+ addColumn( i18n( "File Size" ) );
+ addColumn( i18n( "Filename" ) );
+}
+
+
+void K3bVcdListView::setupActions()
+{
+ m_actionCollection = new KActionCollection( this );
+ m_actionProperties = new KAction( i18n( "Properties" ), "misc", 0, this, SLOT( showPropertiesDialog() ), actionCollection() );
+ m_actionRemove = new KAction( i18n( "Remove" ), "editdelete", Key_Delete, this, SLOT( slotRemoveTracks() ), actionCollection() );
+
+ // disabled by default
+ m_actionRemove->setEnabled( false );
+}
+
+
+void K3bVcdListView::setupPopupMenu()
+{
+ m_popupMenu = new KPopupMenu( this, "VcdViewPopupMenu" );
+ m_actionRemove->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ m_actionProperties->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ m_view->actionCollection() ->action( "project_burn" ) ->plug( m_popupMenu );
+}
+
+
+bool K3bVcdListView::acceptDrag( QDropEvent* e ) const
+{
+ // the first is for built-in item moving, the second for dropping urls
+ return ( KListView::acceptDrag( e ) || KURLDrag::canDecode( e ) );
+}
+
+
+QDragObject* K3bVcdListView::dragObject()
+{
+ QPtrList<QListViewItem> list = selectedItems();
+
+ if ( list.isEmpty() )
+ return 0;
+
+ QPtrListIterator<QListViewItem> it( list );
+ KURL::List urls;
+
+ for ( ; it.current(); ++it )
+ urls.append( KURL( ( ( K3bVcdListViewItem* ) it.current() ) ->vcdTrack() ->absPath() ) );
+
+ return KURLDrag::newDrag( urls, viewport() );
+}
+
+
+void K3bVcdListView::slotDropped( KListView*, QDropEvent* e, QListViewItem* after )
+{
+ if ( !e->isAccepted() )
+ return ;
+
+ int pos;
+ if ( after == 0L )
+ pos = 0;
+ else
+ pos = ( ( K3bVcdListViewItem* ) after ) ->vcdTrack() ->index() + 1;
+
+ if ( e->source() == viewport() ) {
+ QPtrList<QListViewItem> sel = selectedItems();
+ QPtrListIterator<QListViewItem> it( sel );
+ K3bVcdTrack* trackAfter = ( after ? ( ( K3bVcdListViewItem* ) after ) ->vcdTrack() : 0 );
+ while ( it.current() ) {
+ K3bVcdTrack * track = ( ( K3bVcdListViewItem* ) it.current() ) ->vcdTrack();
+ m_doc->moveTrack( track, trackAfter );
+ trackAfter = track;
+ ++it;
+ }
+ } else {
+ KURL::List urls;
+ KURLDrag::decode( e, urls );
+
+ m_doc->addTracks( urls, pos );
+ }
+
+ // now grab that focus
+ setFocus();
+}
+
+
+void K3bVcdListView::insertItem( QListViewItem* item )
+{
+ KListView::insertItem( item );
+
+ // make sure at least one item is selected
+ if ( selectedItems().isEmpty() ) {
+ setSelected( firstChild(), true );
+ }
+}
+
+void K3bVcdListView::showPopupMenu( KListView*, QListViewItem* _item, const QPoint& _point )
+{
+ if ( _item ) {
+ m_actionRemove->setEnabled( true );
+ } else {
+ m_actionRemove->setEnabled( false );
+ }
+
+ m_popupMenu->popup( _point );
+}
+
+void K3bVcdListView::showPropertiesDialog()
+{
+ QPtrList<K3bVcdTrack> selected = selectedTracks();
+ if ( !selected.isEmpty() && selected.count() == 1 ) {
+ QPtrList<K3bVcdTrack> tracks = *m_doc->tracks();
+ K3bVcdTrackDialog d( m_doc, tracks, selected, this );
+ if ( d.exec() ) {
+ repaint();
+ }
+ } else {
+ m_view->slotProperties();
+ }
+}
+
+QPtrList<K3bVcdTrack> K3bVcdListView::selectedTracks()
+{
+ QPtrList<K3bVcdTrack> selectedTracks;
+ QPtrList<QListViewItem> selectedVI( selectedItems() );
+ for ( QListViewItem * item = selectedVI.first(); item != 0; item = selectedVI.next() ) {
+ K3bVcdListViewItem * vcdItem = dynamic_cast<K3bVcdListViewItem*>( item );
+ if ( vcdItem ) {
+ selectedTracks.append( vcdItem->vcdTrack() );
+ }
+ }
+
+ return selectedTracks;
+}
+
+
+void K3bVcdListView::slotRemoveTracks()
+{
+ QPtrList<K3bVcdTrack> selected = selectedTracks();
+ if ( !selected.isEmpty() ) {
+
+ for ( K3bVcdTrack * track = selected.first(); track != 0; track = selected.next() ) {
+ m_doc->removeTrack( track );
+ }
+ }
+
+ if ( m_doc->numOfTracks() == 0 ) {
+ m_actionRemove->setEnabled( false );
+ }
+}
+
+
+void K3bVcdListView::slotTrackRemoved( K3bVcdTrack* track )
+{
+ QListViewItem * viewItem = m_itemMap[ track ];
+ m_itemMap.remove( track );
+ delete viewItem;
+}
+
+
+void K3bVcdListView::slotUpdateItems()
+{
+ // iterate through all doc-tracks and test if we have a listItem, if not, create one
+ K3bVcdTrack * track = m_doc->first();
+ K3bVcdTrack* lastTrack = 0;
+ while ( track != 0 ) {
+ if ( !m_itemMap.contains( track ) )
+ m_itemMap.insert( track, new K3bVcdListViewItem( track, this, m_itemMap[ lastTrack ] ) );
+
+ lastTrack = track;
+ track = m_doc->next();
+ }
+
+ if ( m_doc->numOfTracks() > 0 ) {
+ m_actionRemove->setEnabled( true );
+ } else {
+ m_actionRemove->setEnabled( false );
+ }
+
+ sort(); // This is so lame!
+
+ header()->setShown( m_doc->numOfTracks() > 0 );
+}
+
+#include "k3bvcdlistview.moc"
diff --git a/src/projects/k3bvcdlistview.h b/src/projects/k3bvcdlistview.h
new file mode 100644
index 0000000..71d22d7
--- /dev/null
+++ b/src/projects/k3bvcdlistview.h
@@ -0,0 +1,90 @@
+/*
+*
+* $Id: k3bvcdlistview.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#ifndef K3BVCDLISTVIEW_H
+#define K3BVCDLISTVIEW_H
+
+
+#include <k3blistview.h>
+
+#include <qmap.h>
+
+class QDragEnterEvent;
+class QDragObject;
+class QDropEvent;
+class QTimer;
+class KPopupMenu;
+class KAction;
+class K3bVcdDoc;
+class K3bView;
+class K3bVcdTrack;
+class KActionCollection;
+class K3bVcdListViewItem;
+class QPainter;
+
+
+class K3bVcdListView : public K3bListView
+{
+ Q_OBJECT
+
+ public:
+ K3bVcdListView( K3bView*, K3bVcdDoc*, QWidget *parent = 0, const char *name = 0 );
+ ~K3bVcdListView();
+
+ /**
+ * reimplemented from KListView
+ */
+ void insertItem( QListViewItem* );
+
+ KActionCollection* actionCollection() const
+ {
+ return m_actionCollection;
+ }
+
+ QPtrList<K3bVcdTrack> selectedTracks();
+
+ signals:
+ void lengthReady();
+
+ private:
+ void setupColumns();
+ void setupPopupMenu();
+ void setupActions();
+
+ K3bVcdDoc* m_doc;
+ K3bView* m_view;
+
+ KAction* m_actionProperties;
+ KAction* m_actionRemove;
+ KActionCollection* m_actionCollection;
+
+ KPopupMenu* m_popupMenu;
+
+ QMap<K3bVcdTrack*, K3bVcdListViewItem*> m_itemMap;
+
+ private slots:
+ void slotDropped( KListView*, QDropEvent* e, QListViewItem* after );
+ void slotUpdateItems();
+ void showPopupMenu( KListView*, QListViewItem* item, const QPoint& );
+ void showPropertiesDialog();
+ void slotRemoveTracks();
+ void slotTrackRemoved( K3bVcdTrack* );
+
+ protected:
+ bool acceptDrag( QDropEvent* e ) const;
+ QDragObject* dragObject();
+};
+
+#endif
diff --git a/src/projects/k3bvcdlistviewitem.cpp b/src/projects/k3bvcdlistviewitem.cpp
new file mode 100644
index 0000000..02df525
--- /dev/null
+++ b/src/projects/k3bvcdlistviewitem.cpp
@@ -0,0 +1,129 @@
+/*
+*
+* $Id: k3bvcdlistviewitem.cpp 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#include <kio/global.h>
+#include <kiconloader.h>
+
+
+// K3b Includes
+#include "k3bvcdlistviewitem.h"
+#include "k3bvcdtrack.h"
+#include <k3bglobals.h>
+
+K3bVcdListViewItem::K3bVcdListViewItem( K3bVcdTrack* track, K3bListView* parent )
+ : K3bListViewItem( parent ), m_track( track )
+{
+ setEditor( 1, LINE );
+ animate();
+}
+
+K3bVcdListViewItem::K3bVcdListViewItem( K3bVcdTrack* track, K3bListView* parent, QListViewItem* after )
+ : K3bListViewItem( parent, after ), m_track( track )
+{
+ setEditor( 1, LINE );
+ animate();
+}
+
+
+K3bVcdListViewItem::~K3bVcdListViewItem()
+{}
+
+QString K3bVcdListViewItem::text( int i ) const
+{
+ //
+ // We add two spaces after all strings (except the once renamable)
+ // to increase readability
+ //
+
+ switch ( i ) {
+ case 0:
+ return QString::number( m_track->index() + 1 ).rightJustify( 2, ' ' ) + " ";
+ case 1:
+ return m_track->title();
+ case 2:
+ // track mpegtype
+ return m_track->mpegTypeS() + " ";
+ case 3:
+ // track mpegsize
+ return m_track->resolution() + " ";
+ case 4:
+ // track low mpegsize for MPEG1 Stills
+ return m_track->highresolution() + " ";
+ case 5:
+ // track mpegfps
+ return m_track->video_frate() + " ";
+ case 6:
+ // track mpegmbps
+ return QString::number( m_track->muxrate() ) + " ";
+ case 7:
+ // track mpegduration
+ return m_track->duration() + " ";
+ case 8:
+ // track size
+ return KIO::convertSize( m_track->size() ) + " ";
+ case 9:
+ // filename
+ return m_track->fileName();
+
+ default:
+ return KListViewItem::text( i );
+ }
+}
+
+void K3bVcdListViewItem::setText( int col, const QString& text )
+{
+ if ( col == 1 ) {
+ // this is the title field
+ m_track->setTitle( text );
+ }
+
+ KListViewItem::setText( col, text );
+}
+
+
+QString K3bVcdListViewItem::key( int, bool ) const
+{
+ QString num = QString::number( m_track->index() );
+ if ( num.length() == 1 )
+ return "00" + num;
+ else if ( num.length() == 2 )
+ return "0" + num;
+
+ return num;
+}
+
+bool K3bVcdListViewItem::animate()
+{
+ bool animate = false;
+
+ switch ( m_track->mpegType() ) {
+ case 0: // MPEG_MOTION
+ setPixmap( 2, ( SmallIcon( "video" ) ) );
+ break;
+ case 1: // MPEG_STILL
+ setPixmap( 2, ( SmallIcon( "image" ) ) );
+ break;
+ case 2: // MPEG_AUDIO
+ setPixmap( 2, ( SmallIcon( "sound" ) ) );
+ break;
+
+ default:
+ setPixmap( 2, ( SmallIcon( "video" ) ) );
+ break;
+ }
+
+
+ return animate;
+}
diff --git a/src/projects/k3bvcdlistviewitem.h b/src/projects/k3bvcdlistviewitem.h
new file mode 100644
index 0000000..0101850
--- /dev/null
+++ b/src/projects/k3bvcdlistviewitem.h
@@ -0,0 +1,50 @@
+/*
+*
+* $Id: k3bvcdlistviewitem.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#ifndef K3BVCDLISTVIEWITEM_H
+#define K3BVCDLISTVIEWITEM_H
+
+#include <k3blistview.h>
+
+class K3bVcdTrack;
+
+class K3bVcdListViewItem : public K3bListViewItem
+{
+
+ public:
+ K3bVcdListViewItem( K3bVcdTrack* track, K3bListView* parent );
+ K3bVcdListViewItem( K3bVcdTrack* track, K3bListView* parent, QListViewItem* after );
+ ~K3bVcdListViewItem();
+
+ /** reimplemented from QListViewItem */
+ QString text( int i ) const;
+
+ /** reimplemented from QListViewItem */
+ void setText( int col, const QString& text );
+
+ /** reimplemented from QListViewItem */
+ QString key( int column, bool a ) const;
+ bool animate();
+
+ K3bVcdTrack* vcdTrack()
+ {
+ return m_track;
+ }
+
+ private:
+ K3bVcdTrack* m_track;
+};
+
+#endif
diff --git a/src/projects/k3bvcdtrackdialog.cpp b/src/projects/k3bvcdtrackdialog.cpp
new file mode 100644
index 0000000..06588b8
--- /dev/null
+++ b/src/projects/k3bvcdtrackdialog.cpp
@@ -0,0 +1,802 @@
+/*
+*
+* $Id: k3bvcdtrackdialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+// Qt Includes
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qframe.h>
+#include <qgroupbox.h>
+#include <qhbox.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmultilineedit.h>
+#include <qpixmap.h>
+#include <qradiobutton.h>
+#include <qtable.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+// Kde Includes
+#include <kiconloader.h>
+#include <kio/global.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <knuminput.h>
+#include <kurl.h>
+
+// K3b Includes
+#include "k3bvcdtrackdialog.h"
+#include "k3bvcdtrack.h"
+#include <kcutlabel.h>
+#include <k3bmsf.h>
+#include <k3bglobals.h>
+#include <k3bcutcombobox.h>
+
+
+K3bVcdTrackDialog::K3bVcdTrackDialog( K3bVcdDoc* _doc, QPtrList<K3bVcdTrack>& tracks, QPtrList<K3bVcdTrack>& selectedTracks, QWidget* parent, const char* name )
+ : KDialogBase( KDialogBase::Plain, i18n( "Video Track Properties" ), KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply,
+ KDialogBase::Ok, parent, name )
+{
+ prepareGui();
+
+ setupPbcTab();
+ setupPbcKeyTab();
+ setupVideoTab();
+ setupAudioTab();
+
+ m_tracks = tracks;
+ m_selectedTracks = selectedTracks;
+ m_vcdDoc = _doc;
+ m_numkeysmap.clear();
+
+ if ( !m_selectedTracks.isEmpty() ) {
+
+ K3bVcdTrack * selectedTrack = m_selectedTracks.first();
+
+ m_displayFileName->setText( selectedTrack->fileName() );
+ m_displayLength->setText( selectedTrack->duration() );
+ m_displaySize->setText( KIO::convertSize( selectedTrack->size() ) );
+ m_muxrate->setText( i18n( "%1 bit/s" ).arg( selectedTrack->muxrate() ) );
+
+ if ( selectedTrack->isSegment() )
+ m_labelMimeType->setPixmap( SmallIcon( "image", KIcon::SizeMedium ) );
+ else
+ m_labelMimeType->setPixmap( SmallIcon( "video", KIcon::SizeMedium ) );
+
+ fillGui();
+ }
+}
+
+K3bVcdTrackDialog::~K3bVcdTrackDialog()
+{}
+
+void K3bVcdTrackDialog::slotOk()
+{
+ slotApply();
+ done( 0 );
+}
+
+void K3bVcdTrackDialog::setPbcTrack( K3bVcdTrack* selected, K3bCutComboBox* box, int which )
+{
+ // TODO: Unset Userdefined on default settings
+ kdDebug() << QString( "K3bVcdTrackDialog::setPbcTrack: currentItem = %1, count = %2" ).arg( box->currentItem() ).arg( m_tracks.count() ) << endl;
+
+ int count = m_tracks.count();
+
+ if ( selected->getPbcTrack( which ) == m_tracks.at( box->currentItem() ) ) {
+ if ( selected->getNonPbcTrack( which ) == ( int ) ( box->currentItem() - count ) ) {
+ kdDebug() << "K3bVcdTrackDialog::setPbcTrack: not changed, return" << endl;
+ return ;
+ }
+ }
+
+ if ( selected->getPbcTrack( which ) )
+ selected->getPbcTrack( which ) ->delFromRevRefList( selected );
+
+ if ( box->currentItem() > count - 1 ) {
+ selected->setPbcTrack( which );
+ selected->setPbcNonTrack( which, box->currentItem() - count );
+ } else {
+ selected->setPbcTrack( which, m_tracks.at( box->currentItem() ) );
+ m_tracks.at( box->currentItem() ) ->addToRevRefList( selected );
+ }
+
+ selected->setUserDefined( which, true );
+}
+
+void K3bVcdTrackDialog::slotApply()
+{
+ // track set
+ K3bVcdTrack * selectedTrack = m_selectedTracks.first();
+
+ setPbcTrack( selectedTrack, m_pbc_previous, K3bVcdTrack::PREVIOUS );
+ setPbcTrack( selectedTrack, m_pbc_next, K3bVcdTrack::NEXT );
+ setPbcTrack( selectedTrack, m_pbc_return, K3bVcdTrack::RETURN );
+ setPbcTrack( selectedTrack, m_pbc_default, K3bVcdTrack::DEFAULT );
+ setPbcTrack( selectedTrack, m_comboAfterTimeout, K3bVcdTrack::AFTERTIMEOUT );
+
+ selectedTrack->setPlayTime( m_spin_times->value() );
+ selectedTrack->setWaitTime( m_spin_waittime->value() );
+ selectedTrack->setReactivity( m_check_reactivity->isChecked() );
+ selectedTrack->setPbcNumKeys( m_check_usekeys->isChecked() );
+ selectedTrack->setPbcNumKeysUserdefined( m_check_overwritekeys->isChecked() );
+
+ // global set
+ VcdOptions() ->setPbcEnabled( m_check_pbc->isChecked() );
+
+ // define numeric keys
+ selectedTrack->delDefinedNumKey();
+
+ if ( m_check_overwritekeys->isChecked() ) {
+ QListViewItemIterator it( m_list_keys );
+ int skiped = 0;
+ int startkey = 0;
+ while ( it.current() ) {
+ if ( it.current() ->text( 1 ).isEmpty() ) {
+ skiped++;
+ } else {
+
+ if ( startkey > 0 )
+ for ( ; skiped > 0; skiped-- )
+ kdDebug() << "Key " << it.current() ->text( 0 ).toInt() - skiped << " Playing: " << displayName( selectedTrack ) << " (normaly none)" << endl;
+ else {
+ skiped = 0;
+ startkey = it.current() ->text( 0 ).toInt();
+ }
+
+ QMap<QString, K3bVcdTrack*>::Iterator mit;
+ mit = m_numkeysmap.find( it.current() ->text( 1 ) );
+ if ( mit != m_numkeysmap.end() )
+ if ( mit.data() ) {
+ selectedTrack->setDefinedNumKey( it.current() ->text( 0 ).toInt(), mit.data() );
+ kdDebug() << "Key " << it.current() ->text( 0 ).toInt() << " Playing: " << it.current() ->text( 1 ) << "Track: " << mit.data() << endl;
+ } else {
+ selectedTrack->setDefinedNumKey( it.current() ->text( 0 ).toInt(), 0L );
+ kdDebug() << "Key " << it.current() ->text( 0 ).toInt() << " Playing: " << it.current() ->text( 1 ) << endl;
+ }
+ }
+ ++it;
+ }
+ } else {
+ selectedTrack->setDefinedNumKey( 1, selectedTrack );
+ kdDebug() << "Key 1" << " Playing: (default) " << displayName( selectedTrack ) << "Track: " << selectedTrack << endl;
+ }
+}
+
+void K3bVcdTrackDialog::fillGui()
+{
+ K3bVcdTrack * selectedTrack = m_selectedTracks.first();
+
+ m_mpegver_video->setText( selectedTrack->mpegTypeS() );
+ m_rate_video->setText( selectedTrack->video_bitrate() );
+ m_chromaformat_video->setText( selectedTrack->video_chroma() );
+ m_format_video->setText( selectedTrack->video_format() );
+ m_highresolution_video->setText( selectedTrack->highresolution() );
+ m_resolution_video->setText( selectedTrack->resolution() );
+
+ m_mpegver_audio->setText( selectedTrack->mpegTypeS( true ) );
+ m_rate_audio->setText( selectedTrack->audio_bitrate() );
+
+ m_sampling_frequency_audio->setText( selectedTrack->audio_sampfreq() );
+ m_mode_audio->setText( selectedTrack->audio_mode() );
+ m_copyright_audio->setText( selectedTrack->audio_copyright() );
+
+ fillPbcGui();
+
+
+ QToolTip::add
+ ( m_pbc_previous, i18n( "May also look like | << on the remote control. " ) );
+ QToolTip::add
+ ( m_pbc_next, i18n( "May also look like >> | on the remote control." ) );
+ QToolTip::add
+ ( m_pbc_return, i18n( "This key may be mapped to the STOP key." ) );
+ QToolTip::add
+ ( m_pbc_default, i18n( "This key is usually mapped to the > or PLAY key." ) );
+ QToolTip::add
+ ( m_comboAfterTimeout, i18n( "Target to be jumped to on time-out of <wait>." ) );
+ QToolTip::add
+ ( m_check_reactivity, i18n( "Delay reactivity of keys." ) );
+ QToolTip::add
+ ( m_check_pbc, i18n( "Playback control, PBC, is available for Video CD 2.0 and Super Video CD 1.0 disc formats." ) );
+ QToolTip::add
+ ( m_check_usekeys, i18n( "Activate the use of numeric keys." ) );
+ QToolTip::add
+ ( m_check_overwritekeys, i18n( "Overwrite default numeric keys." ) );
+ QToolTip::add
+ ( m_list_keys, i18n( "Numeric keys." ) );
+ QToolTip::add
+ ( m_spin_times, i18n( "Times to repeat the playback of 'play track'." ) );
+ QToolTip::add
+ ( m_spin_waittime, i18n( "Time in seconds to wait after playback of 'play track'." ) );
+
+ QWhatsThis::add
+ ( m_comboAfterTimeout, i18n( "<p>Target to be jumped to on time-out of <wait>."
+ "<p>If omitted (and <wait> is not set to an infinite time) one of the targets is selected at random." ) );
+ QWhatsThis::add
+ ( m_check_reactivity, i18n( "<p>When reactivity is set to delayed, it is recommended that the length of the referenced 'play track' is not more than 5 seconds."
+ "<p>The recommended setting for a play item consisting of one still picture and no audio is to loop once and have a delayed reactivity." ) );
+ QWhatsThis::add
+ ( m_check_pbc, i18n( "<p>Playback control, PBC, is available for Video CD 2.0 and Super Video CD 1.0 disc formats."
+ "<p>PBC allows control of the playback of play items and the possibility of interaction with the user through the remote control or some other input device available." ) );
+ QWhatsThis::add
+ ( m_check_usekeys, i18n( "These are actually pseudo keys, representing the numeric keys 0, 1, ..., 9." ) );
+ QWhatsThis::add
+ ( m_check_overwritekeys, i18n( "<p>If numeric keys enabled, you can overwrite the default settings." ) );
+ QWhatsThis::add
+ ( m_spin_times, i18n( "<p>Times to repeat the playback of 'play track'."
+ "<p>The reactivity attribute controls whether the playback of 'play track' is finished, thus delayed, before executing user triggered action or an immediate jump is performed."
+ "<p>After the specified number of repetitions have completed, the <wait> time begins to count down, unless set to an infinite wait time."
+ "<p>If this element is omitted, a default of `1' is used, i.e. the 'play track' will be displayed once." ) );
+ QWhatsThis::add
+ ( m_spin_waittime, i18n( "Time in seconds to wait after playback of 'play track' before triggering the <timeout> action (unless the user triggers some action before time ran up)." ) );
+
+}
+
+void K3bVcdTrackDialog::fillPbcGui()
+{
+ K3bVcdTrack * selectedTrack = m_selectedTracks.first();
+ // add tracktitles to combobox
+ int iPrevious = -1;
+ int iNext = -1;
+ int iReturn = -1;
+ int iDefault = -1;
+ int iAfterTimeOut = -1;
+
+ K3bVcdTrack* track;
+ K3bListViewItem* item;
+
+ m_numkeysmap.insert( "", 0L );
+ m_numkeysmap.insert( displayName( selectedTrack ) , selectedTrack );
+
+ for ( track = m_tracks.first(); track; track = m_tracks.next() ) {
+ QPixmap pm;
+ if ( track->isSegment() )
+ pm = SmallIcon( "image" );
+ else
+ pm = SmallIcon( "video" );
+
+ QString s = displayName( track );
+ if ( track != selectedTrack ) // donot insert selectedTrack, it was as "ItSelf" inserted to the begin of map
+ m_numkeysmap.insert( s, track );
+
+ m_pbc_previous->insertItem( pm, s );
+ if ( track == selectedTrack->getPbcTrack( K3bVcdTrack::PREVIOUS ) )
+ iPrevious = m_pbc_previous->count() - 1;
+
+ m_pbc_next->insertItem( pm, s );
+ if ( track == selectedTrack->getPbcTrack( K3bVcdTrack::NEXT ) )
+ iNext = m_pbc_next->count() - 1;
+
+ m_pbc_return->insertItem( pm, s );
+ if ( track == selectedTrack->getPbcTrack( K3bVcdTrack::RETURN ) )
+ iReturn = m_pbc_return->count() - 1;
+
+ m_pbc_default->insertItem( pm, s );
+ if ( track == selectedTrack->getPbcTrack( K3bVcdTrack::DEFAULT ) )
+ iDefault = m_pbc_default->count() - 1;
+
+ m_comboAfterTimeout->insertItem( pm, s );
+ if ( track == selectedTrack->getPbcTrack( K3bVcdTrack::AFTERTIMEOUT ) )
+ iAfterTimeOut = m_comboAfterTimeout->count() - 1;
+
+ }
+
+ // add Event Disabled
+ QPixmap pmDisabled = SmallIcon( "stop" );
+ QString txtDisabled = i18n( "Event Disabled" );
+ m_pbc_previous->insertItem( pmDisabled, txtDisabled );
+ m_pbc_next->insertItem( pmDisabled, txtDisabled );
+ m_pbc_return->insertItem( pmDisabled, txtDisabled );
+ m_pbc_default->insertItem( pmDisabled, txtDisabled );
+ m_comboAfterTimeout->insertItem( pmDisabled, txtDisabled );
+
+ // add VideoCD End
+ QPixmap pmEnd = SmallIcon( "cdrom_unmount" );
+ QString txtEnd = i18n( "VideoCD END" );
+ m_pbc_previous->insertItem( pmEnd, txtEnd );
+ m_pbc_next->insertItem( pmEnd, txtEnd );
+ m_pbc_return->insertItem( pmEnd, txtEnd );
+ m_pbc_default->insertItem( pmEnd, txtEnd );
+ m_comboAfterTimeout->insertItem( pmEnd, txtEnd );
+ m_numkeysmap.insert( txtEnd, 0L );
+
+ for ( int i = 99; i > 0; i-- ) {
+ item = new K3bListViewItem( m_list_keys, QString::number( i ) + " ", "" );
+ item->setEditor( 1, K3bListViewItem::COMBO , m_numkeysmap.keys() );
+ }
+
+ int count = m_tracks.count();
+
+ if ( iPrevious < 0 )
+ m_pbc_previous->setCurrentItem( count + selectedTrack->getNonPbcTrack( K3bVcdTrack::PREVIOUS ) );
+ else
+ m_pbc_previous->setCurrentItem( iPrevious );
+
+ if ( iNext < 0 )
+ m_pbc_next->setCurrentItem( count + selectedTrack->getNonPbcTrack( K3bVcdTrack::NEXT ) );
+ else
+ m_pbc_next->setCurrentItem( iNext );
+
+ if ( iReturn < 0 )
+ m_pbc_return->setCurrentItem( count + selectedTrack->getNonPbcTrack( K3bVcdTrack::RETURN ) );
+ else
+ m_pbc_return->setCurrentItem( iReturn );
+
+ if ( iDefault < 0 )
+ m_pbc_default->setCurrentItem( count + selectedTrack->getNonPbcTrack( K3bVcdTrack::DEFAULT ) );
+ else
+ m_pbc_default->setCurrentItem( iDefault );
+
+ if ( iAfterTimeOut < 0 )
+ m_comboAfterTimeout->setCurrentItem( count + selectedTrack->getNonPbcTrack( K3bVcdTrack::AFTERTIMEOUT ) );
+ else
+ m_comboAfterTimeout->setCurrentItem( iAfterTimeOut );
+
+
+ m_spin_waittime->setValue( selectedTrack->getWaitTime() );
+ m_spin_times->setValue( selectedTrack->getPlayTime() );
+
+ m_check_reactivity->setChecked( selectedTrack->Reactivity() );
+ m_check_pbc->setChecked( VcdOptions() ->PbcEnabled() );
+
+ m_check_usekeys->setChecked( selectedTrack->PbcNumKeys() );
+ m_check_overwritekeys->setChecked( selectedTrack->PbcNumKeysUserdefined() );
+
+ m_mainTabbed->setTabEnabled( m_widgetnumkeys, m_check_usekeys->isChecked() && m_check_pbc->isChecked() );
+
+ setDefinedNumKeys();
+}
+
+void K3bVcdTrackDialog::prepareGui()
+{
+ QFrame * frame = plainPage();
+
+ QGridLayout* mainLayout = new QGridLayout( frame );
+ mainLayout->setSpacing( spacingHint() );
+ mainLayout->setMargin( 0 );
+
+ m_mainTabbed = new QTabWidget( frame );
+
+ ///////////////////////////////////////////////////
+ // FILE-INFO BOX
+ ///////////////////////////////////////////////////
+ QGroupBox* groupFileInfo = new QGroupBox( 0, Qt::Vertical, i18n( "File Info" ), frame, "groupFileInfo" );
+ groupFileInfo->layout() ->setSpacing( 0 );
+ groupFileInfo->layout() ->setMargin( 0 );
+
+ QGridLayout* groupFileInfoLayout = new QGridLayout( groupFileInfo->layout() );
+ groupFileInfoLayout->setAlignment( Qt::AlignTop );
+ groupFileInfoLayout->setSpacing( spacingHint() );
+ groupFileInfoLayout->setMargin( marginHint() );
+
+ m_labelMimeType = new QLabel( groupFileInfo, "m_labelMimeType" );
+
+ m_displayFileName = new KCutLabel( groupFileInfo );
+ m_displayFileName->setText( i18n( "Filename" ) );
+ m_displayFileName->setAlignment( int( QLabel::AlignTop | QLabel::AlignLeft ) );
+
+ QLabel* labelSize = new QLabel( i18n( "Size:" ), groupFileInfo, "labelSize" );
+ QLabel* labelLength = new QLabel( i18n( "Length:" ), groupFileInfo, "labelLength" );
+ QLabel* labelMuxrate = new QLabel( i18n( "Muxrate:" ), groupFileInfo, "labelMuxrate" );
+
+ m_displaySize = new QLabel( groupFileInfo, "m_displaySize" );
+ m_displaySize->setText( "0.0 MB" );
+ m_displaySize->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+ m_displayLength = new QLabel( groupFileInfo, "m_displayLength" );
+ m_displayLength->setText( "0:0:0" );
+ m_displayLength->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+ m_muxrate = new QLabel( groupFileInfo, "m_muxrate" );
+ m_muxrate->setText( i18n( "%1 bit/s" ).arg( 0 ) );
+ m_muxrate->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+ QFrame* fileInfoLine = new QFrame( groupFileInfo );
+ fileInfoLine->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+
+ groupFileInfoLayout->addWidget( m_labelMimeType, 0, 0 );
+ groupFileInfoLayout->addMultiCellWidget( m_displayFileName, 0, 1, 1, 1 );
+ groupFileInfoLayout->addMultiCellWidget( fileInfoLine, 2, 2, 0, 1 );
+ groupFileInfoLayout->addWidget( labelLength, 3, 0 );
+ groupFileInfoLayout->addWidget( labelSize, 4, 0 );
+ groupFileInfoLayout->addWidget( labelMuxrate, 5, 0 );
+ groupFileInfoLayout->addWidget( m_displayLength, 3, 1 );
+ groupFileInfoLayout->addWidget( m_displaySize, 4, 1 );
+ groupFileInfoLayout->addWidget( m_muxrate, 5, 1 );
+
+ groupFileInfoLayout->setRowStretch( 6, 1 );
+ groupFileInfoLayout->setColStretch( 1, 1 );
+
+ QFont f( m_displayLength->font() );
+ f.setBold( true );
+ m_displayLength->setFont( f );
+ m_displaySize->setFont( f );
+ m_muxrate->setFont( f );
+ ///////////////////////////////////////////////////
+
+ mainLayout->addWidget( groupFileInfo, 0, 0 );
+ mainLayout->addWidget( m_mainTabbed, 0, 1 );
+
+ // mainLayout->setColStretch( 0, 1 );
+
+}
+
+void K3bVcdTrackDialog::setupPbcTab()
+{
+ // /////////////////////////////////////////////////
+ // Playback Control TAB
+ // /////////////////////////////////////////////////
+ QWidget * w = new QWidget( m_mainTabbed );
+
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setAlignment( Qt::AlignTop );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( marginHint() );
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ QGroupBox* groupOptions = new QGroupBox( 3, Qt::Vertical, i18n( "Settings" ), w );
+ groupOptions->layout() ->setSpacing( spacingHint() );
+ groupOptions->layout() ->setMargin( marginHint() );
+
+ m_check_pbc = new QCheckBox( i18n( "Enable playback control (for the whole CD)" ), groupOptions, "m_check_pbc" );
+
+ m_check_usekeys = new QCheckBox( i18n( "Use numeric keys" ), groupOptions, "m_check_usekeys" );
+ m_check_usekeys->setEnabled( false );
+
+ m_check_reactivity = new QCheckBox( i18n( "Reactivity delayed to the end of playing track" ), groupOptions, "m_check_reactivity" );
+ m_check_reactivity->setEnabled( false );
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ m_groupPlay = new QGroupBox( 0, Qt::Vertical, i18n( "Playing" ), w );
+ m_groupPlay->layout() ->setSpacing( spacingHint() );
+ m_groupPlay->layout() ->setMargin( marginHint() );
+
+ QGridLayout* groupPlayLayout = new QGridLayout( m_groupPlay->layout() );
+ groupPlayLayout->setAlignment( Qt::AlignTop );
+
+ QLabel* labelPlaying = new QLabel( i18n( "Playing track" ) , m_groupPlay, "labelPlaying" );
+
+ m_spin_times = new QSpinBox( m_groupPlay, "m_spin_times" );
+ m_spin_times->setValue( 1 );
+ m_spin_times->setSuffix( i18n( " time(s)" ) );
+ m_spin_times->setSpecialValueText( i18n( "forever" ) );
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ m_labelWait = new QLabel( i18n( "then wait" ), m_groupPlay, "m_labelWait" );
+ m_spin_waittime = new QSpinBox( m_groupPlay, "m_spinSeconds" );
+ m_spin_waittime->setMinValue( -1 );
+ m_spin_waittime->setValue( 0 );
+ // m_spin_waittime->setEnabled( false );
+ m_spin_waittime->setSuffix( i18n( " seconds" ) );
+ m_spin_waittime->setSpecialValueText( i18n( "infinite" ) );
+
+ m_labelAfterTimeout = new QLabel( i18n( "after timeout playing" ), m_groupPlay, "m_labelTimeout" );
+ // m_labelAfterTimeout->setEnabled( false );
+ m_comboAfterTimeout = new K3bCutComboBox( K3bCutComboBox::SQUEEZE, m_groupPlay, "m_comboAfterTimeout" );
+ // m_comboAfterTimeout->setEnabled( false );
+
+ groupPlayLayout->addWidget( labelPlaying, 1, 0 );
+ groupPlayLayout->addWidget( m_spin_times, 1, 1 );
+ groupPlayLayout->addWidget( m_labelWait, 1, 2 );
+ groupPlayLayout->addWidget( m_spin_waittime, 1, 3 );
+ groupPlayLayout->addMultiCellWidget( m_labelAfterTimeout, 2, 2, 1, 3 );
+ groupPlayLayout->addMultiCellWidget( m_comboAfterTimeout, 3, 3, 1, 3 );
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ m_groupPbc = new QGroupBox( 0, Qt::Vertical, i18n( "Key Pressed Interaction" ), w );
+ m_groupPbc->layout() ->setSpacing( spacingHint() );
+ m_groupPbc->layout() ->setMargin( marginHint() );
+
+ QGridLayout* groupPbcLayout = new QGridLayout( m_groupPbc->layout() );
+ groupPbcLayout->setAlignment( Qt::AlignTop );
+
+ QLabel* labelPbc_previous = new QLabel( i18n( "Previous:" ), m_groupPbc, "labelPbc_previous" );
+ QLabel* labelPbc_next = new QLabel( i18n( "Next:" ), m_groupPbc, "labelPbc_next" );
+ QLabel* labelPbc_return = new QLabel( i18n( "Return:" ), m_groupPbc, "labelPbc_return" );
+ QLabel* labelPbc_default = new QLabel( i18n( "Default:" ), m_groupPbc, "labelPbc_default" );
+
+ m_pbc_previous = new K3bCutComboBox( K3bCutComboBox::SQUEEZE, m_groupPbc, "m_pbc_previous" );
+ m_pbc_next = new K3bCutComboBox( K3bCutComboBox::SQUEEZE, m_groupPbc, "m_pbc_next" );
+ m_pbc_return = new K3bCutComboBox( K3bCutComboBox::SQUEEZE, m_groupPbc, "m_pbc_return" );
+ m_pbc_default = new K3bCutComboBox( K3bCutComboBox::SQUEEZE, m_groupPbc, "m_pbc_default" );
+
+ groupPbcLayout->addWidget( labelPbc_previous, 1, 0 );
+ groupPbcLayout->addMultiCellWidget( m_pbc_previous, 1, 1, 1, 3 );
+
+ groupPbcLayout->addWidget( labelPbc_next, 2, 0 );
+ groupPbcLayout->addMultiCellWidget( m_pbc_next, 2, 2, 1, 3 );
+
+ groupPbcLayout->addWidget( labelPbc_return, 3, 0 );
+ groupPbcLayout->addMultiCellWidget( m_pbc_return, 3, 3, 1, 3 );
+
+ groupPbcLayout->addWidget( labelPbc_default, 4, 0 );
+ groupPbcLayout->addMultiCellWidget( m_pbc_default, 4, 4, 1, 3 );
+
+
+ grid->addWidget( groupOptions, 0, 0 );
+ grid->addWidget( m_groupPlay, 1, 0 );
+ grid->addWidget( m_groupPbc, 2, 0 );
+
+ grid->setRowStretch( 9, 1 );
+
+ m_mainTabbed->addTab( w, i18n( "Playback Control" ) );
+
+ m_groupPlay->setEnabled( false );
+ m_groupPbc->setEnabled( false );
+
+ connect( m_check_pbc, SIGNAL( toggled( bool ) ), this, SLOT( slotPbcToggled( bool ) ) );
+ connect( m_spin_times, SIGNAL( valueChanged( int ) ), this, SLOT( slotPlayTimeChanged( int ) ) );
+ connect( m_spin_waittime, SIGNAL( valueChanged( int ) ), this, SLOT( slotWaitTimeChanged( int ) ) );
+ connect( m_check_usekeys, SIGNAL( toggled( bool ) ), this, SLOT( slotUseKeysToggled( bool ) ) );
+}
+
+void K3bVcdTrackDialog::setupPbcKeyTab()
+{
+ // /////////////////////////////////////////////////
+ // Playback Control Numeric Key's TAB
+ // /////////////////////////////////////////////////
+ m_widgetnumkeys = new QWidget( m_mainTabbed );
+
+ QGridLayout* grid = new QGridLayout( m_widgetnumkeys );
+ grid->setAlignment( Qt::AlignTop );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( marginHint() );
+
+ m_groupKey = new QGroupBox( 3, Qt::Vertical, i18n( "Numeric Keys" ), m_widgetnumkeys );
+ m_groupKey->setEnabled( false );
+ m_groupKey->layout() ->setSpacing( spacingHint() );
+ m_groupKey->layout() ->setMargin( marginHint() );
+
+ m_list_keys = new K3bListView( m_groupKey, "m_list_keys" );
+ m_list_keys->setAllColumnsShowFocus( true );
+ m_list_keys->setDoubleClickForEdit( false );
+ m_list_keys->setColumnAlignment( 0, Qt::AlignRight );
+ m_list_keys->setSelectionMode( QListView::NoSelection );
+ m_list_keys->setSorting( -1 );
+ m_list_keys->addColumn( i18n( "Key" ) );
+ m_list_keys->addColumn( i18n( "Playing" ) );
+ m_list_keys->setResizeMode( QListView::LastColumn );
+ m_check_overwritekeys = new QCheckBox( i18n( "Overwrite default assignment" ), m_widgetnumkeys, "m_check_overwritekeys" );
+
+ grid->addWidget( m_groupKey, 1, 0 );
+ grid->addWidget( m_check_overwritekeys, 2, 0 );
+
+ m_mainTabbed->addTab( m_widgetnumkeys, i18n( "Numeric Keys" ) );
+
+ connect( m_check_overwritekeys, SIGNAL( toggled( bool ) ), this, SLOT( slotGroupkeyToggled( bool ) ) );
+
+}
+
+void K3bVcdTrackDialog::setupAudioTab()
+{
+ // /////////////////////////////////////////////////
+ // AUDIO TAB
+ // /////////////////////////////////////////////////
+ QWidget * w = new QWidget( m_mainTabbed );
+
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setAlignment( Qt::AlignTop );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( marginHint() );
+
+ QLabel* labelMpegVer_Audio = new QLabel( i18n( "Type:" ), w, "labelMpegVer_Audio" );
+ QLabel* labelRate_Audio = new QLabel( i18n( "Rate:" ), w, "labelRate_Audio" );
+ QLabel* labelSampling_Frequency_Audio = new QLabel( i18n( "Sampling frequency:" ), w, "labelSampling_Frequency_Audio" );
+ QLabel* labelMode_Audio = new QLabel( i18n( "Mode:" ), w, "labelMode_Audio" );
+ QLabel* labelCopyright_Audio = new QLabel( i18n( "Copyright:" ), w, "labelCopyright_Audio" );
+
+ m_mpegver_audio = new QLabel( w, "m_mpegver_audio" );
+ m_rate_audio = new QLabel( w, "m_rate_audio" );
+ m_sampling_frequency_audio = new QLabel( w, "m_sampling_frequency_audio" );
+ m_mode_audio = new QLabel( w, "m_mode_audio" );
+ m_copyright_audio = new QLabel( w, "m_copyright_audio" );
+
+ m_mpegver_audio->setFrameShape( QLabel::LineEditPanel );
+ m_rate_audio->setFrameShape( QLabel::LineEditPanel );
+ m_sampling_frequency_audio->setFrameShape( QLabel::LineEditPanel );
+ m_mode_audio->setFrameShape( QLabel::LineEditPanel );
+ m_copyright_audio->setFrameShape( QLabel::LineEditPanel );
+
+ m_mpegver_audio->setFrameShadow( QLabel::Sunken );
+ m_rate_audio->setFrameShadow( QLabel::Sunken );
+ m_sampling_frequency_audio->setFrameShadow( QLabel::Sunken );
+ m_mode_audio->setFrameShadow( QLabel::Sunken );
+ m_copyright_audio->setFrameShadow( QLabel::Sunken );
+
+ grid->addWidget( labelMpegVer_Audio, 1, 0 );
+ grid->addMultiCellWidget( m_mpegver_audio, 1, 1, 1, 4 );
+
+ grid->addWidget( labelRate_Audio, 2, 0 );
+ grid->addMultiCellWidget( m_rate_audio, 2, 2, 1, 4 );
+
+ grid->addWidget( labelSampling_Frequency_Audio, 3, 0 );
+ grid->addMultiCellWidget( m_sampling_frequency_audio, 3, 3, 1, 4 );
+
+ grid->addWidget( labelMode_Audio, 4, 0 );
+ grid->addMultiCellWidget( m_mode_audio, 4, 4, 1, 4 );
+
+ grid->addWidget( labelCopyright_Audio, 5, 0 );
+ grid->addMultiCellWidget( m_copyright_audio, 5, 5, 1, 4 );
+
+ grid->setRowStretch( 9, 4 );
+
+ m_mainTabbed->addTab( w, i18n( "Audio" ) );
+
+}
+
+void K3bVcdTrackDialog::setupVideoTab()
+{
+ // /////////////////////////////////////////////////
+ // VIDEO TAB
+ // /////////////////////////////////////////////////
+ QWidget * w = new QWidget( m_mainTabbed );
+
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setAlignment( Qt::AlignTop );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( marginHint() );
+
+ QLabel* labelMpegVer_Video = new QLabel( i18n( "Type:" ), w, "labelMpegVer_Video" );
+ QLabel* labelRate_Video = new QLabel( i18n( "Rate:" ), w, "labelRate_Video" );
+ QLabel* labelChromaFormat_Video = new QLabel( i18n( "Chroma format:" ), w, "labelChromaFormat_Video" );
+ QLabel* labelFormat_Video = new QLabel( i18n( "Video format:" ), w, "labelFormat_Video" );
+ QLabel* labelResolution_Video = new QLabel( i18n( "Resolution:" ), w, "labelSize_Video" );
+ QLabel* labelHighResolution_Video = new QLabel( i18n( "High resolution:" ), w, "labelHighResolution_Video" );
+
+ m_mpegver_video = new QLabel( w, "m_mpegver_video" );
+ m_rate_video = new QLabel( w, "m_rate_video" );
+ m_chromaformat_video = new QLabel( w, "m_chromaformat_video" );
+ m_format_video = new QLabel( w, "m_format_video" );
+ m_resolution_video = new QLabel( w, "m_resolution_video" );
+ m_highresolution_video = new QLabel( w, "m_highresolution_video" );
+
+ m_mpegver_video->setFrameShape( QLabel::LineEditPanel );
+ m_rate_video->setFrameShape( QLabel::LineEditPanel );
+ m_chromaformat_video->setFrameShape( QLabel::LineEditPanel );
+ m_format_video->setFrameShape( QLabel::LineEditPanel );
+ m_resolution_video->setFrameShape( QLabel::LineEditPanel );
+ m_highresolution_video->setFrameShape( QLabel::LineEditPanel );
+
+ m_mpegver_video->setFrameShadow( QLabel::Sunken );
+ m_rate_video->setFrameShadow( QLabel::Sunken );
+ m_chromaformat_video->setFrameShadow( QLabel::Sunken );
+ m_format_video->setFrameShadow( QLabel::Sunken );
+ m_resolution_video->setFrameShadow( QLabel::Sunken );
+ m_highresolution_video->setFrameShadow( QLabel::Sunken );
+
+ grid->addWidget( labelMpegVer_Video, 1, 0 );
+ grid->addMultiCellWidget( m_mpegver_video, 1, 1, 1, 4 );
+
+ grid->addWidget( labelRate_Video, 2, 0 );
+ grid->addMultiCellWidget( m_rate_video, 2, 2, 1, 4 );
+
+ grid->addWidget( labelChromaFormat_Video, 3, 0 );
+ grid->addMultiCellWidget( m_chromaformat_video, 3, 3, 1, 4 );
+
+ grid->addWidget( labelFormat_Video, 4, 0 );
+ grid->addMultiCellWidget( m_format_video, 4, 4, 1, 4 );
+
+ grid->addWidget( labelResolution_Video, 5, 0 );
+ grid->addMultiCellWidget( m_resolution_video, 5, 5, 1, 4 );
+
+ grid->addWidget( labelHighResolution_Video, 6, 0 );
+ grid->addMultiCellWidget( m_highresolution_video, 6, 6, 1, 4 );
+
+ grid->setRowStretch( 9, 4 );
+
+ m_mainTabbed->addTab( w, i18n( "Video" ) );
+}
+
+void K3bVcdTrackDialog::setDefinedNumKeys( )
+{
+ K3bVcdTrack * selectedTrack = m_selectedTracks.first();
+ if ( !m_check_overwritekeys->isChecked() ) {
+
+ selectedTrack->delDefinedNumKey();
+ selectedTrack->setDefinedNumKey( 1, selectedTrack );
+
+ }
+
+ QListViewItemIterator it( m_list_keys );
+ QMap<int, K3bVcdTrack*> definedkeysmap = selectedTrack->DefinedNumKey();
+
+ while ( it.current() ) {
+ int itemId = it.current() ->text( 0 ).toInt();
+
+ QMap<int, K3bVcdTrack*>::const_iterator keyit = definedkeysmap.find( itemId );
+
+ if ( keyit != definedkeysmap.end() ) {
+ if ( keyit.data() ) {
+ if ( m_tracks.findRef( keyit.data() ) >= 0 ) {
+ it.current() ->setText( 1 , displayName( keyit.data() ) ) ;
+ } else {
+ it.current() ->setText( 1 , "" ) ;
+ selectedTrack->delDefinedNumKey( keyit.key() );
+ }
+ } else {
+ it.current() ->setText( 1 , i18n( "VideoCD END" ) ) ;
+ }
+ } else {
+ it.current() ->setText( 1 , "" ) ;
+ }
+ ++it;
+ }
+}
+
+QString K3bVcdTrackDialog::displayName( K3bVcdTrack * track )
+{
+ if ( track == m_selectedTracks.first() )
+ return i18n( "ItSelf" );
+
+ if ( track->isSegment() )
+ return i18n( "Segment-%1 - %2" ).arg( QString::number( track->index() + 1 ).rightJustify( 3, '0' ) ).arg( track->title() );
+
+ return i18n( "Sequence-%1 - %2" ).arg( QString::number( track->index() + 1 ).rightJustify( 3, '0' ) ).arg( track->title() );
+}
+
+void K3bVcdTrackDialog::slotPlayTimeChanged( int value )
+{
+ if ( value == 0 ) {
+ m_labelWait->setEnabled( false );
+ m_spin_waittime->setEnabled( false );
+ m_labelAfterTimeout->setEnabled( false );
+ m_comboAfterTimeout->setEnabled( false );
+ } else {
+ m_labelWait->setEnabled( true );
+ m_spin_waittime->setEnabled( true );
+ if ( m_spin_waittime->value() > -1 ) {
+ m_labelAfterTimeout->setEnabled( true );
+ m_comboAfterTimeout->setEnabled( true );
+ }
+ }
+}
+
+void K3bVcdTrackDialog::slotWaitTimeChanged( int value )
+{
+ if ( value < 0 || !m_labelWait->isEnabled() ) {
+ m_labelAfterTimeout->setEnabled( false );
+ m_comboAfterTimeout->setEnabled( false );
+ } else {
+ m_labelAfterTimeout->setEnabled( true );
+ m_comboAfterTimeout->setEnabled( true );
+ }
+}
+
+void K3bVcdTrackDialog::slotPbcToggled( bool b )
+{
+ m_groupPlay->setEnabled( b );
+ m_groupPbc->setEnabled( b );
+ m_check_usekeys->setEnabled( b );
+ slotUseKeysToggled( b && m_check_usekeys->isChecked() );
+ m_check_reactivity->setEnabled( b );
+ if ( b )
+ slotWaitTimeChanged( m_spin_waittime->value() );
+}
+
+void K3bVcdTrackDialog::slotUseKeysToggled( bool b )
+{
+ m_mainTabbed->setTabEnabled( m_widgetnumkeys, b );
+}
+
+void K3bVcdTrackDialog::slotGroupkeyToggled( bool b )
+{
+ m_groupKey->setEnabled( b );
+ setDefinedNumKeys();
+}
+
+#include "k3bvcdtrackdialog.moc"
diff --git a/src/projects/k3bvcdtrackdialog.h b/src/projects/k3bvcdtrackdialog.h
new file mode 100644
index 0000000..3b62c35
--- /dev/null
+++ b/src/projects/k3bvcdtrackdialog.h
@@ -0,0 +1,123 @@
+/*
+*
+* $Id: k3bvcdtrackdialog.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#ifndef K3BVCDTRACKDIALOG_H
+#define K3BVCDTRACKDIALOG_H
+
+#include <kdialogbase.h>
+#include <qptrlist.h>
+#include <qtabwidget.h>
+
+#include <k3bvcddoc.h>
+#include <k3blistview.h>
+
+class K3bVcdTrack;
+class QLabel;
+class QCheckBox;
+class QComboBox;
+class QGroupBox;
+class QRadioButton;
+class QButtonGroup;
+class KCutLabel;
+class K3bCutComboBox;
+
+
+class K3bVcdTrackDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bVcdTrackDialog( K3bVcdDoc*, QPtrList<K3bVcdTrack>& tracks, QPtrList<K3bVcdTrack>& selectedTracks, QWidget* parent = 0, const char* name = 0 );
+ ~K3bVcdTrackDialog();
+
+ protected slots:
+ void slotOk();
+ void slotApply();
+
+ private slots:
+ void slotPlayTimeChanged( int );
+ void slotWaitTimeChanged( int );
+ void slotPbcToggled( bool );
+ void slotUseKeysToggled( bool );
+ void slotGroupkeyToggled( bool );
+
+
+ private:
+ K3bVcdDoc* m_vcdDoc;
+ QPtrList<K3bVcdTrack> m_tracks;
+ QPtrList<K3bVcdTrack> m_selectedTracks;
+ QMap<QString, K3bVcdTrack*> m_numkeysmap;
+ QTabWidget* m_mainTabbed;
+
+ KCutLabel* m_displayFileName;
+ QLabel* m_labelMimeType;
+ QLabel* m_displaySize;
+ QLabel* m_displayLength;
+ QLabel* m_muxrate;
+
+ QLabel* m_mpegver_audio;
+ QLabel* m_rate_audio;
+ QLabel* m_sampling_frequency_audio;
+ QLabel* m_mode_audio;
+ QLabel* m_copyright_audio;
+
+ QLabel* m_mpegver_video;
+ QLabel* m_rate_video;
+ QLabel* m_chromaformat_video;
+ QLabel* m_format_video;
+ QLabel* m_resolution_video;
+ QLabel* m_highresolution_video;
+
+ QLabel* m_labelAfterTimeout;
+ QLabel* m_labelWait;
+
+ QGroupBox* m_groupPlay;
+ QGroupBox* m_groupPbc;
+ QGroupBox* m_groupKey;
+ QWidget* m_widgetnumkeys;
+
+ K3bCutComboBox* m_pbc_previous;
+ K3bCutComboBox* m_pbc_next;
+ K3bCutComboBox* m_pbc_return;
+ K3bCutComboBox* m_pbc_default;
+ K3bCutComboBox* m_comboAfterTimeout;
+
+ QCheckBox* m_check_reactivity;
+ QCheckBox* m_check_pbc;
+ QCheckBox* m_check_usekeys;
+ QCheckBox* m_check_overwritekeys;
+ K3bListView* m_list_keys;
+
+ QSpinBox* m_spin_times;
+ QSpinBox* m_spin_waittime;
+
+ void prepareGui();
+ void setupPbcTab();
+ void setupPbcKeyTab();
+ void setupAudioTab();
+ void setupVideoTab();
+ void fillGui();
+ void fillPbcGui();
+
+ void setPbcTrack( K3bVcdTrack*, K3bCutComboBox*, int );
+ void setDefinedNumKeys( );
+ QString displayName( K3bVcdTrack* );
+ K3bVcdOptions* VcdOptions()
+ {
+ return m_vcdDoc->vcdOptions();
+ }
+};
+
+#endif
diff --git a/src/projects/k3bvcdview.cpp b/src/projects/k3bvcdview.cpp
new file mode 100644
index 0000000..d8984d4
--- /dev/null
+++ b/src/projects/k3bvcdview.cpp
@@ -0,0 +1,74 @@
+/*
+*
+* $Id: k3bvcdview.cpp 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+// QT-includes
+#include <qlayout.h>
+#include <qstring.h>
+
+
+// KDE-includes
+#include <klocale.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+// K3b Includes
+#include "k3bvcdview.h"
+#include "k3bvcddoc.h"
+#include "k3bvcdlistview.h"
+#include "k3bvcdburndialog.h"
+#include <k3bfillstatusdisplay.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bcore.h>
+
+
+K3bVcdView::K3bVcdView( K3bVcdDoc* pDoc, QWidget* parent, const char *name )
+ : K3bView( pDoc, parent, name )
+{
+ m_doc = pDoc;
+
+ // --- setup GUI ---------------------------------------------------
+
+ m_vcdlist = new K3bVcdListView( this, pDoc, this );
+ setMainWidget( m_vcdlist );
+ fillStatusDisplay() ->showSize();
+
+ connect( m_vcdlist, SIGNAL( lengthReady() ), fillStatusDisplay(), SLOT( update() ) );
+ connect( m_doc, SIGNAL( newTracks() ), fillStatusDisplay(), SLOT( update() ) );
+}
+
+K3bVcdView::~K3bVcdView()
+{}
+
+
+K3bProjectBurnDialog* K3bVcdView::newBurnDialog( QWidget * parent, const char * name )
+{
+ return new K3bVcdBurnDialog( m_doc, parent, name, true );
+}
+
+
+void K3bVcdView::init()
+{
+ if( !k3bcore->externalBinManager()->foundBin( "vcdxbuild" ) ) {
+ kdDebug() << "(K3bVcdView) could not find vcdxbuild executable" << endl;
+ KMessageBox::information( this,
+ i18n( "Could not find VcdImager executable. "
+ "To create VideoCD's you must install VcdImager >= 0.7.12. "
+ "You can find this on your distribution disks or download "
+ "it from http://www.vcdimager.org" ) );
+ }
+}
+
+#include "k3bvcdview.moc"
diff --git a/src/projects/k3bvcdview.h b/src/projects/k3bvcdview.h
new file mode 100644
index 0000000..77ad292
--- /dev/null
+++ b/src/projects/k3bvcdview.h
@@ -0,0 +1,55 @@
+/*
+*
+* $Id: k3bvcdview.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003-2004 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#ifndef K3BVCDVIEW_H
+#define K3BVCDVIEW_H
+
+#include <qstringlist.h>
+#include <qptrlist.h>
+
+// K3b Includes
+#include <k3bview.h>
+
+class K3bVcdListView;
+class K3bVcdListViewItem;
+class QWidget;
+class K3bVcdDoc;
+class K3bVcdTrack;
+class QListViewItem;
+class KListView;
+class K3bVcdBurnDialog;
+class K3bProjectBurnDialog;
+
+
+class K3bVcdView : public K3bView
+{
+ Q_OBJECT
+
+ public:
+ K3bVcdView( K3bVcdDoc* pDoc, QWidget* parent, const char *name = 0 );
+ ~K3bVcdView();
+
+ protected:
+ K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ void init();
+
+ private:
+ K3bVcdDoc* m_doc;
+
+ K3bVcdListView* m_vcdlist;
+};
+
+#endif
diff --git a/src/projects/k3bvideodvdburndialog.cpp b/src/projects/k3bvideodvdburndialog.cpp
new file mode 100644
index 0000000..22626df
--- /dev/null
+++ b/src/projects/k3bvideodvdburndialog.cpp
@@ -0,0 +1,198 @@
+/*
+ *
+ * $Id: k3bvideodvdburndialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdburndialog.h"
+#include "k3bvideodvddoc.h"
+
+#include <k3bdevice.h>
+#include <k3bwriterselectionwidget.h>
+#include <k3btempdirselectionwidget.h>
+#include <k3bcore.h>
+#include <k3bwritingmodewidget.h>
+#include <k3bglobals.h>
+#include <k3bdataimagesettingswidget.h>
+#include <k3bisooptions.h>
+#include <k3bstdguiitems.h>
+#include <k3bglobalsettings.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kio/global.h>
+#include <kmessagebox.h>
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+
+K3bVideoDvdBurnDialog::K3bVideoDvdBurnDialog( K3bVideoDvdDoc* doc, QWidget *parent, const char *name, bool modal )
+ : K3bProjectBurnDialog( doc, parent, name, modal, true ),
+ m_doc( doc )
+{
+ prepareGui();
+
+ setTitle( i18n("Video DVD Project"), i18n("Size: %1").arg( KIO::convertSize(doc->size()) ) );
+
+ // for now we just put the verify checkbox on the main page...
+ m_checkVerify = K3bStdGuiItems::verifyCheckBox( m_optionGroup );
+ m_optionGroupLayout->addWidget( m_checkVerify );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ m_optionGroupLayout->addItem( spacer );
+
+ // create image settings tab
+ m_imageSettingsWidget = new K3bDataImageSettingsWidget( this );
+ m_imageSettingsWidget->showFileSystemOptions( false );
+
+ addPage( m_imageSettingsWidget, i18n("Filesystem") );
+
+ m_tempDirSelectionWidget->setSelectionMode( K3bTempDirSelectionWidget::FILE );
+
+ QString path = m_doc->tempDir();
+ if( path.isEmpty() ) {
+ path = K3b::defaultTempPath();
+ if( m_doc->isoOptions().volumeID().isEmpty() )
+ path.append( "image.iso" );
+ else
+ path.append( m_doc->isoOptions().volumeID() + ".iso" );
+ }
+ m_tempDirSelectionWidget->setTempPath( path );
+}
+
+
+K3bVideoDvdBurnDialog::~K3bVideoDvdBurnDialog()
+{
+}
+
+
+void K3bVideoDvdBurnDialog::saveSettings()
+{
+ K3bProjectBurnDialog::saveSettings();
+
+ // save iso image settings
+ K3bIsoOptions o = m_doc->isoOptions();
+ m_imageSettingsWidget->save( o );
+ m_doc->setIsoOptions( o );
+
+ // save image file path
+ m_doc->setTempDir( m_tempDirSelectionWidget->tempPath() );
+
+ m_doc->setVerifyData( m_checkVerify->isChecked() );
+}
+
+
+void K3bVideoDvdBurnDialog::readSettings()
+{
+ K3bProjectBurnDialog::readSettings();
+
+ if( !doc()->tempDir().isEmpty() )
+ m_tempDirSelectionWidget->setTempPath( doc()->tempDir() );
+ else
+ m_tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() + doc()->name() + ".iso" );
+
+ m_checkVerify->setChecked( m_doc->verifyData() );
+
+ m_imageSettingsWidget->load( m_doc->isoOptions() );
+
+ // in case overburn is enabled we allow some made up max size
+ // before we force a DL medium
+ if( doc()->size() > 4700372992LL &&
+ ( !k3bcore->globalSettings()->overburn() ||
+ doc()->size() > 4900000000LL ) )
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD_DL );
+ else
+ m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD );
+
+ toggleAll();
+}
+
+
+void K3bVideoDvdBurnDialog::toggleAll()
+{
+ K3bProjectBurnDialog::toggleAll();
+
+ if( m_checkSimulate->isChecked() || m_checkOnlyCreateImage->isChecked() ) {
+ m_checkVerify->setChecked(false);
+ m_checkVerify->setEnabled(false);
+ }
+ else
+ m_checkVerify->setEnabled(true);
+}
+
+
+void K3bVideoDvdBurnDialog::loadK3bDefaults()
+{
+ K3bProjectBurnDialog::loadK3bDefaults();
+
+ m_imageSettingsWidget->load( K3bIsoOptions::defaults() );
+ m_checkVerify->setChecked( false );
+
+ toggleAll();
+}
+
+
+void K3bVideoDvdBurnDialog::loadUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::loadUserDefaults( c );
+
+ K3bIsoOptions o = K3bIsoOptions::load( c );
+ m_imageSettingsWidget->load( o );
+
+ m_checkVerify->setChecked( c->readBoolEntry( "verify data", false ) );
+
+ toggleAll();
+}
+
+
+void K3bVideoDvdBurnDialog::saveUserDefaults( KConfigBase* c )
+{
+ K3bProjectBurnDialog::saveUserDefaults(c);
+
+ K3bIsoOptions o;
+ m_imageSettingsWidget->save( o );
+ o.save( c );
+
+ c->writeEntry( "verify data", m_checkVerify->isChecked() );
+}
+
+
+void K3bVideoDvdBurnDialog::slotStartClicked()
+{
+ if( m_checkOnlyCreateImage->isChecked() ||
+ m_checkCacheImage->isChecked() ) {
+ QFileInfo fi( m_tempDirSelectionWidget->tempPath() );
+ if( fi.isDir() )
+ m_tempDirSelectionWidget->setTempPath( fi.filePath() + "/image.iso" );
+
+ if( QFile::exists( m_tempDirSelectionWidget->tempPath() ) ) {
+ if( KMessageBox::warningContinueCancel( this,
+ i18n("Do you want to overwrite %1?").arg(m_tempDirSelectionWidget->tempPath()),
+ i18n("File Exists"), i18n("Overwrite") )
+ == KMessageBox::Continue ) {
+ // delete the file here to avoid problems with free space in K3bProjectBurnDialog::slotStartClicked
+ QFile::remove( m_tempDirSelectionWidget->tempPath() );
+ }
+ else
+ return;
+ }
+ }
+
+ K3bProjectBurnDialog::slotStartClicked();
+}
+
+#include "k3bvideodvdburndialog.moc"
diff --git a/src/projects/k3bvideodvdburndialog.h b/src/projects/k3bvideodvdburndialog.h
new file mode 100644
index 0000000..0dbbe58
--- /dev/null
+++ b/src/projects/k3bvideodvdburndialog.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id: k3bvideodvdburndialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_VIDEODVD_BURNDIALOG_H_
+#define _K3B_VIDEODVD_BURNDIALOG_H_
+
+#include "k3bprojectburndialog.h"
+
+
+class K3bVideoDvdDoc;
+class K3bDataImageSettingsWidget;
+class QCheckBox;
+
+
+class K3bVideoDvdBurnDialog : public K3bProjectBurnDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDvdBurnDialog( K3bVideoDvdDoc*, QWidget *parent = 0, const char *name = 0, bool modal = true );
+ ~K3bVideoDvdBurnDialog();
+
+ protected slots:
+ void slotStartClicked();
+ void saveSettings();
+ void readSettings();
+
+ protected:
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+ void toggleAll();
+
+ private:
+ K3bDataImageSettingsWidget* m_imageSettingsWidget;
+
+ QCheckBox* m_checkVerify;
+
+ K3bVideoDvdDoc* m_doc;
+};
+
+#endif
diff --git a/src/projects/k3bvideodvdview.cpp b/src/projects/k3bvideodvdview.cpp
new file mode 100644
index 0000000..277beac
--- /dev/null
+++ b/src/projects/k3bvideodvdview.cpp
@@ -0,0 +1,84 @@
+/*
+ *
+ * $Id: k3bvideodvdview.cpp 644513 2007-03-20 09:07:44Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdview.h"
+#include "k3bvideodvddoc.h"
+#include "k3bvideodvdburndialog.h"
+#include "k3bdatadirtreeview.h"
+#include "k3bdatafileview.h"
+#include "k3bdataurladdingdialog.h"
+#include <k3bfillstatusdisplay.h>
+#include <k3bdatafileview.h>
+#include <k3btoolbox.h>
+#include <k3bprojectplugin.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kactioncollection.h>
+
+#include <qsplitter.h>
+
+
+K3bVideoDvdView::K3bVideoDvdView( K3bVideoDvdDoc* doc, QWidget *parent, const char *name )
+ : K3bView( doc, parent, name ),
+ m_doc(doc)
+{
+ fillStatusDisplay()->showDvdSizes(true);
+
+ // --- setup GUI ---------------------------------------------------
+ QSplitter* mainSplitter = new QSplitter( this );
+ m_dataDirTree = new K3bDataDirTreeView( this, doc, mainSplitter );
+ m_dataFileView = new K3bDataFileView( this, m_dataDirTree, doc, mainSplitter );
+ m_dataDirTree->setFileView( m_dataFileView );
+ setMainWidget( mainSplitter );
+
+ connect( m_dataFileView, SIGNAL(dirSelected(K3bDirItem*)), m_dataDirTree, SLOT(setCurrentDir(K3bDirItem*)) );
+
+ m_dataDirTree->checkForNewItems();
+ m_dataFileView->checkForNewItems();
+
+ addPluginButtons( K3bProjectPlugin::VIDEO_DVD );
+}
+
+
+K3bVideoDvdView::~K3bVideoDvdView()
+{
+}
+
+
+K3bProjectBurnDialog* K3bVideoDvdView::newBurnDialog( QWidget* parent, const char* name )
+{
+ return new K3bVideoDvdBurnDialog( m_doc, parent, name, true );
+}
+
+
+void K3bVideoDvdView::init()
+{
+ KMessageBox::information( this,
+ i18n("Be aware that you need to provide the complete Video DVD filestructure. "
+ "K3b does not support video transcoding and preparation of video object "
+ "files yet. That means you need to already have the VTS_X_YY.VOB "
+ "and VTS_X_YY.IFO files."),
+ i18n("K3b Video DVD Restrictions"),
+ "video_dvd_restrictions" );
+}
+
+
+void K3bVideoDvdView::addUrls( const KURL::List& urls )
+{
+ K3bDataUrlAddingDialog::addUrls( urls, m_dataFileView->currentDir() );
+}
+
+#include "k3bvideodvdview.moc"
diff --git a/src/projects/k3bvideodvdview.h b/src/projects/k3bvideodvdview.h
new file mode 100644
index 0000000..1125ac4
--- /dev/null
+++ b/src/projects/k3bvideodvdview.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * $Id: k3bvideodvdview.h 644513 2007-03-20 09:07:44Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_VIDEO_DVDVIEW_H_
+#define _K3B_VIDEO_DVDVIEW_H_
+
+#include <k3bview.h>
+
+class K3bVideoDvdDoc;
+class K3bDataDirTreeView;
+class K3bDataFileView;
+
+
+class K3bVideoDvdView : public K3bView
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDvdView( K3bVideoDvdDoc* doc, QWidget *parent = 0, const char *name = 0 );
+ ~K3bVideoDvdView();
+
+ void addUrls( const KURL::List& );
+
+ protected:
+ virtual K3bProjectBurnDialog* newBurnDialog( QWidget* parent = 0, const char* name = 0 );
+
+ void init();
+
+ private:
+ K3bVideoDvdDoc* m_doc;
+ K3bDataDirTreeView* m_dataDirTree;
+ K3bDataFileView* m_dataFileView;
+};
+
+#endif
diff --git a/src/projects/k3bview.cpp b/src/projects/k3bview.cpp
new file mode 100644
index 0000000..0809f59
--- /dev/null
+++ b/src/projects/k3bview.cpp
@@ -0,0 +1,176 @@
+/*
+ *
+ * $Id: k3bview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+// include files for Qt
+#include <qlayout.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qptrlist.h>
+#include <qtoolbutton.h>
+
+#include <kaction.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+// application specific includes
+#include "k3bview.h"
+#include "k3bdoc.h"
+#include "k3bfillstatusdisplay.h"
+#include "k3bprojectburndialog.h"
+#include "k3bprojectplugindialog.h"
+#include <k3btoolbox.h>
+#include <k3bpluginmanager.h>
+#include <k3bprojectplugin.h>
+#include <k3bcore.h>
+
+
+K3bView::K3bView( K3bDoc* pDoc, QWidget *parent, const char* name )
+ : QWidget( parent, name ),
+ m_doc( pDoc )
+{
+ QGridLayout* grid = new QGridLayout( this );
+
+ m_toolBox = new K3bToolBox( this, "toolbox" );
+ m_fillStatusDisplay = new K3bFillStatusDisplay( m_doc, this );
+
+ grid->addMultiCellWidget( m_toolBox, 0, 0, 0, 1 );
+ grid->addMultiCellWidget( m_fillStatusDisplay, 2, 2, 0, 1 );
+ // grid->addWidget( m_buttonBurn, 2, 1 );
+ grid->setRowStretch( 1, 1 );
+ grid->setColStretch( 0, 1 );
+ grid->setSpacing( 5 );
+ grid->setMargin( 2 );
+
+ KAction* burnAction = new KAction( i18n("&Burn"), "cdburn", CTRL + Key_B, this, SLOT(slotBurn()),
+ actionCollection(), "project_burn");
+ burnAction->setToolTip( i18n("Open the burn dialog for the current project") );
+ KAction* propAction = new KAction( i18n("&Properties"), "edit", CTRL + Key_P, this, SLOT(slotProperties()),
+ actionCollection(), "project_properties");
+ propAction->setToolTip( i18n("Open the properties dialog") );
+
+ m_toolBox->addButton( burnAction, true );
+ m_toolBox->addSeparator();
+
+ // this is just for testing (or not?)
+ // most likely every project type will have it's rc file in the future
+ setXML( "<!DOCTYPE kpartgui SYSTEM \"kpartgui.dtd\">"
+ "<kpartgui name=\"k3bproject\" version=\"1\">"
+ "<MenuBar>"
+ " <Menu name=\"project\"><text>&amp;Project</text>"
+ " <Action name=\"project_burn\"/>"
+ " <Action name=\"project_properties\"/>"
+ " </Menu>"
+ "</MenuBar>"
+ "</kpartgui>", true );
+}
+
+K3bView::~K3bView()
+{
+}
+
+
+void K3bView::setMainWidget( QWidget* w )
+{
+ static_cast<QGridLayout*>(layout())->addMultiCellWidget( w, 1, 1, 0, 1 );
+}
+
+
+void K3bView::slotBurn()
+{
+ if( m_doc->numOfTracks() == 0 || m_doc->size() == 0 ) {
+ KMessageBox::information( this, i18n("Please add files to your project first."),
+ i18n("No Data to Burn"), QString::null, false );
+ }
+ else {
+ K3bProjectBurnDialog* dlg = newBurnDialog( this );
+ if( dlg ) {
+ dlg->execBurnDialog(true);
+ delete dlg;
+ }
+ else {
+ kdDebug() << "(K3bDoc) Error: no burndialog available." << endl;
+ }
+ }
+}
+
+
+void K3bView::slotProperties()
+{
+ K3bProjectBurnDialog* dlg = newBurnDialog( this );
+ if( dlg ) {
+ dlg->execBurnDialog(false);
+ delete dlg;
+ }
+ else {
+ kdDebug() << "(K3bDoc) Error: no burndialog available." << endl;
+ }
+}
+
+
+// KActionCollection* K3bView::actionCollection() const
+// {
+// return m_actionCollection;
+// }
+
+
+void K3bView::addPluginButtons( int projectType )
+{
+ QPtrList<K3bPlugin> pl = k3bcore->pluginManager()->plugins( "ProjectPlugin" );
+ for( QPtrListIterator<K3bPlugin> it( pl ); *it; ++it ) {
+ K3bProjectPlugin* pp = dynamic_cast<K3bProjectPlugin*>( *it );
+ if( pp && (pp->type() & projectType) ) {
+ QToolButton* button = toolBox()->addButton( pp->text(),
+ pp->icon(),
+ pp->toolTip(),
+ pp->whatsThis(),
+ this,
+ SLOT(slotPluginButtonClicked()) );
+ m_plugins.insert( static_cast<void*>(button), pp );
+ }
+ }
+}
+
+
+void K3bView::slotPluginButtonClicked()
+{
+ QObject* o = const_cast<QObject*>(sender());
+ if( K3bProjectPlugin* p = m_plugins[static_cast<void*>(o)] ) {
+ if( p->hasGUI() ) {
+ K3bProjectPluginDialog dlg( p, doc(), this );
+ dlg.exec();
+ }
+ else
+ p->activate( doc(), this );
+ }
+}
+
+
+void K3bView::addUrl( const KURL& url )
+{
+ KURL::List urls(url);
+ addUrls( urls );
+}
+
+
+void K3bView::addUrls( const KURL::List& urls )
+{
+ doc()->addUrls( urls );
+}
+
+#include "k3bview.moc"
diff --git a/src/projects/k3bview.h b/src/projects/k3bview.h
new file mode 100644
index 0000000..2bd8266
--- /dev/null
+++ b/src/projects/k3bview.h
@@ -0,0 +1,112 @@
+/*
+ *
+ * $Id: k3bview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BVIEW_H
+#define K3BVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// include files for Qt
+#include <qwidget.h>
+#include <qptrdict.h>
+
+#include <kxmlguiclient.h>
+#include <kurl.h>
+
+class K3bDoc;
+class KActionCollection;
+class K3bFillStatusDisplay;
+class K3bProjectBurnDialog;
+class K3bToolBox;
+class K3bProjectPlugin;
+
+
+/**
+ *
+ */
+class K3bView : public QWidget, public KXMLGUIClient
+{
+ Q_OBJECT
+
+ public:
+ /**
+ *
+ */
+ K3bView( K3bDoc* pDoc, QWidget* parent, const char *name = 0 );
+ virtual ~K3bView();
+
+ /**
+ * returns a pointer to the document connected to the view
+ * @deprecated use doc()
+ */
+ K3bDoc* getDocument() const { return m_doc; }
+ K3bDoc* doc() const { return m_doc; }
+
+ void setMainWidget( QWidget* );
+
+ public slots:
+ /**
+ * Default impl. brings up the burnDialog via newBurnDialog() with writing
+ */
+ virtual void slotBurn();
+
+ /**
+ * Default impl. brings up the burnDialog via newBurnDialog() without writing
+ */
+ virtual void slotProperties();
+
+ /**
+ * Add an url to the doc. The default implementation simply calls
+ * addUrls.
+ */
+ virtual void addUrl( const KURL& );
+
+ /**
+ * Add urls to the doc. The default implementation calls doc()->addUrls.
+ */
+ virtual void addUrls( const KURL::List& );
+
+ protected:
+ /**
+ * Protected since the BurnDialog is not part of the API.
+ */
+ virtual K3bProjectBurnDialog* newBurnDialog( QWidget* = 0, const char* = 0 ) = 0;
+
+ /**
+ * Call this to add the projectplugin buttons to the toolbox. It is not called
+ * automatically to make it possible to add other buttons before.
+ *
+ * @param projectType the type of the project (@see K3bProjectPlugin)
+ */
+ void addPluginButtons( int projectType );
+
+ K3bFillStatusDisplay* fillStatusDisplay() const { return m_fillStatusDisplay; }
+ K3bToolBox* toolBox() const { return m_toolBox; }
+
+ private slots:
+ void slotPluginButtonClicked();
+
+ private:
+ K3bDoc* m_doc;
+ K3bFillStatusDisplay* m_fillStatusDisplay;
+ K3bToolBox* m_toolBox;
+
+ QPtrDict<K3bProjectPlugin> m_plugins;
+};
+
+#endif // K3BVIEW_H
diff --git a/src/projects/kostore/Makefile.am b/src/projects/kostore/Makefile.am
new file mode 100644
index 0000000..d99ae86
--- /dev/null
+++ b/src/projects/kostore/Makefile.am
@@ -0,0 +1,11 @@
+
+KDE_CXXFLAGS = $(USE_RTTI)
+noinst_LTLIBRARIES = libkostore.la
+INCLUDES = $(all_includes)
+
+####### Files
+
+libkostore_la_LIBADD = $(LIB_KIO)
+libkostore_la_SOURCES = koStore.cc koZipStore.cc koStoreBase.cc
+#libkostore_la_LDFLAGS = $(all_libraries) -version-info 3:0:0 $(KDE_LDFLAGS) -no-undefined
+#include_HEADERS = koStore.h
diff --git a/src/projects/kostore/README.k3b b/src/projects/kostore/README.k3b
new file mode 100644
index 0000000..dbf4db1
--- /dev/null
+++ b/src/projects/kostore/README.k3b
@@ -0,0 +1,2 @@
+This is a stripped down version of the KoStore lib from Koffice.
+It only contains the Zip backend.
diff --git a/src/projects/kostore/SPEC b/src/projects/kostore/SPEC
new file mode 100644
index 0000000..e72286a
--- /dev/null
+++ b/src/projects/kostore/SPEC
@@ -0,0 +1,122 @@
+-------------------------------------------------------------------------------
+- -
+- KOffice Storage Format Specification - Version 2.3 -
+- -
+- by Werner, last changed: 20020306 by Werner Trobin -
+- -
+- History : -
+- Version 1.0 : binary store -
+- Version 2.0 : tar.gz store -
+- Version 2.1 : cleaned up -
+- version 2.2 : shaheed Put each part into its own directory to allow -
+- one filter to easily embed the results of another -
+- and also to have its own documentinfo etc. -
+- Added description of naming convention. -
+- Version 2.3 : werner Allow the usage of relative links. It is now -
+- possible to refer to any "embedded" image or part -
+- via a plain relative URL as you all know it. -
+- -
+-------------------------------------------------------------------------------
+
+The purpose of this document is to define a common KOffice Storage Structure.
+Torben, Reggie, and all the others agreed on storing embedded KOffice Parts
+and binary data (e.g. pictures, movies, sounds) via a simple tar.gz-structure.
+The support class for the tar format is kdelibs/kio/ktar.*, written by Torben
+and finished by David.
+
+The obvious benefits of this type of storage are:
+ - It's 100% non- proprietary as it uses only the already available formats
+ (XML, pictures, tar.gz, ...) and tools (tar, gzip).
+ - It enables anybody to edit the document directly; for instance, to update
+ an image (faster than launching the application), or to write scripts
+ that generate KOffice documents ! :)
+ - It is also easy to write an import filter for any other office-suite
+ application out there by reading the tar.gz file and extracting the XML out
+ of it (at the worst, the user can extract the XML file by himself, but then
+ the import loses embedded Parts and pictures).
+
+The tar.gz format also generates much smaller files than the old binary
+store, since everything's gzipped.
+
+Name of the KOffice Files
+-------------------------
+
+As some people suggested, using a "tgz"-ending is confusing; it's been dropped.
+Instead, we use the "normal" endings like ".kwd", ".ksp", ".kpr", etc. To recognize
+KOffice documents without a proper extension David Faure <faure@kde.org>
+added some magic numbers to the gzip header (to see what I'm talking about
+please use the "file" command on a KOffice document or see
+http://lists.kde.org/?l=koffice-devel&m=98609092618214&w=2);
+
+External Structure
+------------------
+
+Here is a simple example to demonstrate the structure of a KOffice document.
+Assume you have to write a lab-report. You surely will have some text, the
+readings, some formulas and a few pictures (e.g. circuit diagram,...).
+The main document will be a KWord-file. In this file you embed some KSpread-
+tables, some KChart-diagramms, the KFormulas, and some picture-frames. You save
+the document as "lab-report.kwd". Here is what the contents of the
+tar.gz file will look like :
+
+lab-report.kwd:
+---------------
+maindoc.xml -- The main XML file containing the KWord document.
+documentinfo.xml -- Author and other "metadata" for KWord document.
+pictures/ -- Pictures embedded in the main KWord document.
+pictures/picture0.jpg
+pictures/picture1.bmp
+cliparts/ -- Cliparts embedded in the main KWord document.
+cliparts/clipart0.wmf
+part0/maindoc.xml -- for instance a KSpread embedded table.
+part0/documentinfo.xml -- Author and other "metadata" for KSpread table.
+part0/part1/maindoc.xml -- say a KChart diagram within the KSpread table.
+part1/maindoc.xml -- say a KChart diagram.
+part2/maindoc.xml -- why not a KIllustrator drawing.
+part2/pictures/ -- Pictures embedded in the KIllustrator document.
+part2/pictures/picture0.jpg
+part2/pictures/picture1.bmp
+part2/cliparts/ -- Cliparts embedded in the KIllustrator document.
+part2/cliparts/clipart0.wmf
+...
+
+Internal Name
+-------------
+
+- Absolute references:
+ The API provided by this specification does not require application writers
+ or filter writers to know the details of the external structure:
+
+ tar:/documentinfo.xml is saved as documentinfo.xml
+ tar:/0 is saved as part0/maindoc.xml
+ tar:/0/documentinfo.xml is saved as part0/documentinfo.xml
+ tar:/0/1 is saved as part0/part1/maindoc.xml
+ tar:/0/1/pictures/picture0.png
+ is saved as part0/part1/pictures/picture0.png
+ tar:/Table1/0 is saved as Table1/part0/maindoc.xml
+
+ Note that this is the structure as of version 2.2 of this specification.
+ The only other format shipped with KDE2.0 is converted (on reading) to look
+ like this through the services of the "Internal Name".
+
+ If the document does not contain any other Parts or pictures, then the
+ maindoc.xml and documentinfo.xml files are tarred and gzipped alone,
+ and saved with the proper extension (.kwd for KWord, .ksp for KSpread,
+ etc.).
+ The plan is to use relative paths everywhere, so please try not to use
+ absolute paths unless neccessary.
+
+- Relative references:
+ To allow parts to be self-contained, and to ease the work of filter
+ developers version 2.3 features relative links within the storage.
+ This means that the KoStore now has a "state" as in "there is something
+ like a current directory". You can specify a link like
+ "pictures/picture0.png" and depending on the current directory this will
+ be mapped to some absolute path. The surrounding code has to ensure that
+ the current path is maintained correctly, but due to that we can get rid
+ of the ugly prefix thingy.
+
+
+Thank you for your attention,
+Werner <trobin@kde.org> and David <faure@kde.org>
+(edited by Chris Lee <lee@azsites.com> for grammer, spelling, and formatting)
diff --git a/src/projects/kostore/koStore.cc b/src/projects/kostore/koStore.cc
new file mode 100644
index 0000000..5e7fd06
--- /dev/null
+++ b/src/projects/kostore/koStore.cc
@@ -0,0 +1,629 @@
+// -*- c-basic-offset: 2 -*-
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ Copyright (C) 2000-2002 David Faure <faure@kde.org>, Werner Trobin <trobin@kde.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 <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "koStore.h"
+//#include "koTarStore.h"
+#include "koZipStore.h"
+//#include "koDirectoryStore.h"
+
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qdir.h>
+
+#include <kurl.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+
+//#define DefaultFormat KoStore::Tar
+#define DefaultFormat KoStore::Zip
+
+const int KoStore::s_area = 30002;
+
+KoStore::Backend KoStore::determineBackend( QIODevice* dev )
+{
+ unsigned char buf[5];
+ if ( dev->readBlock( (char *)buf, 4 ) < 4 )
+ return DefaultFormat; // will create a "bad" store (bad()==true)
+ if ( buf[0] == 0037 && buf[1] == 0213 ) // gzip -> tar.gz
+ return Tar;
+ if ( buf[0] == 'P' && buf[1] == 'K' && buf[2] == 3 && buf[3] == 4 )
+ return Zip;
+ return DefaultFormat; // fallback
+}
+
+KoStore* KoStore::createStore( const QString& fileName, Mode mode, const QCString & appIdentification, Backend backend )
+{
+ if ( backend == Auto ) {
+ if ( mode == KoStore::Write )
+ backend = DefaultFormat;
+ else
+ {
+ QFileInfo inf( fileName );
+ if ( inf.isDir() )
+ backend = Directory;
+ else
+ {
+ QFile file( fileName );
+ if ( file.open( IO_ReadOnly ) )
+ backend = determineBackend( &file );
+ else
+ backend = DefaultFormat; // will create a "bad" store (bad()==true)
+ }
+ }
+ }
+ switch ( backend )
+ {
+// case Tar:
+// return new KoTarStore( fileName, mode, appIdentification );
+ case Zip:
+ return new KoZipStore( fileName, mode, appIdentification );
+// case Directory:
+// return new KoDirectoryStore( fileName /* should be a dir name.... */, mode );
+ default:
+ kdWarning(s_area) << "Unsupported backend requested for KoStore : " << backend << endl;
+ return 0L;
+ }
+}
+
+KoStore* KoStore::createStore( QIODevice *device, Mode mode, const QCString & appIdentification, Backend backend )
+{
+ if ( backend == Auto )
+ {
+ if ( mode == KoStore::Write )
+ backend = DefaultFormat;
+ else {
+ if ( device->open( IO_ReadOnly ) ) {
+ backend = determineBackend( device );
+ device->close();
+ }
+ }
+ }
+ switch ( backend )
+ {
+// case Tar:
+// return new KoTarStore( device, mode, appIdentification );
+// case Directory:
+// kdError(s_area) << "Can't create a Directory store for a memory buffer!" << endl;
+ // fallback
+ case Zip:
+ return new KoZipStore( device, mode, appIdentification );
+ default:
+ kdWarning(s_area) << "Unsupported backend requested for KoStore : " << backend << endl;
+ return 0L;
+ }
+}
+
+KoStore* KoStore::createStore( QWidget* window, const KURL& url, Mode mode, const QCString & appIdentification, Backend backend )
+{
+ if ( url.isLocalFile() )
+ return createStore(url.path(), mode, appIdentification, backend );
+
+ QString tmpFile;
+ if ( mode == KoStore::Write )
+ {
+ if ( backend == Auto )
+ backend = DefaultFormat;
+ }
+ else
+ {
+ const bool downloaded =
+ KIO::NetAccess::download( url, tmpFile, window );
+
+ if (!downloaded)
+ {
+ kdError(s_area) << "Could not download file!" << endl;
+ backend = DefaultFormat; // will create a "bad" store (bad()==true)
+ }
+ else if ( backend == Auto )
+ {
+ QFile file( tmpFile );
+ if ( file.open( IO_ReadOnly ) )
+ {
+ backend = determineBackend( &file );
+ file.close();
+ }
+ }
+ }
+ switch ( backend )
+ {
+// case Tar:
+// return new KoTarStore( window, url, tmpFile, mode, appIdentification );
+ case Zip:
+ return new KoZipStore( window, url, tmpFile, mode, appIdentification );
+ default:
+ kdWarning(s_area) << "Unsupported backend requested for KoStore (KURL) : " << backend << endl;
+ KMessageBox::sorry( window,
+ i18n("The directory mode is not supported for remote locations."),
+ i18n("KOffice Storage"));
+ return 0L;
+ }
+}
+
+namespace {
+ const char* const ROOTPART = "root";
+ const char* const MAINNAME = "maindoc.xml";
+}
+
+bool KoStore::init( Mode _mode )
+{
+ d = 0;
+ m_bIsOpen = false;
+ m_mode = _mode;
+ m_stream = 0;
+
+ // Assume new style names.
+ m_namingVersion = NAMING_VERSION_2_2;
+ return true;
+}
+
+KoStore::~KoStore()
+{
+ delete m_stream;
+}
+
+bool KoStore::open( const QString & _name )
+{
+ // This also converts from relative to absolute, i.e. merges the currentPath()
+ m_sName = toExternalNaming( _name );
+
+ if ( m_bIsOpen )
+ {
+ kdWarning(s_area) << "KoStore: File is already opened" << endl;
+ //return KIO::ERR_INTERNAL;
+ return false;
+ }
+
+ if ( m_sName.length() > 512 )
+ {
+ kdError(s_area) << "KoStore: Filename " << m_sName << " is too long" << endl;
+ //return KIO::ERR_MALFORMED_URL;
+ return false;
+ }
+
+ if ( m_mode == Write )
+ {
+ kdDebug(s_area) << "KoStore: opening for writing '" << m_sName << "'" << endl;
+ if ( m_strFiles.findIndex( m_sName ) != -1 ) // just check if it's there
+ {
+ kdWarning(s_area) << "KoStore: Duplicate filename " << m_sName << endl;
+ //return KIO::ERR_FILE_ALREADY_EXIST;
+ return false;
+ }
+
+ m_strFiles.append( m_sName );
+
+ m_iSize = 0;
+ if ( !openWrite( m_sName ) )
+ return false;
+ }
+ else if ( m_mode == Read )
+ {
+ kdDebug(s_area) << "Opening for reading '" << m_sName << "'" << endl;
+ if ( !openRead( m_sName ) )
+ return false;
+ }
+ else
+ //return KIO::ERR_UNSUPPORTED_ACTION;
+ return false;
+
+ m_bIsOpen = true;
+ return true;
+}
+
+bool KoStore::isOpen() const
+{
+ return m_bIsOpen;
+}
+
+bool KoStore::close()
+{
+ kdDebug(s_area) << "KoStore: Closing" << endl;
+
+ if ( !m_bIsOpen )
+ {
+ kdWarning(s_area) << "KoStore: You must open before closing" << endl;
+ //return KIO::ERR_INTERNAL;
+ return false;
+ }
+
+ bool ret = m_mode == Write ? closeWrite() : closeRead();
+
+ delete m_stream;
+ m_stream = 0L;
+ m_bIsOpen = false;
+ return ret;
+}
+
+QIODevice* KoStore::device() const
+{
+ if ( !m_bIsOpen )
+ kdWarning(s_area) << "KoStore: You must open before asking for a device" << endl;
+ if ( m_mode != Read )
+ kdWarning(s_area) << "KoStore: Can not get device from store that is opened for writing" << endl;
+ return m_stream;
+}
+
+QByteArray KoStore::read( unsigned long int max )
+{
+ QByteArray data; // Data is a QArray<char>
+
+ if ( !m_bIsOpen )
+ {
+ kdWarning(s_area) << "KoStore: You must open before reading" << endl;
+ data.resize( 0 );
+ return data;
+ }
+ if ( m_mode != Read )
+ {
+ kdError(s_area) << "KoStore: Can not read from store that is opened for writing" << endl;
+ data.resize( 0 );
+ return data;
+ }
+
+ if ( m_stream->atEnd() )
+ {
+ data.resize( 0 );
+ return data;
+ }
+
+ if ( max > m_iSize - m_stream->at() )
+ max = m_iSize - m_stream->at();
+ if ( max == 0 )
+ {
+ data.resize( 0 );
+ return data;
+ }
+
+ char *p = new char[ max ];
+ m_stream->readBlock( p, max );
+
+ data.setRawData( p, max );
+ return data;
+}
+
+Q_LONG KoStore::write( const QByteArray& data )
+{
+ return write( data.data(), data.size() ); // see below
+}
+
+Q_LONG KoStore::read( char *_buffer, Q_ULONG _len )
+{
+ if ( !m_bIsOpen )
+ {
+ kdError(s_area) << "KoStore: You must open before reading" << endl;
+ return -1;
+ }
+ if ( m_mode != Read )
+ {
+ kdError(s_area) << "KoStore: Can not read from store that is opened for writing" << endl;
+ return -1;
+ }
+
+ if ( m_stream->atEnd() )
+ return 0;
+
+ if ( _len > m_iSize - m_stream->at() )
+ _len = m_iSize - m_stream->at();
+ if ( _len == 0 )
+ return 0;
+
+ return m_stream->readBlock( _buffer, _len );
+}
+
+Q_LONG KoStore::write( const char* _data, Q_ULONG _len )
+{
+ if ( _len == 0L ) return 0;
+
+ if ( !m_bIsOpen )
+ {
+ kdError(s_area) << "KoStore: You must open before writing" << endl;
+ return 0L;
+ }
+ if ( m_mode != Write )
+ {
+ kdError(s_area) << "KoStore: Can not write to store that is opened for reading" << endl;
+ return 0L;
+ }
+
+ int nwritten = m_stream->writeBlock( _data, _len );
+ Q_ASSERT( nwritten == (int)_len );
+ m_iSize += nwritten;
+
+ return nwritten;
+}
+
+QIODevice::Offset KoStore::size() const
+{
+ if ( !m_bIsOpen )
+ {
+ kdWarning(s_area) << "KoStore: You must open before asking for a size" << endl;
+ return static_cast<QIODevice::Offset>(-1);
+ }
+ if ( m_mode != Read )
+ {
+ kdWarning(s_area) << "KoStore: Can not get size from store that is opened for writing" << endl;
+ return static_cast<QIODevice::Offset>(-1);
+ }
+ return m_iSize;
+}
+
+bool KoStore::enterDirectory( const QString& directory )
+{
+ //kdDebug(s_area) << "KoStore::enterDirectory " << directory << endl;
+ int pos;
+ bool success = true;
+ QString tmp( directory );
+
+ while ( ( pos = tmp.find( '/' ) ) != -1 &&
+ ( success = enterDirectoryInternal( tmp.left( pos ) ) ) )
+ tmp = tmp.mid( pos + 1 );
+
+ if ( success && !tmp.isEmpty() )
+ return enterDirectoryInternal( tmp );
+ return success;
+}
+
+bool KoStore::leaveDirectory()
+{
+ if ( m_currentPath.isEmpty() )
+ return false;
+
+ m_currentPath.pop_back();
+
+ return enterAbsoluteDirectory( expandEncodedDirectory( currentPath() ) );
+}
+
+QString KoStore::currentDirectory() const
+{
+ return expandEncodedDirectory( currentPath() );
+}
+
+QString KoStore::currentPath() const
+{
+ QString path;
+ QStringList::ConstIterator it = m_currentPath.begin();
+ QStringList::ConstIterator end = m_currentPath.end();
+ for ( ; it != end; ++it ) {
+ path += *it;
+ path += '/';
+ }
+ return path;
+}
+
+void KoStore::pushDirectory()
+{
+ m_directoryStack.push( currentPath() );
+}
+
+void KoStore::popDirectory()
+{
+ m_currentPath.clear();
+ enterAbsoluteDirectory( QString::null );
+ enterDirectory( m_directoryStack.pop() );
+}
+
+bool KoStore::addLocalFile( const QString &fileName, const QString &destName )
+{
+ QFileInfo fi( fileName );
+ uint size = fi.size();
+ QFile file( fileName );
+ if ( !file.open( IO_ReadOnly ))
+ {
+ return false;
+ }
+
+ if ( !open ( destName ) )
+ {
+ return false;
+ }
+
+ QByteArray data ( 8 * 1024 );
+
+ uint total = 0;
+ for ( int block = 0; ( block = file.readBlock ( data.data(), data.size() ) ) > 0; total += block )
+ {
+ data.resize(block);
+ if ( write( data ) != block )
+ return false;
+ data.resize(8*1024);
+ }
+ Q_ASSERT( total == size );
+
+ close();
+ file.close();
+
+ return true;
+}
+
+bool KoStore::extractFile ( const QString &srcName, const QString &fileName )
+{
+ if ( !open ( srcName ) )
+ return false;
+
+ QFile file( fileName );
+
+ if( !file.open ( IO_WriteOnly ) )
+ {
+ close();
+ return false;
+ }
+
+ QByteArray data ( 8 * 1024 );
+ uint total = 0;
+ for( int block = 0; ( block = read ( data.data(), data.size() ) ) > 0; total += block )
+ {
+ file.writeBlock ( data.data(), block );
+ }
+
+ if( size() != static_cast<QIODevice::Offset>(-1) )
+ Q_ASSERT( total == size() );
+
+ file.close();
+ close();
+
+ return true;
+}
+
+QStringList KoStore::addLocalDirectory( const QString &dirPath, const QString &destName )
+{
+ QString dot = ".";
+ QString dotdot = "..";
+ QStringList content;
+
+ QDir dir(dirPath);
+ if ( !dir.exists() )
+ return 0;
+
+ QStringList files = dir.entryList();
+ for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it )
+ {
+ if ( *it != dot && *it != dotdot )
+ {
+ QString currentFile = dirPath + "/" + *it;
+ QString dest = destName.isEmpty() ? *it : (destName + "/" + *it);
+
+ QFileInfo fi ( currentFile );
+ if ( fi.isFile() )
+ {
+ addLocalFile ( currentFile, dest );
+ content.append(dest);
+ }
+ else if ( fi.isDir() )
+ {
+ content += addLocalDirectory ( currentFile, dest );
+ }
+ }
+ }
+
+ return content;
+}
+
+
+bool KoStore::at( QIODevice::Offset pos )
+{
+ return m_stream->at( pos );
+}
+
+QIODevice::Offset KoStore::at() const
+{
+ return m_stream->at();
+}
+
+bool KoStore::atEnd() const
+{
+ return m_stream->atEnd();
+}
+
+// See the specification for details of what this function does.
+QString KoStore::toExternalNaming( const QString & _internalNaming ) const
+{
+ if ( _internalNaming == ROOTPART )
+ return expandEncodedDirectory( currentPath() ) + MAINNAME;
+
+ QString intern;
+ if ( _internalNaming.startsWith( "tar:/" ) ) // absolute reference
+ intern = _internalNaming.mid( 5 ); // remove protocol
+ else
+ intern = currentPath() + _internalNaming;
+
+ return expandEncodedPath( intern );
+}
+
+QString KoStore::expandEncodedPath( QString intern ) const
+{
+ if ( m_namingVersion == NAMING_VERSION_RAW )
+ return intern;
+
+ QString result;
+ int pos;
+
+ if ( ( pos = intern.findRev( '/', -1 ) ) != -1 ) {
+ result = expandEncodedDirectory( intern.left( pos ) ) + '/';
+ intern = intern.mid( pos + 1 );
+ }
+
+ // Now process the filename. If the first character is numeric, we have
+ // a main document.
+ if ( QChar(intern.at(0)).isDigit() )
+ {
+ // If this is the first part name, check if we have a store with
+ // old-style names.
+ if ( ( m_namingVersion == NAMING_VERSION_2_2 ) &&
+ ( m_mode == Read ) &&
+ ( fileExists( result + "part" + intern + ".xml" ) ) )
+ m_namingVersion = NAMING_VERSION_2_1;
+
+ if ( m_namingVersion == NAMING_VERSION_2_1 )
+ result = result + "part" + intern + ".xml";
+ else
+ result = result + "part" + intern + "/" + MAINNAME;
+ }
+ else
+ result += intern;
+ return result;
+}
+
+QString KoStore::expandEncodedDirectory( QString intern ) const
+{
+ if ( m_namingVersion == NAMING_VERSION_RAW )
+ return intern;
+
+ QString result;
+ int pos;
+ while ( ( pos = intern.find( '/' ) ) != -1 ) {
+ if ( QChar(intern.at(0)).isDigit() )
+ result += "part";
+ result += intern.left( pos + 1 ); // copy numbers (or "pictures") + "/"
+ intern = intern.mid( pos + 1 ); // remove the dir we just processed
+ }
+
+ if ( QChar(intern.at(0)).isDigit() )
+ result += "part";
+ result += intern;
+ return result;
+}
+
+bool KoStore::enterDirectoryInternal( const QString& directory )
+{
+ if ( enterRelativeDirectory( expandEncodedDirectory( directory ) ) )
+ {
+ m_currentPath.append( directory );
+ return true;
+ }
+ return false;
+}
+
+void KoStore::disallowNameExpansion( void )
+{
+ m_namingVersion = NAMING_VERSION_RAW;
+}
+
+bool KoStore::hasFile( const QString& fileName ) const
+{
+ return fileExists( toExternalNaming( currentPath() + fileName ) );
+}
diff --git a/src/projects/kostore/koStore.h b/src/projects/kostore/koStore.h
new file mode 100644
index 0000000..a22c5f3
--- /dev/null
+++ b/src/projects/kostore/koStore.h
@@ -0,0 +1,384 @@
+// -*- c-basic-offset: 2 -*-
+/* This file is part of the KDE project
+ Copyright (C) 1998, 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 __koStore_h_
+#define __koStore_h_
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qiodevice.h>
+#include <qvaluestack.h>
+//#include <koffice_export.h>
+#include <kdemacros.h>
+
+#define KOSTORE_EXPORT KDE_EXPORT
+
+class QWidget;
+
+class KURL;
+
+/**
+ * Saves and loads KOffice documents using various backends. Currently supported
+ * backends are ZIP, tar and directory.
+ * We call a "store" the file on the hard disk (the one the users sees)
+ * and call a "file" a file inside the store.
+ */
+class KoStore
+{
+public:
+
+ enum Mode { Read, Write };
+ enum Backend { Auto, Tar, Zip, Directory };
+
+ /**
+ * Open a store (i.e. the representation on disk of a KOffice document).
+ *
+ * @param fileName the name of the file to open
+ * @param mode if KoStore::Read, open an existing store to read it.
+ * if KoStore::Write, create or replace a store.
+ * @param backend the backend to use for the data storage.
+ * Auto means automatically-determined for reading,
+ * and the current format (now Zip) for writing.
+ *
+ * @param appIdentification the application's mimetype,
+ * to be written in the file for "mime-magic" identification.
+ * Only meaningful if mode is Write, and if backend!=Directory.
+ */
+ static KoStore* createStore( const QString& fileName, Mode mode, const QCString & appIdentification = "", Backend backend = Auto );
+
+ /**
+ * Create a store for any kind of QIODevice: file, memory buffer...
+ * KoStore will take care of opening the QIODevice.
+ * This method doesn't support the Directory store!
+ */
+ static KoStore* createStore( QIODevice *device, Mode mode, const QCString & appIdentification = "", Backend backend = Auto );
+
+ /**
+ * Open a store (i.e. the representation on disk of a KOffice document).
+ *
+ * @param window associated window (for the progress bar dialog and authentication)
+ * @param url URL of the file to open
+ * @param mode if KoStore::Read, open an existing store to read it.
+ * if KoStore::Write, create or replace a store.
+ * @param backend the backend to use for the data storage.
+ * Auto means automatically-determined for reading,
+ * and the current format (now Zip) for writing.
+ *
+ * @param appIdentification the application's mimetype,
+ * to be written in the file for "mime-magic" identification.
+ * Only meaningful if mode is Write, and if backend!=Directory.
+ *
+ * If the file is remote, the backend Directory cannot be used!
+ *
+ * @since 1.4
+ * @bug saving not completely implemented (fixed temporary file)
+ */
+ static KoStore* createStore( QWidget* window, const KURL& url, Mode mode, const QCString & appIdentification = "", Backend backend = Auto );
+
+ /**
+ * Destroys the store (i.e. closes the file on the hard disk)
+ */
+ virtual ~KoStore();
+
+ /**
+ * Open a new file inside the store
+ * @param name The filename, internal representation ("root", "tar:/0"... ).
+ * If the tar:/ prefix is missing it's assumed to be a relative URI.
+ * @return true on success.
+ */
+ bool open( const QString & name );
+
+ /**
+ * Check whether a file inside the store is currently opened with open(),
+ * ready to be read or written.
+ * @return true if a file is currently opened.
+ */
+ bool isOpen() const;
+
+ /**
+ * Close the file inside the store
+ * @return true on success.
+ */
+ bool close();
+
+ /**
+ * Get a device for reading a file from the store directly
+ * (slightly faster than read() calls)
+ * You need to call @ref open first, and @ref close afterwards.
+ */
+ QIODevice* device() const;
+
+ /**
+ * Read data from the currently opened file. You can also use the streams
+ * for this.
+ */
+ QByteArray read( unsigned long int max );
+
+ /**
+ * Write data into the currently opened file. You can also use the streams
+ * for this.
+ */
+ Q_LONG write( const QByteArray& _data );
+
+ /**
+ * Read data from the currently opened file. You can also use the streams
+ * for this.
+ * @return size of data read, -1 on error
+ */
+ Q_LONG read( char *_buffer, Q_ULONG _len );
+
+ /**
+ * Write data into the currently opened file. You can also use the streams
+ * for this.
+ */
+ virtual Q_LONG write( const char* _data, Q_ULONG _len );
+
+ /**
+ * @return the size of the currently opened file, -1 on error.
+ * Can be used as an argument for the read methods, for instance
+ */
+ QIODevice::Offset size() const;
+
+ /**
+ * @return true if an error occurred
+ */
+ bool bad() const { return !m_bGood; } // :)
+
+ /**
+ * @return the mode used when opening, read or write
+ */
+ Mode mode() const { return m_mode; }
+
+ /**
+ * Enters one or multiple directories. In Read mode this actually
+ * checks whether the specified directories exist and returns false
+ * if they don't. In Write mode we don't create the directory, we
+ * just use the "current directory" to generate the absolute path
+ * if you pass a relative path (one not starting with tar:/) when
+ * opening a stream.
+ * Note: Operates on internal names
+ */
+ bool enterDirectory( const QString& directory );
+
+ /**
+ * Leaves a directory. Equivalent to "cd .."
+ * @return true on success, false if we were at the root already to
+ * make it possible to "loop to the root"
+ */
+ bool leaveDirectory();
+
+ /**
+ * Returns the current path including a trailing slash.
+ * Note: Returns a path in "internal name" style
+ */
+ QString currentPath() const;
+
+ /**
+ * Returns the current directory.
+ * Note: Returns a path in "internal name" style
+ */
+ QString currentDirectory() const;
+
+
+ /**
+ * Stacks the current directory. Restore the current path using
+ * @ref popDirectory .
+ */
+ void pushDirectory();
+
+ /**
+ * Restores the previously pushed directory. No-op if the stack is
+ * empty.
+ */
+ void popDirectory();
+
+ /**
+ * @return true if the given file exists in the current directory,
+ * i.e. if open(fileName) will work.
+ */
+ bool hasFile( const QString& fileName ) const;
+
+ /**
+ * Imports a local file into a store
+ * @param fileName file on hard disk
+ * @param destName file in the store
+ */
+ bool addLocalFile( const QString &fileName, const QString &destName );
+
+ /**
+ * Imports a local directory
+ * @param dirPath path to the directory on a disk
+ * @param dest path in the store where the directory should get saved
+ * @return the directory index
+ */
+ QStringList addLocalDirectory( const QString &dirPath, const QString &dest );
+
+
+ /**
+ * Extracts a file out of the store
+ * @param srcName file in the store
+ * @param fileName file on a disk
+ */
+ bool extractFile( const QString &srcName, const QString &fileName );
+
+ //@{
+ /// See QIODevice
+ bool at( QIODevice::Offset pos );
+ QIODevice::Offset at() const;
+ bool atEnd() const;
+ //@}
+
+ /**
+ * Do not expand file and directory names
+ * Useful when using KoStore on non-KOffice files.
+ * (This method should be called just after the constructor)
+ */
+ void disallowNameExpansion( void );
+
+protected:
+
+ KoStore() {}
+
+ /**
+ * Init store - called by constructor.
+ * @return true on success
+ */
+ virtual bool init( Mode mode );
+ /**
+ * Open the file @p name in the store, for writing
+ * On success, this method must set m_stream to a stream in which we can write.
+ * @param name "absolute path" (in the archive) to the file to open
+ * @return true on success
+ */
+ virtual bool openWrite( const QString& name ) = 0;
+ /**
+ * Open the file @p name in the store, for reading.
+ * On success, this method must set m_stream to a stream from which we can read,
+ * as well as setting m_iSize to the size of the file.
+ * @param name "absolute path" (in the archive) to the file to open
+ * @return true on success
+ */
+ virtual bool openRead( const QString& name ) = 0;
+
+ /**
+ * @return true on success
+ */
+ virtual bool closeRead() = 0;
+ /**
+ * @return true on success
+ */
+ virtual bool closeWrite() = 0;
+
+ /**
+ * Enter a subdirectory of the current directory.
+ * The directory might not exist yet in Write mode.
+ */
+ virtual bool enterRelativeDirectory( const QString& dirName ) = 0;
+ /**
+ * Enter a directory where we've been before.
+ * It is guaranteed to always exist.
+ */
+ virtual bool enterAbsoluteDirectory( const QString& path ) = 0;
+
+ /**
+ * Check if a file exists inside the store.
+ * @param absPath the absolute path inside the store, i.e. not relative to the current directory
+ */
+ virtual bool fileExists( const QString& absPath ) const = 0;
+
+private:
+ static Backend determineBackend( QIODevice* dev );
+
+ /**
+ * Conversion routine
+ * @param _internalNaming name used internally : "root", "tar:/0", ...
+ * @return the name used in the file, more user-friendly ("maindoc.xml",
+ * "part0/maindoc.xml", ...)
+ * Examples:
+ *
+ * tar:/0 is saved as part0/maindoc.xml
+ * tar:/0/1 is saved as part0/part1/maindoc.xml
+ * tar:/0/1/pictures/picture0.png is saved as part0/part1/pictures/picture0.png
+ *
+ * see specification (koffice/lib/store/SPEC) for details.
+ */
+ QString toExternalNaming( const QString & _internalNaming ) const;
+
+ /**
+ * Expands a full path name for a stream (directories+filename)
+ */
+ QString expandEncodedPath( QString intern ) const;
+
+ /**
+ * Expands only directory names(!)
+ * Needed for the path handling code, as we only operate on internal names
+ */
+ QString expandEncodedDirectory( QString intern ) const;
+
+ mutable enum
+ {
+ NAMING_VERSION_2_1,
+ NAMING_VERSION_2_2,
+ NAMING_VERSION_RAW ///< Never expand file and directory names
+ } m_namingVersion;
+
+ /**
+ * Enter *one* single directory. Nothing like foo/bar/bleh allowed.
+ * Performs some checking when in Read mode
+ */
+ bool enterDirectoryInternal( const QString& directory );
+
+protected:
+
+ Mode m_mode;
+
+ /// Store the filenames (with full path inside the archive) when writing, to avoid duplicates
+ QStringList m_strFiles;
+
+ /// The "current directory" (path)
+ QStringList m_currentPath;
+
+ /// Used to push/pop directories to make it easy to save/restore the state
+ QValueStack<QString> m_directoryStack;
+
+ /// Current filename (between an open() and a close())
+ QString m_sName;
+ /// Current size of the file named m_sName
+ QIODevice::Offset m_iSize;
+
+ /// The stream for the current read or write operation
+ QIODevice * m_stream;
+
+ bool m_bIsOpen;
+ /// Must be set by the constructor.
+ bool m_bGood;
+
+ static const int s_area;
+
+private:
+ KoStore( const KoStore& store ); ///< don't copy
+ KoStore& operator=( const KoStore& store ); ///< don't assign
+
+ class Private;
+ Private * d;
+
+};
+
+#endif
diff --git a/src/projects/kostore/koStoreBase.cc b/src/projects/kostore/koStoreBase.cc
new file mode 100644
index 0000000..a9cc63e
--- /dev/null
+++ b/src/projects/kostore/koStoreBase.cc
@@ -0,0 +1,29 @@
+//
+/* This file is part of the KDE project
+ Copyright 2004 Nicolas GOUTTE <goutte@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "koStoreBase.h"
+
+KoStoreBase::KoStoreBase(void) : m_fileMode(Local), m_window(0)
+{
+}
+
+KoStoreBase::~KoStoreBase(void)
+{
+}
diff --git a/src/projects/kostore/koStoreBase.h b/src/projects/kostore/koStoreBase.h
new file mode 100644
index 0000000..0987577
--- /dev/null
+++ b/src/projects/kostore/koStoreBase.h
@@ -0,0 +1,51 @@
+//
+/* This file is part of the KDE project
+ Copyright 2004 Nicolas GOUTTE <goutte@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KOSTORE_BASE_H
+#define KOSTORE_BASE_H
+
+#include <kurl.h>
+
+#include "koStore.h"
+
+/**
+ * Helper class for KoStore (mainly for remote file support)
+ * @since 1.4
+ */
+class KoStoreBase : public KoStore
+{
+public:
+ KoStoreBase(void);
+ virtual ~KoStoreBase(void);
+public:
+ enum FileMode { /*Bad=0,*/ Local=1, RemoteRead, RemoteWrite };
+
+protected:
+ /**
+ * original URL of the remote file
+ * (undefined for a local file)
+ */
+ KURL m_url;
+ FileMode m_fileMode;
+ QString m_localFileName;
+ QWidget* m_window;
+};
+
+#endif //KOSTORE_BASE_H
diff --git a/src/projects/kostore/koStoreDevice.h b/src/projects/kostore/koStoreDevice.h
new file mode 100644
index 0000000..b245d60
--- /dev/null
+++ b/src/projects/kostore/koStoreDevice.h
@@ -0,0 +1,88 @@
+/* This file is part of the KDE project
+ 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 koStoreDevice_h
+#define koStoreDevice_h
+
+#include "koStore.h"
+
+/**
+ * This class implements a QIODevice around KoStore, so that
+ * it can be used to create a QDomDocument from it, to be written or read
+ * using QDataStream or to be written using QTextStream
+ */
+class KoStoreDevice : public QIODevice
+{
+public:
+ /// Note: KoStore::open() should be called before calling this.
+ KoStoreDevice( KoStore * store ) : m_store(store) {
+ setType( IO_Direct );
+ }
+ ~KoStoreDevice() {}
+
+ bool open( int m ) {
+ if ( m & IO_ReadOnly )
+ return ( m_store->mode() == KoStore::Read );
+ if ( m & IO_WriteOnly )
+ return ( m_store->mode() == KoStore::Write );
+ return false;
+ }
+ void close() { }
+ void flush() { }
+
+ Offset size() const {
+ if ( m_store->mode() == KoStore::Read )
+ return m_store->size();
+ else
+ return 0xffffffff;
+ }
+
+ virtual Q_LONG readBlock( char *data, Q_ULONG maxlen ) { return m_store->read(data, maxlen); }
+ virtual Q_LONG writeBlock( const char *data, Q_ULONG len ) { return m_store->write( data, len ); }
+ // Not virtual, only to uncover shadow
+ Q_LONG writeBlock( const QByteArray& data ) { return QIODevice::writeBlock( data ); }
+
+ int getch() {
+ char c[2];
+ if ( m_store->read(c, 1) == -1)
+ return -1;
+ else
+ return c[0];
+ }
+ int putch( int _c ) {
+ char c[2];
+ c[0] = _c;
+ c[1] = 0;
+ if (m_store->write( c, 1 ) == 1)
+ return _c;
+ else
+ return -1;
+ }
+ int ungetch( int ) { return -1; } // unsupported
+
+ // See QIODevice
+ virtual bool at( Offset pos ) { return m_store->at(pos); }
+ virtual Offset at() const { return m_store->at(); }
+ virtual bool atEnd() const { return m_store->atEnd(); }
+
+protected:
+ KoStore * m_store;
+};
+
+#endif
diff --git a/src/projects/kostore/koZipStore.cc b/src/projects/kostore/koZipStore.cc
new file mode 100644
index 0000000..ed3fec4
--- /dev/null
+++ b/src/projects/kostore/koZipStore.cc
@@ -0,0 +1,237 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000-2002 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 "koZipStore.h"
+
+#include <qbuffer.h>
+
+#include <kzip.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kurl.h>
+#include <kio/netaccess.h>
+#if ! KDE_IS_VERSION( 3, 4, 1 )
+#include <qdir.h>
+#include <qfileinfo.h>
+#endif
+
+KoZipStore::KoZipStore( const QString & _filename, Mode _mode, const QCString & appIdentification )
+{
+ kdDebug(s_area) << "KoZipStore Constructor filename = " << _filename
+ << " mode = " << int(_mode)
+ << " mimetype = " << appIdentification << endl;
+
+ m_pZip = new KZip( _filename );
+
+#if ! KDE_IS_VERSION( 3, 4, 1 )
+ // Workaround for KZip KSaveFile double deletion in kdelibs-3.4,
+ // when trying to write to a non-writable directory.
+ QDir dir( QFileInfo( _filename ).dir() );
+ if (_mode == Write && !QFileInfo( dir.path() ).isWritable() )
+ {
+ kdWarning(s_area) << dir.path() << " isn't writable" << endl;
+ m_bGood = false;
+ m_currentDir = 0;
+ KoStore::init( _mode );
+ }
+ else
+#endif
+ {
+ m_bGood = init( _mode, appIdentification ); // open the zip file and init some vars
+ }
+}
+
+KoZipStore::KoZipStore( QIODevice *dev, Mode mode, const QCString & appIdentification )
+{
+ m_pZip = new KZip( dev );
+ m_bGood = init( mode, appIdentification );
+}
+
+KoZipStore::KoZipStore( QWidget* window, const KURL & _url, const QString & _filename, Mode _mode, const QCString & appIdentification )
+{
+ kdDebug(s_area) << "KoZipStore Constructor url" << _url.prettyURL()
+ << " filename = " << _filename
+ << " mode = " << int(_mode)
+ << " mimetype = " << appIdentification << endl;
+
+ m_url = _url;
+ m_window = window;
+
+ if ( _mode == KoStore::Read )
+ {
+ m_fileMode = KoStoreBase::RemoteRead;
+ m_localFileName = _filename;
+
+ }
+ else
+ {
+ m_fileMode = KoStoreBase::RemoteWrite;
+ m_localFileName = "/tmp/kozip"; // ### FIXME with KTempFile
+ }
+
+ m_pZip = new KZip( m_localFileName );
+ m_bGood = init( _mode, appIdentification ); // open the zip file and init some vars
+}
+
+KoZipStore::~KoZipStore()
+{
+ kdDebug(s_area) << "KoZipStore::~KoZipStore" << endl;
+ m_pZip->close();
+ delete m_pZip;
+
+ // Now we have still some job to do for remote files.
+ if ( m_fileMode == KoStoreBase::RemoteRead )
+ {
+ KIO::NetAccess::removeTempFile( m_localFileName );
+ }
+ else if ( m_fileMode == KoStoreBase::RemoteWrite )
+ {
+ KIO::NetAccess::upload( m_localFileName, m_url, m_window );
+ // ### FIXME: delete temp file
+ }
+}
+
+bool KoZipStore::init( Mode _mode, const QCString& appIdentification )
+{
+ KoStore::init( _mode );
+ m_currentDir = 0;
+ bool good = m_pZip->open( _mode == Write ? IO_WriteOnly : IO_ReadOnly );
+
+ if ( good && _mode == Read )
+ good = m_pZip->directory() != 0;
+ else if ( good && _mode == Write )
+ {
+ //kdDebug(s_area) << "KoZipStore::init writing mimetype " << appIdentification << endl;
+
+ m_pZip->setCompression( KZip::NoCompression );
+ m_pZip->setExtraField( KZip::NoExtraField );
+ // Write identification
+ (void)m_pZip->writeFile( "mimetype", "", "", appIdentification.length(), appIdentification.data() );
+ m_pZip->setCompression( KZip::DeflateCompression );
+ // We don't need the extra field in KOffice - so we leave it as "no extra field".
+ }
+ return good;
+}
+
+bool KoZipStore::openWrite( const QString& name )
+{
+#if 0
+ // Prepare memory buffer for writing
+ m_byteArray.resize( 0 );
+ m_stream = new QBuffer( m_byteArray );
+ m_stream->open( IO_WriteOnly );
+ return true;
+#endif
+ m_stream = 0L; // Don't use!
+ return m_pZip->prepareWriting( name, "", "" /*m_pZip->rootDir()->user(), m_pZip->rootDir()->group()*/, 0 );
+}
+
+bool KoZipStore::openRead( const QString& name )
+{
+ const KArchiveEntry * entry = m_pZip->directory()->entry( name );
+ if ( entry == 0L )
+ {
+ //kdWarning(s_area) << "Unknown filename " << name << endl;
+ //return KIO::ERR_DOES_NOT_EXIST;
+ return false;
+ }
+ if ( entry->isDirectory() )
+ {
+ kdWarning(s_area) << name << " is a directory !" << endl;
+ //return KIO::ERR_IS_DIRECTORY;
+ return false;
+ }
+ // Must cast to KZipFileEntry, not only KArchiveFile, because device() isn't virtual!
+ const KZipFileEntry * f = static_cast<const KZipFileEntry *>(entry);
+ delete m_stream;
+ m_stream = f->device();
+ m_iSize = f->size();
+ return true;
+}
+
+Q_LONG KoZipStore::write( const char* _data, Q_ULONG _len )
+{
+ if ( _len == 0L ) return 0;
+ //kdDebug(s_area) << "KoZipStore::write " << _len << endl;
+
+ if ( !m_bIsOpen )
+ {
+ kdError(s_area) << "KoStore: You must open before writing" << endl;
+ return 0L;
+ }
+ if ( m_mode != Write )
+ {
+ kdError(s_area) << "KoStore: Can not write to store that is opened for reading" << endl;
+ return 0L;
+ }
+
+ m_iSize += _len;
+ if ( m_pZip->writeData( _data, _len ) ) // writeData returns a bool!
+ return _len;
+ return 0L;
+}
+
+bool KoZipStore::closeWrite()
+{
+ kdDebug(s_area) << "Wrote file " << m_sName << " into ZIP archive. size "
+ << m_iSize << endl;
+ return m_pZip->doneWriting( m_iSize );
+#if 0
+ if ( !m_pZip->writeFile( m_sName , "user", "group", m_iSize, m_byteArray.data() ) )
+ kdWarning( s_area ) << "Failed to write " << m_sName << endl;
+ m_byteArray.resize( 0 ); // save memory
+ return true;
+#endif
+}
+
+bool KoZipStore::enterRelativeDirectory( const QString& dirName )
+{
+ if ( m_mode == Read ) {
+ if ( !m_currentDir ) {
+ m_currentDir = m_pZip->directory(); // initialize
+ Q_ASSERT( m_currentPath.isEmpty() );
+ }
+ const KArchiveEntry *entry = m_currentDir->entry( dirName );
+ if ( entry && entry->isDirectory() ) {
+ m_currentDir = dynamic_cast<const KArchiveDirectory*>( entry );
+ return m_currentDir != 0;
+ }
+ return false;
+ }
+ else // Write, no checking here
+ return true;
+}
+
+bool KoZipStore::enterAbsoluteDirectory( const QString& path )
+{
+ if ( path.isEmpty() )
+ {
+ m_currentDir = 0;
+ return true;
+ }
+ m_currentDir = dynamic_cast<const KArchiveDirectory*>( m_pZip->directory()->entry( path ) );
+ Q_ASSERT( m_currentDir );
+ return m_currentDir != 0;
+}
+
+bool KoZipStore::fileExists( const QString& absPath ) const
+{
+ const KArchiveEntry *entry = m_pZip->directory()->entry( absPath );
+ return entry && entry->isFile();
+}
diff --git a/src/projects/kostore/koZipStore.h b/src/projects/kostore/koZipStore.h
new file mode 100644
index 0000000..e87f5e4
--- /dev/null
+++ b/src/projects/kostore/koZipStore.h
@@ -0,0 +1,61 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 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 koZipStore_h
+#define koZipStore_h
+
+#include "koStoreBase.h"
+
+class KZip;
+class KArchiveDirectory;
+class KURL;
+
+class KoZipStore : public KoStoreBase
+{
+public:
+ KoZipStore( const QString & _filename, Mode _mode, const QCString & appIdentification );
+ KoZipStore( QIODevice *dev, Mode mode, const QCString & appIdentification );
+ /**
+ * KURL-constructor
+ * @todo saving not completely implemented (fixed temporary file)
+ * @since 1.4
+ */
+ KoZipStore( QWidget* window, const KURL& _url, const QString & _filename, Mode _mode, const QCString & appIdentification );
+ ~KoZipStore();
+
+ virtual Q_LONG write( const char* _data, Q_ULONG _len );
+protected:
+ virtual bool init( Mode _mode, const QCString& appIdentification );
+ virtual bool openWrite( const QString& name );
+ virtual bool openRead( const QString& name );
+ virtual bool closeWrite();
+ virtual bool closeRead() { return true; }
+ virtual bool enterRelativeDirectory( const QString& dirName );
+ virtual bool enterAbsoluteDirectory( const QString& path );
+ virtual bool fileExists( const QString& absPath ) const;
+
+ /// The archive
+ KZip * m_pZip;
+
+ /** In "Read" mode this pointer is pointing to the
+ current directory in the archive to speed up the verification process */
+ const KArchiveDirectory* m_currentDir;
+};
+
+#endif
diff --git a/src/rip/Makefile.am b/src/rip/Makefile.am
new file mode 100644
index 0000000..da023c7
--- /dev/null
+++ b/src/rip/Makefile.am
@@ -0,0 +1,32 @@
+if include_videodvdrip
+VIDEODVDRIPDIR = videodvd
+VIDEODVDRIPLIB = videodvd/libvideodvdrip.la
+endif
+
+AM_CPPFLAGS = -I$(srcdir)/../../libk3b/core \
+ -I$(srcdir)/../../libk3b/cddb \
+ -I$(srcdir)/../../libk3bdevice \
+ -I$(srcdir)/../../libk3b/plugin \
+ -I$(srcdir)/../../libk3b/tools \
+ -I$(srcdir)/../../libk3b/projects \
+ -I$(srcdir)/../../libk3b/projects/audiocd \
+ -I$(srcdir)/../../libk3b/cddb \
+ -I$(srcdir)/../../libk3b/jobs/ \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../projects \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = librip.la
+librip_la_LIBADD = $(VIDEODVDRIPLIB)
+
+librip_la_SOURCES = base_k3baudiorippingoptionwidget.ui \
+ base_k3bcddbpatternwidget.ui k3bpatternparser.cpp k3baudiorippingdialog.cpp \
+ k3baudioripthread.cpp k3baudiocdview.cpp k3bcddbpatternwidget.cpp \
+ k3bvideocdinfo.cpp k3bvideocdview.cpp k3bvideocdrip.cpp \
+ k3bvideocdrippingdialog.cpp k3bcuefilewriter.cpp k3baudioconvertingoptionwidget.cpp \
+ k3baudiocdlistview.cpp k3baudioprojectconvertingdialog.cpp \
+ k3baudioprojectconvertingthread.cpp k3baudioripjob.cpp
+
+SUBDIRS = $(VIDEODVDRIPDIR) \ No newline at end of file
diff --git a/src/rip/base_k3baudiorippingoptionwidget.ui b/src/rip/base_k3baudiorippingoptionwidget.ui
new file mode 100644
index 0000000..04355b4
--- /dev/null
+++ b/src/rip/base_k3baudiorippingoptionwidget.ui
@@ -0,0 +1,282 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bAudioRippingOptionWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>436</width>
+ <height>182</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Filetype</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>m_comboFileType</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>m_buttonConfigurePlugin</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Configure Plugin</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="0" column="1" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkCreatePlaylist</cstring>
+ </property>
+ <property name="text">
+ <string>Create m&amp;3u playlist</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Create playlist for the ripped files</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will create a playlist of the ripped files
+which can be used with programs like xmms or noatun.
+&lt;p&gt;You may use the special strings to give the playlist a unique filename.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkPlaylistRelative</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Use relative paths</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Use relative paths instead of absolute</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked, the entries in the playlist will be relative to its location.
+&lt;p&gt;Example: If your playlist is located in &lt;em&gt;/home/myself/music&lt;/em&gt; and
+your audio files are in &lt;em&gt;/home/myself/music/cool&lt;/em&gt;; then the entries in the
+playlist will look something like: &lt;em&gt;cool/track1.ogg&lt;/em&gt;.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkSingleFile</cstring>
+ </property>
+ <property name="text">
+ <string>Create si&amp;ngle file</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Rip all tracks to a single file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will create only one
+audio file no matter how many tracks are ripped. This
+file will contain all tracks one after the other.
+&lt;p&gt;This might be useful to rip a live album or a radio play.
+&lt;p&gt;&lt;b&gt;Caution:&lt;/b&gt; The file will have the name of the first track.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkWriteCueFile</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Write &amp;cue file</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Write a cuefile</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will create a CDRWIN cue file which allows to easily write a copy of the audio CD on other systems.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Target Folder</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Free space in directory:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_editBaseDir</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>m_labelFreeSpace</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Space needed:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>m_labelNeededSpace</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_checkCreatePlaylist</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_checkPlaylistRelative</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkSingleFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_checkWriteCueFile</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/src/rip/base_k3bcddbpatternwidget.ui b/src/rip/base_k3bcddbpatternwidget.ui
new file mode 100644
index 0000000..cafaa5d
--- /dev/null
+++ b/src/rip/base_k3bcddbpatternwidget.ui
@@ -0,0 +1,180 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bCddbPatternWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bPatternOptionTab</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>344</width>
+ <height>139</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Ripping Pattern</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkBlankReplace</cstring>
+ </property>
+ <property name="text">
+ <string>Replace all blan&amp;ks with:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editBlankReplace</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>_</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Playlist pattern:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>m_comboPlaylistPattern</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Ripped files pattern:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_comboFilenamePattern</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Insert your custom pattern here</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLLabel">
+ <property name="name">
+ <cstring>m_specialStringsLabel</cstring>
+ </property>
+ <property name="text">
+ <string>See special strings</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="KURLLabel">
+ <property name="name">
+ <cstring>m_conditionalInclusionLabel</cstring>
+ </property>
+ <property name="text">
+ <string>About conditional inclusion</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_checkBlankReplace</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_editBlankReplace</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_comboFilenamePattern</tabstop>
+ <tabstop>m_comboPlaylistPattern</tabstop>
+ <tabstop>m_checkBlankReplace</tabstop>
+ <tabstop>m_editBlankReplace</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurllabel.h</includehint>
+ <includehint>kurllabel.h</includehint>
+</includehints>
+</UI>
diff --git a/src/rip/k3baudiocdlistview.cpp b/src/rip/k3baudiocdlistview.cpp
new file mode 100644
index 0000000..b5f8566
--- /dev/null
+++ b/src/rip/k3baudiocdlistview.cpp
@@ -0,0 +1,66 @@
+/*
+ *
+ * $Id: k3baudiocdlistview.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiocdlistview.h"
+#include "k3baudiocdview.h"
+
+#include <klocale.h>
+
+#include <qheader.h>
+#include <qtooltip.h>
+
+
+K3bAudioCdListView::K3bAudioCdListView( K3bAudioCdView* view, QWidget* parent, const char* name )
+ : K3bListView( parent, name ),
+ m_view(view)
+{
+ setFullWidth(true);
+ setSorting(-1);
+ setAllColumnsShowFocus( true );
+ setSelectionModeExt( Extended );
+ setDragEnabled( true );
+ addColumn( "" );
+ addColumn( "" );
+ addColumn( i18n("Artist") );
+ addColumn( i18n("Title") );
+ addColumn( i18n("Length") );
+ addColumn( i18n("Size") );
+
+ setDoubleClickForEdit( true );
+
+ header()->setClickEnabled(false);
+ setColumnWidthMode( 0, QListView::Manual );
+ setColumnWidth( 0, 20 );
+ header()->setResizeEnabled( false,0 );
+
+ setColumnAlignment( 4, Qt::AlignHCenter );
+
+ QToolTip::add( viewport(), i18n("Check the tracks that should be ripped") );
+}
+
+
+K3bAudioCdListView::~K3bAudioCdListView()
+{
+}
+
+
+QDragObject* K3bAudioCdListView::dragObject()
+{
+ return m_view->dragObject();
+}
+
+
+#include "k3baudiocdlistview.moc"
+
diff --git a/src/rip/k3baudiocdlistview.h b/src/rip/k3baudiocdlistview.h
new file mode 100644
index 0000000..1ce4a90
--- /dev/null
+++ b/src/rip/k3baudiocdlistview.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * $Id: k3baudiocdlistview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_CD_LISTVIEW_H_
+#define _K3B_AUDIO_CD_LISTVIEW_H_
+
+#include <k3blistview.h>
+
+class QDragObject;
+class K3bAudioCdView;
+
+/**
+ * Internally used by K3bAudioCdView
+ */
+class K3bAudioCdListView : public K3bListView
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioCdListView( K3bAudioCdView*, QWidget* parent = 0, const char* name = 0 );
+ ~K3bAudioCdListView();
+
+ protected:
+ /**
+ * @reimpl from KListView
+ */
+ QDragObject* dragObject();
+
+ private:
+ K3bAudioCdView* m_view;
+};
+
+#endif
diff --git a/src/rip/k3baudiocdview.cpp b/src/rip/k3baudiocdview.cpp
new file mode 100644
index 0000000..d225922
--- /dev/null
+++ b/src/rip/k3baudiocdview.cpp
@@ -0,0 +1,631 @@
+/*
+ *
+ * $Id: k3baudiocdview.cpp 624215 2007-01-16 19:10:03Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudiocdview.h"
+#include "k3baudiorippingdialog.h"
+#include "k3baudiocdlistview.h"
+
+#include <k3bpassivepopup.h>
+#include <k3btoc.h>
+#include <k3bdiskinfo.h>
+#include <k3bdevicehandler.h>
+#include <k3blistview.h>
+#include <k3bcddbresult.h>
+#include <k3bmsf.h>
+#include <k3bcddb.h>
+#include <k3bcddbquery.h>
+#include <k3btoolbox.h>
+#include <kcutlabel.h>
+#include <k3bstdguiitems.h>
+#include <k3bapplication.h>
+#include <k3bthememanager.h>
+#include <k3baudiocdtrackdrag.h>
+#include <k3bthemedlabel.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kstandarddirs.h>
+#include <kdialogbase.h>
+
+#include <qlayout.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qspinbox.h>
+#include <qfont.h>
+#include <qdragobject.h>
+
+
+
+
+class K3bAudioCdView::AudioTrackViewItem : public K3bCheckListViewItem
+{
+public:
+ AudioTrackViewItem( QListView* parent,
+ QListViewItem* after,
+ int _trackNumber,
+ const K3b::Msf& length)
+ : K3bCheckListViewItem( parent, after ) {
+
+ setText( 1, QString::number(_trackNumber).rightJustify( 2, ' ' ) );
+ setText( 3, i18n("Track %1").arg(_trackNumber) );
+ setText( 4, " " + length.toString() + " " );
+ setText( 5, " " + KIO::convertSize( length.audioBytes() ) + " " );
+
+ trackNumber = _trackNumber;
+
+ setEditor( 2, LINE );
+ setEditor( 3, LINE );
+
+ setChecked(true);
+ }
+
+ void setup() {
+ K3bCheckListViewItem::setup();
+
+ setHeight( height() + 4 );
+ }
+
+ int trackNumber;
+
+ void updateCddbData( const K3bCddbResultEntry& entry ) {
+ setText( 2, entry.artists[trackNumber-1] );
+ setText( 3, entry.titles[trackNumber-1] );
+ }
+};
+
+
+K3bAudioCdView::K3bAudioCdView( QWidget* parent, const char *name )
+ : K3bMediaContentsView( true,
+ K3bMedium::CONTENT_AUDIO,
+ K3bDevice::MEDIA_CD_ALL,
+ K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_COMPLETE,
+ parent, name )
+{
+ QGridLayout* mainGrid = new QGridLayout( mainWidget() );
+
+ // toolbox
+ // ----------------------------------------------------------------------------------
+ QHBoxLayout* toolBoxLayout = new QHBoxLayout( 0, 0, 0, "toolBoxLayout" );
+ m_toolBox = new K3bToolBox( mainWidget() );
+ toolBoxLayout->addWidget( m_toolBox );
+ QSpacerItem* spacer = new QSpacerItem( 10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ toolBoxLayout->addItem( spacer );
+ m_labelLength = new QLabel( mainWidget() );
+ m_labelLength->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ toolBoxLayout->addWidget( m_labelLength );
+
+
+ // the track view
+ // ----------------------------------------------------------------------------------
+ m_trackView = new K3bAudioCdListView( this, mainWidget() );
+
+ connect( m_trackView, SIGNAL(itemRenamed(QListViewItem*, const QString&, int)),
+ this, SLOT(slotItemRenamed(QListViewItem*, const QString&, int)) );
+ connect( m_trackView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) );
+// connect( m_trackView, SIGNAL(selectionChanged(QListViewItem*)),
+// this, SLOT(slotTrackSelectionChanged(QListViewItem*)) );
+
+ mainGrid->addLayout( toolBoxLayout, 0, 0 );
+ mainGrid->addWidget( m_trackView, 1, 0 );
+
+
+ m_cddb = new K3bCddb( this );
+
+ connect( m_cddb, SIGNAL(queryFinished(int)),
+ this, SLOT(slotCddbQueryFinished(int)) );
+
+ initActions();
+ // slotTrackSelectionChanged(0);
+
+ setLeftPixmap( K3bTheme::MEDIA_LEFT );
+ setRightPixmap( K3bTheme::MEDIA_AUDIO );
+
+ m_busyInfoLabel = new K3bThemedLabel( i18n("Searching for Artist information..."), this );
+ m_busyInfoLabel->setFrameStyle( QFrame::Box|QFrame::Plain );
+ m_busyInfoLabel->setMargin( 6 );
+ m_busyInfoLabel->hide();
+}
+
+
+K3bAudioCdView::~K3bAudioCdView()
+{
+}
+
+
+void K3bAudioCdView::reloadMedium()
+{
+ m_toc = medium().toc();
+ m_device = medium().device();
+
+ // initialize cddb info for editing
+ m_cddbInfo = K3bCddbResultEntry();
+ m_cddbInfo.discid = QString::number( medium().toc().discId(), 16 );
+
+ for( int i = 0; i < (int)m_toc.count(); ++i ) {
+ m_cddbInfo.titles.append("");
+ m_cddbInfo.artists.append("");
+ m_cddbInfo.extInfos.append("");
+ }
+
+ m_trackView->clear();
+ showBusyLabel(true);
+
+ // create a listviewItem for every audio track
+ int index = 1;
+ for( K3bDevice::Toc::const_iterator it = m_toc.begin();
+ it != m_toc.end(); ++it ) {
+
+ // for now skip data tracks since we are not able to rip them to iso
+ if( (*it).type() == K3bTrack::AUDIO ) {
+ K3b::Msf length( (*it).length() );
+ (void)new AudioTrackViewItem( m_trackView,
+ m_trackView->lastItem(),
+ index,
+ length );
+ }
+
+ index++;
+ }
+
+ m_cdText = medium().cdText();
+
+ // simulate a cddb entry with the cdtext data
+ m_cddbInfo.cdTitle = m_cdText.title();
+ m_cddbInfo.cdArtist = m_cdText.performer();
+ m_cddbInfo.cdExtInfo = m_cdText.message();
+
+ for( unsigned int i = 0; i < m_cdText.count(); ++i ) {
+ m_cddbInfo.titles[i] = m_cdText[i].title();
+ m_cddbInfo.artists[i] = m_cdText[i].performer();
+ m_cddbInfo.extInfos[i] = m_cdText[i].message();
+ }
+
+ updateDisplay();
+
+ KConfig* c = k3bcore->config();
+ c->setGroup("Cddb");
+ bool useCddb = ( c->readBoolEntry( "use local cddb query", true ) ||
+ c->readBoolEntry( "use remote cddb", false ) );
+
+ if( useCddb &&
+ ( m_cdText.isEmpty() ||
+ KMessageBox::questionYesNo( this,
+ i18n("Found Cd-Text. Do you want to use it instead of querying CDDB?"),
+ i18n("Found Cd-Text"),
+ i18n("Use CD-Text"),
+ i18n("Query CDDB"),
+ "prefereCdTextOverCddb" ) == KMessageBox::No ) )
+ queryCddb();
+ else
+ showBusyLabel(false);
+}
+
+
+void K3bAudioCdView::initActions()
+{
+ m_actionCollection = new KActionCollection( this );
+
+ KAction* actionSelectAll = new KAction( i18n("Check All"), 0, 0, this,
+ SLOT(slotCheckAll()), actionCollection(),
+ "check_all" );
+ KAction* actionDeselectAll = new KAction( i18n("Uncheck All"), 0, 0, this,
+ SLOT(slotUncheckAll()), actionCollection(),
+ "uncheck_all" );
+ KAction* actionSelect = new KAction( i18n("Check Track"), 0, 0, this,
+ SLOT(slotSelect()), actionCollection(),
+ "select_track" );
+ KAction* actionDeselect = new KAction( i18n("Uncheck Track"), 0, 0, this,
+ SLOT(slotDeselect()), actionCollection(),
+ "deselect_track" );
+ KAction* actionEditTrackCddbInfo = new KAction( i18n("Edit Track cddb Info"), "edit", 0, this,
+ SLOT(slotEditTrackCddb()), actionCollection(),
+ "edit_track_cddb" );
+ KAction* actionEditAlbumCddbInfo = new KAction( i18n("Edit Album cddb Info"), "edit", 0, this,
+ SLOT(slotEditAlbumCddb()), actionCollection(),
+ "edit_album_cddb" );
+
+ KAction* actionStartRip = new KAction( i18n("Start Ripping"), "cddarip", 0, this,
+ SLOT(startRip()), actionCollection(), "start_rip" );
+
+ KAction* actionQueryCddb = new KAction( i18n("Query cddb"), "reload", 0, this,
+ SLOT(queryCddb()), actionCollection(), "query_cddb" );
+
+ KAction* actionSaveCddbLocally = new KAction( i18n("Save Cddb Entry Locally"), "filesave", 0, this,
+ SLOT(slotSaveCddbLocally()), actionCollection(), "save_cddb_local" );
+
+ // TODO: set the actions tooltips and whatsthis infos
+
+ // setup the popup menu
+ m_popupMenu = new KActionMenu( actionCollection(), "popup_menu" );
+ KAction* separator = new KActionSeparator( actionCollection(), "separator" );
+ m_popupMenu->insert( actionSelect );
+ m_popupMenu->insert( actionDeselect );
+ m_popupMenu->insert( actionSelectAll );
+ m_popupMenu->insert( actionDeselectAll );
+ m_popupMenu->insert( separator );
+ m_popupMenu->insert( actionEditTrackCddbInfo );
+ m_popupMenu->insert( actionEditAlbumCddbInfo );
+ m_popupMenu->insert( separator );
+ m_popupMenu->insert( actionStartRip );
+
+ // setup the toolbox
+ m_toolBox->addButton( actionStartRip, true );
+ m_toolBox->addSpacing();
+ m_toolBox->addButton( actionQueryCddb );
+ m_toolBox->addButton( actionSaveCddbLocally );
+ m_toolBox->addButton( actionEditTrackCddbInfo );
+ m_toolBox->addButton( actionEditAlbumCddbInfo );
+}
+
+
+void K3bAudioCdView::slotContextMenu( KListView*, QListViewItem*, const QPoint& p )
+{
+ m_popupMenu->popup(p);
+}
+
+
+void K3bAudioCdView::slotItemRenamed( QListViewItem* item, const QString& str, int col )
+{
+ AudioTrackViewItem* a = (AudioTrackViewItem*)item;
+ if( col == 2 )
+ m_cddbInfo.artists[a->trackNumber-1] = str;
+ else if( col == 3 )
+ m_cddbInfo.titles[a->trackNumber-1] = str;
+ else if( col == 6 )
+ m_cddbInfo.extInfos[a->trackNumber-1] = str;
+}
+
+
+void K3bAudioCdView::slotTrackSelectionChanged( QListViewItem* item )
+{
+ actionCollection()->action("edit_track_cddb")->setEnabled( item != 0 );
+ actionCollection()->action("select_track")->setEnabled( item != 0 );
+ actionCollection()->action("deselect_track")->setEnabled( item != 0 );
+}
+
+
+void K3bAudioCdView::startRip()
+{
+ QValueList<int> trackNumbers;
+ for( QListViewItemIterator it( m_trackView ); it.current(); ++it ) {
+ AudioTrackViewItem* a = (AudioTrackViewItem*)it.current();
+ if( a->isChecked() )
+ trackNumbers.append( a->trackNumber );
+ }
+
+ if( trackNumbers.count() == 0 ) {
+ KMessageBox::error( this, i18n("Please select the tracks to rip."),
+ i18n("No Tracks Selected") );
+ }
+ else {
+ K3bAudioRippingDialog rip( m_toc,
+ m_device,
+ m_cddbInfo,
+ trackNumbers,
+ this );
+ rip.exec();
+ }
+}
+
+
+void K3bAudioCdView::slotEditTrackCddb()
+{
+ QPtrList<QListViewItem> items( m_trackView->selectedItems() );
+ if( !items.isEmpty() ) {
+ AudioTrackViewItem* a = static_cast<AudioTrackViewItem*>(items.first());
+
+ KDialogBase d( this, "trackCddbDialog", true, i18n("Cddb Track %1").arg(a->trackNumber),
+ KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true);
+ QWidget* w = new QWidget( &d );
+
+ KLineEdit* editTitle = new KLineEdit( m_cddbInfo.titles[a->trackNumber-1], w );
+ KLineEdit* editArtist = new KLineEdit( m_cddbInfo.artists[a->trackNumber-1], w );
+ KLineEdit* editExtInfo = new KLineEdit( m_cddbInfo.extInfos[a->trackNumber-1], w );
+ QFrame* line = new QFrame( w );
+ line->setFrameShape( QFrame::HLine );
+ line->setFrameShadow( QFrame::Sunken );
+
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setSpacing( KDialog::spacingHint() );
+
+ grid->addWidget( new QLabel( i18n("Title:"), w ), 0, 0 );
+ grid->addWidget( editTitle, 0, 1 );
+ grid->addMultiCellWidget( line, 1, 1, 0, 1 );
+ grid->addWidget( new QLabel( i18n("Artist:"), w ), 2, 0 );
+ grid->addWidget( editArtist, 2, 1 );
+ grid->addWidget( new QLabel( i18n("Extra info:"), w ), 3, 0 );
+ grid->addWidget( editExtInfo, 3, 1 );
+ grid->setRowStretch( 4, 1 );
+
+ d.setMainWidget(w);
+ d.resize( QMAX( QMAX(d.sizeHint().height(), d.sizeHint().width()), 300), d.sizeHint().height() );
+
+ if( d.exec() == QDialog::Accepted ) {
+ m_cddbInfo.titles[a->trackNumber-1] = editTitle->text();
+ m_cddbInfo.artists[a->trackNumber-1] = editArtist->text();
+ m_cddbInfo.extInfos[a->trackNumber-1] = editExtInfo->text();
+ a->updateCddbData( m_cddbInfo );
+ }
+ }
+}
+
+
+void K3bAudioCdView::slotEditAlbumCddb()
+{
+ KDialogBase d( this, "trackCddbDialog", true, i18n("Album Cddb"),
+ KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true);
+ QWidget* w = new QWidget( &d );
+
+ KLineEdit* editTitle = new KLineEdit( m_cddbInfo.cdTitle, w );
+ KLineEdit* editArtist = new KLineEdit( m_cddbInfo.cdArtist, w );
+ KLineEdit* editExtInfo = new KLineEdit( m_cddbInfo.cdExtInfo, w );
+ KLineEdit* editGenre = new KLineEdit( m_cddbInfo.genre, w );
+ QSpinBox* spinYear = new QSpinBox( 0, 9999, 1, w );
+ spinYear->setValue( m_cddbInfo.year );
+ QFrame* line = new QFrame( w );
+ line->setFrameShape( QFrame::HLine );
+ line->setFrameShadow( QFrame::Sunken );
+ KComboBox* comboCat = new KComboBox( w );
+ comboCat->insertStringList( K3bCddbQuery::categories() );
+
+ // set the category
+ for( int i = 0; i < comboCat->count(); ++i )
+ if( comboCat->text(i) == m_cddbInfo.category ) {
+ comboCat->setCurrentItem(i);
+ break;
+ }
+
+ QGridLayout* grid = new QGridLayout( w );
+ grid->setSpacing( KDialog::spacingHint() );
+
+ grid->addWidget( new QLabel( i18n("Title:"), w ), 0, 0 );
+ grid->addWidget( editTitle, 0, 1 );
+ grid->addMultiCellWidget( line, 1, 1, 0, 1 );
+ grid->addWidget( new QLabel( i18n("Artist:"), w ), 2, 0 );
+ grid->addWidget( editArtist, 2, 1 );
+ grid->addWidget( new QLabel( i18n("Extra info:"), w ), 3, 0 );
+ grid->addWidget( editExtInfo, 3, 1 );
+ grid->addWidget( new QLabel( i18n("Genre:"), w ), 4, 0 );
+ grid->addWidget( editGenre, 4, 1 );
+ grid->addWidget( new QLabel( i18n("Year:"), w ), 5, 0 );
+ grid->addWidget( spinYear, 5, 1 );
+ grid->addWidget( new QLabel( i18n("Category:"), w ), 6, 0 );
+ grid->addWidget( comboCat, 6, 1 );
+ grid->setRowStretch( 7, 1 );
+
+ d.setMainWidget(w);
+ d.resize( QMAX( QMAX(d.sizeHint().height(), d.sizeHint().width()), 300), d.sizeHint().height() );
+
+ if( d.exec() == QDialog::Accepted ) {
+ m_cddbInfo.cdTitle = editTitle->text();
+ m_cddbInfo.cdArtist = editArtist->text();
+ m_cddbInfo.cdExtInfo = editExtInfo->text();
+ m_cddbInfo.category = comboCat->currentText();
+ m_cddbInfo.genre = editGenre->text();
+ m_cddbInfo.year = spinYear->value();
+
+ updateDisplay();
+ }
+}
+
+
+void K3bAudioCdView::queryCddb()
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup("Cddb");
+
+ m_cddb->readConfig( c );
+
+ if( c->readBoolEntry( "use local cddb query", true ) ||
+ c->readBoolEntry( "use remote cddb", false ) ) {
+
+ showBusyLabel(true);
+
+ m_cddb->query( m_toc );
+ }
+}
+
+
+void K3bAudioCdView::slotCddbQueryFinished( int error )
+{
+ if( error == K3bCddbQuery::SUCCESS ) {
+ m_cddbInfo = m_cddb->result();
+
+ // save the entry locally
+ KConfig* c = k3bcore->config();
+ c->setGroup( "Cddb" );
+ if( c->readBoolEntry( "save cddb entries locally", true ) )
+ m_cddb->saveEntry( m_cddbInfo );
+
+ updateDisplay();
+ }
+ else if( error == K3bCddbQuery::NO_ENTRY_FOUND ) {
+ if( !KConfigGroup( k3bcore->config(), "Cddb" ).readBoolEntry( "use remote cddb", false ) )
+ K3bPassivePopup::showPopup( i18n("<p>No CDDB entry found. Enable remote CDDB queries in the K3b settings to get access "
+ "to more entries through the internet."), i18n("CDDB") );
+ else
+ K3bPassivePopup::showPopup( i18n("No CDDB entry found."), i18n("CDDB") );
+ }
+ else if( error != K3bCddbQuery::CANCELED ) {
+ K3bPassivePopup::showPopup( m_cddb->errorString(), i18n("CDDB Error") );
+ }
+
+ enableInteraction(true);
+}
+
+
+void K3bAudioCdView::slotSaveCddbLocally()
+{
+ // check if the minimal info has been inserted
+ if( m_cddbInfo.category.isEmpty() ) {
+ KMessageBox::sorry( this, i18n("Please set the category before saving.") );
+ return;
+ }
+
+ if( m_cddbInfo.cdTitle.isEmpty() || m_cddbInfo.cdArtist.isEmpty() ) {
+ KMessageBox::sorry( this, i18n("Please set CD artist and title before saving.") );
+ return;
+ }
+
+ bool missingTitle = false;
+ bool missingArtist = false;
+ bool allTrackArtistsEmpty = true;
+ for( unsigned int i = 0; i < m_cddbInfo.titles.count(); ++i ) {
+ if( m_cddbInfo.titles[i].isEmpty() )
+ missingTitle = true;
+ if( m_cddbInfo.artists[i].isEmpty() )
+ missingArtist = true;
+ if( !m_cddbInfo.artists[i].isEmpty() )
+ allTrackArtistsEmpty = false;
+ }
+
+ if( missingTitle ||
+ ( missingArtist && !allTrackArtistsEmpty ) ) {
+ KMessageBox::sorry( this, i18n("Please set at least artist and title on all tracks before saving.") );
+ return;
+ }
+
+ // make sure the data gets updated (bad design like a lot in the cddb stuff! :(
+ m_cddbInfo.rawData.truncate(0);
+
+ KConfig* c = k3bcore->config();
+ c->setGroup("Cddb");
+
+ m_cddb->readConfig( c );
+
+ m_cddb->saveEntry( m_cddbInfo );
+ K3bPassivePopup::showPopup( i18n("Saved entry (%1) in category %2.")
+ .arg(m_cddbInfo.discid)
+ .arg(m_cddbInfo.category),
+ i18n("CDDB") );
+}
+
+
+void K3bAudioCdView::slotCheckAll()
+{
+ for( QListViewItemIterator it( m_trackView ); it.current(); ++it )
+ ((AudioTrackViewItem*)it.current())->setChecked(true);
+}
+
+void K3bAudioCdView::slotUncheckAll()
+{
+ for( QListViewItemIterator it( m_trackView ); it.current(); ++it )
+ ((AudioTrackViewItem*)it.current())->setChecked(false);
+}
+
+void K3bAudioCdView::slotSelect()
+{
+ QPtrList<QListViewItem> items( m_trackView->selectedItems() );
+ for( QPtrListIterator<QListViewItem> it( items );
+ it.current(); ++it )
+ static_cast<AudioTrackViewItem*>(it.current())->setChecked(true);
+}
+
+void K3bAudioCdView::slotDeselect()
+{
+ QPtrList<QListViewItem> items( m_trackView->selectedItems() );
+ for( QPtrListIterator<QListViewItem> it( items );
+ it.current(); ++it )
+ static_cast<AudioTrackViewItem*>(it.current())->setChecked(false);
+}
+
+void K3bAudioCdView::updateDisplay()
+{
+ // update the listview
+ for( QListViewItemIterator it( m_trackView ); it.current(); ++it ) {
+ AudioTrackViewItem* item = (AudioTrackViewItem*)it.current();
+ item->updateCddbData( m_cddbInfo );
+ }
+
+ if( !m_cddbInfo.cdTitle.isEmpty() ) {
+ QString s = m_cddbInfo.cdTitle;
+ if( !m_cddbInfo.cdArtist.isEmpty() )
+ s += " (" + m_cddbInfo.cdArtist + ")";
+ setTitle( s );
+ }
+ else
+ setTitle( i18n("Audio CD") );
+
+ m_labelLength->setText( i18n("1 track (%1)",
+ "%n tracks (%1)",
+ m_toc.count()).arg(K3b::Msf(m_toc.length()).toString()) );
+}
+
+
+void K3bAudioCdView::showBusyLabel( bool b )
+{
+ if( !b ) {
+ actionCollection()->action( "start_rip" )->setEnabled( true );
+ m_trackView->setEnabled( true );
+ m_busyInfoLabel->hide();
+ }
+ else {
+ // the themed label is a cut label, thus its size hint is
+ // based on the cut text, we force it to be full
+ m_busyInfoLabel->resize( width(), height() );
+ m_busyInfoLabel->resize( m_busyInfoLabel->sizeHint() );
+ int x = (width() - m_busyInfoLabel->width())/2;
+ int y = (height() - m_busyInfoLabel->height())/2;
+ QRect r( QPoint( x, y ), m_busyInfoLabel->size() );
+ m_busyInfoLabel->setGeometry( r );
+ m_busyInfoLabel->show();
+
+ m_trackView->setEnabled( false );
+ enableInteraction( false );
+ }
+}
+
+
+void K3bAudioCdView::enableInteraction( bool b )
+{
+ // we leave the track view enabled in default disabled mode
+ // since drag'n'drop to audio projects does not need an inserted CD
+ actionCollection()->action( "start_rip" )->setEnabled( b );
+ if( b )
+ showBusyLabel( false );
+}
+
+
+QDragObject* K3bAudioCdView::dragObject()
+{
+ QPtrList<QListViewItem> items = m_trackView->selectedItems();
+ QValueList<int> tracks;
+ for( QPtrListIterator<QListViewItem> it( items );
+ it.current(); ++it )
+ tracks.append( static_cast<AudioTrackViewItem*>(it.current())->trackNumber );
+
+ if( !items.isEmpty() ) {
+ QDragObject* drag = new K3bAudioCdTrackDrag( m_toc,
+ tracks,
+ m_cddbInfo,
+ m_device,
+ this );
+ drag->setPixmap( m_trackView->createDragPixmap( items ) );
+ return drag;
+ }
+ else
+ return 0;
+}
+
+#include "k3baudiocdview.moc"
diff --git a/src/rip/k3baudiocdview.h b/src/rip/k3baudiocdview.h
new file mode 100644
index 0000000..257a0f5
--- /dev/null
+++ b/src/rip/k3baudiocdview.h
@@ -0,0 +1,107 @@
+/*
+ *
+ * $Id: k3baudiocdview.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_AUDIOCD_VIEW_H_
+#define _K3B_AUDIOCD_VIEW_H_
+
+#include <k3bmediacontentsview.h>
+#include <k3bmedium.h>
+
+#include <k3btoc.h>
+#include <k3bcddbresult.h>
+#include <k3bcdtext.h>
+
+class K3bListView;
+class KListView;
+class QListViewItem;
+class QPoint;
+class KActionCollection;
+class KActionMenu;
+class K3bCddb;
+class QLabel;
+class K3bToolBox;
+class QDragObject;
+
+
+namespace K3bDevice {
+ class Device;
+}
+
+
+class K3bAudioCdView : public K3bMediaContentsView
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioCdView( QWidget* parent = 0, const char * name = 0 );
+ ~K3bAudioCdView();
+
+ KActionCollection* actionCollection() const { return m_actionCollection; }
+
+ /**
+ * internal
+ */
+ QDragObject* dragObject();
+
+ public slots:
+ void queryCddb();
+
+ private slots:
+ void slotContextMenu( KListView*, QListViewItem*, const QPoint& );
+ void slotItemRenamed( QListViewItem*, const QString&, int );
+ void slotCddbQueryFinished( int );
+ void slotTrackSelectionChanged( QListViewItem* );
+ void slotSaveCddbLocally();
+
+ void slotEditTrackCddb();
+ void slotEditAlbumCddb();
+ void startRip();
+ void slotCheckAll();
+ void slotUncheckAll();
+ void slotSelect();
+ void slotDeselect();
+
+ private:
+ void reloadMedium();
+
+ void initActions();
+ void updateDisplay();
+ void enableInteraction( bool );
+ void showBusyLabel( bool );
+
+ K3bDevice::Toc m_toc;
+ K3bDevice::Device* m_device;
+
+ K3bCddbResultEntry m_cddbInfo;
+
+ KActionCollection* m_actionCollection;
+ KActionMenu* m_popupMenu;
+
+ K3bListView* m_trackView;
+ K3bToolBox* m_toolBox;
+ QLabel* m_labelLength;
+
+ class AudioTrackViewItem;
+
+ K3bCddb* m_cddb;
+
+ K3bDevice::CdText m_cdText;
+
+ QLabel* m_busyInfoLabel;
+};
+
+
+#endif
diff --git a/src/rip/k3baudioconvertingoptionwidget.cpp b/src/rip/k3baudioconvertingoptionwidget.cpp
new file mode 100644
index 0000000..a044dc5
--- /dev/null
+++ b/src/rip/k3baudioconvertingoptionwidget.cpp
@@ -0,0 +1,266 @@
+/*
+ *
+ * $Id: k3baudioconvertingoptionwidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudioconvertingoptionwidget.h"
+
+#include <k3bpluginmanager.h>
+#include <k3baudioencoder.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+
+#include <kcombobox.h>
+#include <kurlrequester.h>
+#include <kio/global.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <qintdict.h>
+#include <qmap.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qtoolbutton.h>
+#include <qcheckbox.h>
+
+
+
+class K3bAudioConvertingOptionWidget::Private
+{
+public:
+ QIntDict<K3bAudioEncoder> encoderMap;
+ QMap<int, QString> extensionMap;
+
+ QTimer freeSpaceUpdateTimer;
+
+ KIO::filesize_t neededSize;
+
+ int getDefaultFormat() {
+ // we prefere formats in this order:
+ // 1. ogg
+ // 2. mp3
+ // 3. flac
+ // 4. wave
+ int ogg = -1;
+ int mp3 = -1;
+ int flac = -1;
+ for( QMap<int, QString>::const_iterator it = extensionMap.constBegin();
+ it != extensionMap.constEnd(); ++it ) {
+ if( it.data() == "ogg" )
+ ogg = it.key();
+ else if( it.data() == "mp3" )
+ mp3 = it.key();
+ else if( it.data() == "flac" )
+ flac = it.key();
+ }
+
+ if( ogg > -1 )
+ return ogg;
+ else if( mp3 > -1 )
+ return mp3;
+ else if( flac > -1 )
+ return flac;
+ else
+ return 0;
+ }
+};
+
+
+K3bAudioConvertingOptionWidget::K3bAudioConvertingOptionWidget( QWidget* parent, const char* name )
+ : base_K3bAudioRippingOptionWidget( parent, name )
+{
+ d = new Private();
+
+ connect( m_editBaseDir, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotUpdateFreeTempSpace()) );
+ connect( m_comboFileType, SIGNAL(activated(int)),
+ this, SLOT(slotEncoderChanged()) );
+ connect( &d->freeSpaceUpdateTimer, SIGNAL(timeout()),
+ this, SLOT(slotUpdateFreeTempSpace()) );
+ connect( m_checkCreatePlaylist, SIGNAL(toggled(bool)), this, SIGNAL(changed()) );
+ connect( m_checkSingleFile, SIGNAL(toggled(bool)), this, SIGNAL(changed()) );
+ connect( m_checkWriteCueFile, SIGNAL(toggled(bool)), this, SIGNAL(changed()) );
+ connect( m_comboFileType, SIGNAL(activated(int)), this, SIGNAL(changed()) );
+ connect( m_editBaseDir, SIGNAL(textChanged(const QString&)), this, SIGNAL(changed()) );
+ connect( m_buttonConfigurePlugin, SIGNAL(clicked()), this, SLOT(slotConfigurePlugin()) );
+
+ m_editBaseDir->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+ m_buttonConfigurePlugin->setIconSet( SmallIconSet( "gear" ) );
+
+ // FIXME: see if sox and the sox encoder are installed and if so do not put the internal wave
+ // writer in the list of encoders.
+
+ d->encoderMap.clear();
+ d->extensionMap.clear();
+ m_comboFileType->clear();
+ m_comboFileType->insertItem( i18n("Wave") );
+ d->extensionMap[0] = "wav";
+
+ // check the available encoding plugins
+ QPtrList<K3bPlugin> fl = k3bcore->pluginManager()->plugins( "AudioEncoder" );
+ for( QPtrListIterator<K3bPlugin> it( fl ); it.current(); ++it ) {
+ K3bAudioEncoder* f = (K3bAudioEncoder*)it.current();
+ QStringList exL = f->extensions();
+
+ for( QStringList::const_iterator exIt = exL.begin();
+ exIt != exL.end(); ++exIt ) {
+ d->extensionMap.insert( m_comboFileType->count(), *exIt );
+ d->encoderMap.insert( m_comboFileType->count(), f );
+ m_comboFileType->insertItem( f->fileTypeComment(*exIt) );
+ }
+ }
+
+ // refresh every 2 seconds
+ d->freeSpaceUpdateTimer.start(2000);
+ slotUpdateFreeTempSpace();
+}
+
+
+K3bAudioConvertingOptionWidget::~K3bAudioConvertingOptionWidget()
+{
+ delete d;
+}
+
+
+QString K3bAudioConvertingOptionWidget::baseDir() const
+{
+ return m_editBaseDir->url();
+}
+
+
+void K3bAudioConvertingOptionWidget::setBaseDir( const QString& path )
+{
+ m_editBaseDir->setURL( path );
+}
+
+
+void K3bAudioConvertingOptionWidget::setNeededSize( KIO::filesize_t size )
+{
+ d->neededSize = size;
+ if( size > 0 )
+ m_labelNeededSpace->setText( KIO::convertSize( size ) );
+ else
+ m_labelNeededSpace->setText( i18n("unknown") );
+
+ slotUpdateFreeTempSpace();
+}
+
+
+void K3bAudioConvertingOptionWidget::slotConfigurePlugin()
+{
+ // 0 for wave
+ K3bAudioEncoder* encoder = d->encoderMap[m_comboFileType->currentItem()];
+ if( encoder )
+ k3bcore->pluginManager()->execPluginDialog( encoder, this );
+}
+
+
+void K3bAudioConvertingOptionWidget::slotUpdateFreeTempSpace()
+{
+ QString path = m_editBaseDir->url();
+
+ if( !QFile::exists( path ) )
+ path.truncate( path.findRev('/') );
+
+ unsigned long size, avail;
+ if( K3b::kbFreeOnFs( path, size, avail ) ) {
+ m_labelFreeSpace->setText( KIO::convertSizeFromKB(avail) );
+ if( avail < d->neededSize/1024 )
+ m_labelNeededSpace->setPaletteForegroundColor( Qt::red );
+ else
+ m_labelNeededSpace->setPaletteForegroundColor( paletteForegroundColor() );
+ }
+ else {
+ m_labelFreeSpace->setText("-");
+ m_labelNeededSpace->setPaletteForegroundColor( paletteForegroundColor() );
+ }
+}
+
+
+void K3bAudioConvertingOptionWidget::slotEncoderChanged()
+{
+ // 0 for wave
+ m_buttonConfigurePlugin->setEnabled( d->encoderMap[m_comboFileType->currentItem()] != 0 );
+}
+
+
+K3bAudioEncoder* K3bAudioConvertingOptionWidget::encoder() const
+{
+ return d->encoderMap[m_comboFileType->currentItem()]; // 0 for wave
+}
+
+
+QString K3bAudioConvertingOptionWidget::extension() const
+{
+ return d->extensionMap[m_comboFileType->currentItem()];
+}
+
+
+void K3bAudioConvertingOptionWidget::loadDefaults()
+{
+ m_editBaseDir->setURL( QDir::homeDirPath() );
+ m_checkSingleFile->setChecked( false );
+ m_checkWriteCueFile->setChecked( false );
+ m_comboFileType->setCurrentItem( d->getDefaultFormat() );
+ m_checkCreatePlaylist->setChecked(false);
+ m_checkPlaylistRelative->setChecked(false);
+
+ slotEncoderChanged();
+}
+
+
+void K3bAudioConvertingOptionWidget::loadConfig( KConfigBase* c )
+{
+ m_editBaseDir->setURL( c->readPathEntry( "last ripping directory", QDir::homeDirPath() ) );
+
+ m_checkSingleFile->setChecked( c->readBoolEntry( "single_file", false ) );
+ m_checkWriteCueFile->setChecked( c->readBoolEntry( "write_cue_file", false ) );
+
+ m_checkCreatePlaylist->setChecked( c->readBoolEntry( "create_playlist", false ) );
+ m_checkPlaylistRelative->setChecked( c->readBoolEntry( "relative_path_in_playlist", false ) );
+
+ QString filetype = c->readEntry( "filetype", d->extensionMap[d->getDefaultFormat()] );
+ if( filetype == "wav" )
+ m_comboFileType->setCurrentItem(0);
+ else {
+ for( QMap<int, QString>::iterator it = d->extensionMap.begin();
+ it != d->extensionMap.end(); ++it ) {
+ if( it.data() == filetype ) {
+ m_comboFileType->setCurrentItem( it.key() );
+ break;
+ }
+ }
+ }
+
+ slotEncoderChanged();
+}
+
+
+void K3bAudioConvertingOptionWidget::saveConfig( KConfigBase* c )
+{
+ c->writePathEntry( "last ripping directory", m_editBaseDir->url() );
+
+ c->writeEntry( "single_file", m_checkSingleFile->isChecked() );
+ c->writeEntry( "write_cue_file", m_checkWriteCueFile->isChecked() );
+
+ c->writeEntry( "create_playlist", m_checkCreatePlaylist->isChecked() );
+ c->writeEntry( "relative_path_in_playlist", m_checkPlaylistRelative->isChecked() );
+
+ if( d->extensionMap.contains(m_comboFileType->currentItem()) )
+ c->writeEntry( "filetype", d->extensionMap[m_comboFileType->currentItem()] );
+ else
+ c->writeEntry( "filetype", "wav" );
+}
+
+#include "k3baudioconvertingoptionwidget.moc"
diff --git a/src/rip/k3baudioconvertingoptionwidget.h b/src/rip/k3baudioconvertingoptionwidget.h
new file mode 100644
index 0000000..ff4cd45
--- /dev/null
+++ b/src/rip/k3baudioconvertingoptionwidget.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * $Id: k3baudioconvertingoptionwidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIO_CONVERTING_OPTION_WIDGET_H_
+#define _K3B_AUDIO_CONVERTING_OPTION_WIDGET_H_
+
+#include "base_k3baudiorippingoptionwidget.h"
+
+#include <qcheckbox.h>
+#include <kio/global.h>
+
+class K3bAudioEncoder;
+class KConfigBase;
+
+
+/**
+ * Internally used by K3bAudioConvertingDialog
+ */
+class K3bAudioConvertingOptionWidget : public base_K3bAudioRippingOptionWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioConvertingOptionWidget( QWidget* parent, const char* name = 0 );
+ ~K3bAudioConvertingOptionWidget();
+
+ void setBaseDir( const QString& path );
+
+ void setNeededSize( KIO::filesize_t );
+
+ /**
+ * @returns 0 if wave is selected
+ */
+ K3bAudioEncoder* encoder() const;
+ QString extension() const;
+
+ QString baseDir() const;
+
+ bool createPlaylist() const { return m_checkCreatePlaylist->isChecked(); }
+ bool playlistRelativePath() const { return m_checkPlaylistRelative->isChecked(); }
+ bool createSingleFile() const { return m_checkSingleFile->isChecked(); }
+ bool createCueFile() const { return m_checkWriteCueFile->isChecked(); }
+
+ public slots:
+ void loadDefaults();
+ void loadConfig( KConfigBase* );
+ void saveConfig( KConfigBase* );
+
+ signals:
+ void changed();
+
+ private slots:
+ void slotConfigurePlugin();
+ void slotUpdateFreeTempSpace();
+ void slotEncoderChanged();
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/rip/k3baudioprojectconvertingdialog.cpp b/src/rip/k3baudioprojectconvertingdialog.cpp
new file mode 100644
index 0000000..8a3eadc
--- /dev/null
+++ b/src/rip/k3baudioprojectconvertingdialog.cpp
@@ -0,0 +1,371 @@
+/*
+ *
+ * $Id: k3baudioprojectconvertingdialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3baudioprojectconvertingdialog.h"
+#include "k3baudioprojectconvertingthread.h"
+#include "k3bpatternparser.h"
+#include "k3bcddbpatternwidget.h"
+#include "k3baudioconvertingoptionwidget.h"
+
+#include <k3baudiodoc.h>
+#include <k3baudioview.h>
+#include <k3baudiotrackplayer.h>
+#include <k3baudiotrack.h>
+#include <k3bjobprogressdialog.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+#include <k3blistview.h>
+#include <k3baudioencoder.h>
+#include <k3bthreadjob.h>
+
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <klistview.h>
+#include <kurlrequester.h>
+#include <kfiledialog.h>
+#include <kio/global.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+#include <qgroupbox.h>
+#include <qheader.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <qtabwidget.h>
+
+
+
+class K3bAudioProjectConvertingDialog::Private
+{
+public:
+ Private() {
+ }
+
+ QValueVector<QString> filenames;
+ QString playlistFilename;
+ QString cueFilename;
+};
+
+
+K3bAudioProjectConvertingDialog::K3bAudioProjectConvertingDialog( K3bAudioDoc* doc, QWidget *parent, const char *name )
+ : K3bInteractionDialog( parent, name,
+ QString::null,
+ QString::null,
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "Audio Project Converting" ), // config group
+ m_doc(doc)
+{
+ d = new Private();
+
+ setupGui();
+
+ setTitle( i18n("Audio Project Conversion"),
+ i18n("1 track (%1)", "%n tracks (%1)",
+ m_doc->numOfTracks()).arg(m_doc->length().toString()) );
+
+ refresh();
+}
+
+
+K3bAudioProjectConvertingDialog::~K3bAudioProjectConvertingDialog()
+{
+ delete d;
+}
+
+
+void K3bAudioProjectConvertingDialog::setupGui()
+{
+ QWidget *frame = mainWidget();
+ QGridLayout* Form1Layout = new QGridLayout( frame );
+ Form1Layout->setSpacing( KDialog::spacingHint() );
+ Form1Layout->setMargin( 0 );
+
+ m_viewTracks = new K3bListView( frame, "m_viewTracks" );
+ m_viewTracks->addColumn(i18n( "Filename (relative to base directory)") );
+ m_viewTracks->addColumn(i18n( "Length") );
+ m_viewTracks->addColumn(i18n( "File Size") );
+ m_viewTracks->setSorting(-1);
+ m_viewTracks->setAllColumnsShowFocus(true);
+ m_viewTracks->setFullWidth(true);
+
+ QTabWidget* mainTab = new QTabWidget( frame );
+
+ m_optionWidget = new K3bAudioConvertingOptionWidget( mainTab );
+ mainTab->addTab( m_optionWidget, i18n("Settings") );
+
+
+ // setup filename pattern page
+ // -------------------------------------------------------------------------------------------
+ m_patternWidget = new K3bCddbPatternWidget( mainTab );
+ mainTab->addTab( m_patternWidget, i18n("File Naming") );
+ connect( m_patternWidget, SIGNAL(changed()), this, SLOT(refresh()) );
+
+ Form1Layout->addWidget( m_viewTracks, 0, 0 );
+ Form1Layout->addWidget( mainTab, 1, 0 );
+ Form1Layout->setRowStretch( 0, 1 );
+
+ connect( m_optionWidget, SIGNAL(changed()), this, SLOT(refresh()) );
+}
+
+
+void K3bAudioProjectConvertingDialog::slotStartClicked()
+{
+ // make sure we have the tracks just for ourselves
+ static_cast<K3bAudioView*>(m_doc->view())->player()->stop();
+
+ // check if all filenames differ
+ if( d->filenames.count() > 1 ) {
+ bool differ = true;
+ // the most stupid version to compare but most cds have about 12 tracks
+ // that's a size where algorithms do not need any optimization! ;)
+ for( unsigned int i = 0; i < d->filenames.count(); ++i ) {
+ for( unsigned int j = i+1; j < d->filenames.count(); ++j )
+ if( d->filenames[i] == d->filenames[j] ) {
+ differ = false;
+ break;
+ }
+ }
+
+ if( !differ ) {
+ KMessageBox::sorry( this, i18n("Please check the naming pattern. All filenames need to be unique.") );
+ return;
+ }
+ }
+
+ // check if we need to overwrite some files...
+ QListViewItemIterator it( m_viewTracks );
+ QStringList filesToOverwrite;
+ for( unsigned int i = 0; i < d->filenames.count(); ++i ) {
+ if( QFile::exists( d->filenames[i] ) )
+ filesToOverwrite.append( d->filenames[i] );
+ }
+
+ if( m_optionWidget->createPlaylist() && QFile::exists( d->playlistFilename ) )
+ filesToOverwrite.append( d->playlistFilename );
+
+ if( !filesToOverwrite.isEmpty() )
+ if( KMessageBox::warningContinueCancelList( this,
+ i18n("Do you want to overwrite these files?"),
+ filesToOverwrite,
+ i18n("Files Exist"), i18n("Overwrite") ) == KMessageBox::Cancel )
+ return;
+
+
+ // just generate a fake m_tracks list for now so we can keep most of the methods
+ // like they are in K3bAudioRipThread. This way future combination is easier
+ QValueVector<QPair<int, QString> > tracksToRip;
+ int i = 0;
+ K3bAudioTrack* track = m_doc->firstTrack();
+ while( track ) {
+ tracksToRip.append( qMakePair( i+1, d->filenames[(m_optionWidget->createSingleFile() ? 0 : i)] ) );
+ ++i;
+ track = track->next();
+ }
+
+ K3bAudioEncoder* encoder = m_optionWidget->encoder();
+
+ K3bAudioProjectConvertingThread* thread = new K3bAudioProjectConvertingThread( m_doc );
+ thread->setCddbEntry( createCddbEntryFromDoc( m_doc ) );
+ thread->setTracksToRip( tracksToRip );
+ thread->setSingleFile( m_optionWidget->createSingleFile() );
+ thread->setWriteCueFile( m_optionWidget->createCueFile() );
+ thread->setEncoder( encoder );
+ thread->setWritePlaylist( m_optionWidget->createPlaylist() );
+ thread->setPlaylistFilename( d->playlistFilename );
+ thread->setUseRelativePathInPlaylist( m_optionWidget->playlistRelativePath() );
+ if( encoder )
+ thread->setFileType( m_optionWidget->extension() );
+
+ K3bJobProgressDialog progressDialog( parentWidget() );
+
+ K3bThreadJob job( thread, &progressDialog, this );
+
+ hide();
+ progressDialog.startJob(&job);
+
+ delete thread;
+
+ close();
+}
+
+
+void K3bAudioProjectConvertingDialog::refresh()
+{
+ m_viewTracks->clear();
+ d->filenames.clear();
+
+ // FIXME: this is bad and needs to be improved
+ // create a cddb entry from the doc to use in the patternparser
+ K3bCddbResultEntry cddbEntry = createCddbEntryFromDoc( m_doc );
+
+ QString baseDir = K3b::prepareDir( m_optionWidget->baseDir() );
+
+ QString extension = m_optionWidget->extension();
+
+ KIO::filesize_t overallSize = 0;
+
+ if( m_optionWidget->createSingleFile() ) {
+ QString filename;
+ long long filesize = 0;
+ if( m_optionWidget->encoder() == 0 ) {
+ filesize = m_doc->length().audioBytes() + 44;
+ }
+ else {
+ filesize = m_optionWidget->encoder()->fileSize( extension, m_doc->length() );
+ }
+
+ if( filesize > 0 )
+ overallSize = filesize;
+
+ filename = K3bPatternParser::parsePattern( cddbEntry, 1,
+ m_patternWidget->filenamePattern(),
+ m_patternWidget->replaceBlanks(),
+ m_patternWidget->blankReplaceString() );
+
+
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename + "." + extension,
+ m_doc->length().toString(),
+ filesize < 0 ? i18n("unknown") : KIO::convertSize( filesize ) );
+
+ d->filenames.append( K3b::fixupPath( baseDir + "/" + filename + "." + extension ) );
+
+ if( m_optionWidget->createCueFile() ) {
+ d->cueFilename = K3b::fixupPath( baseDir + "/" + filename + ".cue" );
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename + ".cue",
+ "-",
+ "-",
+ i18n("Cue-file") );
+ }
+ }
+ else {
+ K3bAudioTrack* track = m_doc->firstTrack();
+ unsigned int i = 1;
+ while( track ) {
+ long long filesize = 0;
+ if( m_optionWidget->encoder() == 0 ) {
+ filesize = track->length().audioBytes() + 44;
+ }
+ else {
+ filesize = m_optionWidget->encoder()->fileSize( extension, track->length() );
+ }
+
+ if( filesize > 0 )
+ overallSize += filesize;
+
+ QString filename = K3bPatternParser::parsePattern( cddbEntry, i,
+ m_patternWidget->filenamePattern(),
+ m_patternWidget->replaceBlanks(),
+ m_patternWidget->blankReplaceString() ) + "." + extension;
+
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename,
+ track->length().toString(),
+ filesize < 0 ? i18n("unknown") : KIO::convertSize( filesize ) );
+
+ d->filenames.append( K3b::fixupPath( baseDir + "/" + filename ) );
+
+ track = track->next();
+ ++i;
+ }
+ }
+
+ // create playlist item
+ if( m_optionWidget->createPlaylist() ) {
+ QString filename = K3bPatternParser::parsePattern( cddbEntry, 1,
+ m_patternWidget->playlistPattern(),
+ m_patternWidget->replaceBlanks(),
+ m_patternWidget->blankReplaceString() ) + ".m3u";
+
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename,
+ "-",
+ "-",
+ i18n("Playlist") );
+
+ d->playlistFilename = K3b::fixupPath( baseDir + "/" + filename );
+ }
+
+ if( overallSize > 0 )
+ m_optionWidget->setNeededSize( overallSize );
+ else
+ m_optionWidget->setNeededSize( 0 );
+}
+
+
+void K3bAudioProjectConvertingDialog::setBaseDir( const QString& path )
+{
+ m_optionWidget->setBaseDir( path );
+}
+
+
+void K3bAudioProjectConvertingDialog::loadK3bDefaults()
+{
+ m_optionWidget->loadDefaults();
+ m_patternWidget->loadDefaults();
+
+ refresh();
+}
+
+void K3bAudioProjectConvertingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_optionWidget->loadConfig( c );
+ m_patternWidget->loadConfig( c );
+
+ refresh();
+}
+
+
+void K3bAudioProjectConvertingDialog::saveUserDefaults( KConfigBase* c )
+{
+ m_optionWidget->saveConfig( c );
+ m_patternWidget->saveConfig( c );
+}
+
+
+K3bCddbResultEntry K3bAudioProjectConvertingDialog::createCddbEntryFromDoc( K3bAudioDoc* doc )
+{
+ K3bCddbResultEntry e;
+
+ // global
+ e.cdTitle = doc->title();
+ e.cdArtist = doc->artist();
+ e.cdExtInfo = doc->cdTextMessage();
+
+ // tracks
+ K3bAudioTrack* track = doc->firstTrack();
+ while( track ) {
+ e.titles.append( track->title() );
+ e.artists.append( track->artist() );
+ e.extInfos.append( track->cdTextMessage() );
+
+ track = track->next();
+ }
+
+ return e;
+}
+
+#include "k3baudioprojectconvertingdialog.moc"
diff --git a/src/rip/k3baudioprojectconvertingdialog.h b/src/rip/k3baudioprojectconvertingdialog.h
new file mode 100644
index 0000000..1816ea2
--- /dev/null
+++ b/src/rip/k3baudioprojectconvertingdialog.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * $Id: k3baudioprojectconvertingdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_AUDIO_PROJECT_CONVERTING_DIALOG_H_
+#define _K3B_AUDIO_PROJECT_CONVERTING_DIALOG_H_
+
+#include <k3binteractiondialog.h>
+#include <k3bmsf.h>
+
+#include <qstringlist.h>
+
+
+class K3bListView;
+class QCheckBox;
+class QSpinBox;
+class QComboBox;
+class K3bCddbPatternWidget;
+class QToolButton;
+class K3bAudioConvertingOptionWidget;
+class K3bCddbResultEntry;
+class K3bAudioConvertingJob;
+class K3bJobHandler;
+class K3bAudioDoc;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bAudioProjectConvertingDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioProjectConvertingDialog( K3bAudioDoc*, QWidget *parent = 0, const char *name = 0 );
+ ~K3bAudioProjectConvertingDialog();
+
+ void setBaseDir( const QString& path );
+
+ public slots:
+ void refresh();
+
+ protected:
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+
+ private:
+ K3bCddbPatternWidget* m_patternWidget;
+ K3bAudioConvertingOptionWidget* m_optionWidget;
+
+ K3bListView* m_viewTracks;
+ K3bAudioDoc* m_doc;
+
+ void setupGui();
+
+ static K3bCddbResultEntry createCddbEntryFromDoc( K3bAudioDoc* );
+
+ class Private;
+ Private* d;
+
+ private slots:
+ void slotStartClicked();
+};
+
+#endif
diff --git a/src/rip/k3baudioprojectconvertingthread.cpp b/src/rip/k3baudioprojectconvertingthread.cpp
new file mode 100644
index 0000000..8c175fb
--- /dev/null
+++ b/src/rip/k3baudioprojectconvertingthread.cpp
@@ -0,0 +1,459 @@
+/*
+ *
+ * $Id: k3baudioprojectconvertingthread.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3baudioprojectconvertingthread.h"
+#include "k3bpatternparser.h"
+
+#include <k3bjob.h>
+#include <k3baudiodoc.h>
+#include <k3baudiotrack.h>
+#include <k3baudioencoder.h>
+#include <k3bwavefilewriter.h>
+#include "k3bcuefilewriter.h"
+
+#include <k3bglobals.h>
+
+#include <qfile.h>
+#include <qtimer.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+
+
+
+class K3bAudioProjectConvertingThread::Private
+{
+public:
+ Private()
+ : encoder(0),
+ waveFileWriter(0),
+ canceled(false) {
+ }
+
+ // the index of the currently ripped track in m_tracks
+ int currentTrackIndex;
+ long long overallBytesRead;
+ long long overallBytesToRead;
+
+ K3bAudioEncoder* encoder;
+ K3bWaveFileWriter* waveFileWriter;
+
+ bool canceled;
+
+ QString fileType;
+};
+
+
+K3bAudioProjectConvertingThread::K3bAudioProjectConvertingThread( K3bAudioDoc* doc )
+ : K3bThread(),
+ m_doc(doc)
+{
+ d = new Private();
+}
+
+
+K3bAudioProjectConvertingThread::~K3bAudioProjectConvertingThread()
+{
+ delete d->waveFileWriter;
+ delete d;
+}
+
+
+void K3bAudioProjectConvertingThread::setFileType( const QString& t )
+{
+ d->fileType = t;
+}
+
+
+void K3bAudioProjectConvertingThread::setEncoder( K3bAudioEncoder* f )
+{
+ d->encoder = f;
+}
+
+
+void K3bAudioProjectConvertingThread::init()
+{
+ d->canceled = false;
+}
+
+
+void K3bAudioProjectConvertingThread::run()
+{
+ emitStarted();
+ emitNewTask( i18n("Converting Audio Tracks") );
+
+ if( !d->encoder )
+ if( !d->waveFileWriter )
+ d->waveFileWriter = new K3bWaveFileWriter();
+
+
+ d->overallBytesRead = 0;
+ d->overallBytesToRead = m_doc->length().audioBytes();
+
+ if( m_singleFile ) {
+ QString& filename = m_tracks[0].second;
+
+ QString dir = filename.left( filename.findRev("/") );
+ if( !KStandardDirs::makeDir( dir ) ) {
+ emitInfoMessage( i18n("Unable to create directory %1").arg(dir), K3bJob::ERROR );
+ emitFinished(false);
+ return;
+ }
+
+ // initialize
+ bool isOpen = true;
+ if( d->encoder ) {
+ if( isOpen = d->encoder->openFile( d->fileType, filename, m_doc->length() ) ) {
+ // here we use cd Title and Artist
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_ARTIST, m_cddbEntry.cdArtist );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_TITLE, m_cddbEntry.cdTitle );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_COMMENT, m_cddbEntry.cdExtInfo );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_ARTIST, m_cddbEntry.cdArtist );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_TITLE, m_cddbEntry.cdTitle );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_COMMENT, m_cddbEntry.cdExtInfo );
+ d->encoder->setMetaData( K3bAudioEncoder::META_YEAR, QString::number(m_cddbEntry.year) );
+ d->encoder->setMetaData( K3bAudioEncoder::META_GENRE, m_cddbEntry.genre );
+ }
+ else
+ emitInfoMessage( d->encoder->lastErrorString(), K3bJob::ERROR );
+ }
+ else {
+ isOpen = d->waveFileWriter->open( filename );
+ }
+
+ if( !isOpen ) {
+ emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(filename), K3bJob::ERROR );
+ emitFinished(false);
+ return;
+ }
+
+ emitInfoMessage( i18n("Converting to single file '%1'.").arg(filename), K3bJob::INFO );
+ }
+
+ bool success = true;
+ K3bAudioTrack* track = m_doc->firstTrack();
+ unsigned int i = 0;
+ while( track ) {
+ d->currentTrackIndex = i;
+ if( !convertTrack( track, m_singleFile ? m_tracks[0].second : m_tracks[i].second ) ) {
+ success = false;
+ break;
+ }
+
+ emitInfoMessage( i18n("Successfully converted track %1.").arg(i+1), K3bJob::INFO );
+
+ track = track->next();
+ ++i;
+ }
+
+ if( m_singleFile ) {
+ if( d->encoder )
+ d->encoder->closeFile();
+ else
+ d->waveFileWriter->close();
+ }
+
+ if( !d->canceled && success && m_writePlaylist ) {
+ success = success && writePlaylist();
+ }
+
+ if( !d->canceled && success && m_writeCueFile && m_singleFile ) {
+ success = success && writeCueFile();
+ }
+
+ if( d->canceled ) {
+ if( d->currentTrackIndex >= 0 && d->currentTrackIndex < (int)m_tracks.count() ) {
+ if( QFile::exists( m_tracks[d->currentTrackIndex].second ) ) {
+ QFile::remove( m_tracks[d->currentTrackIndex].second );
+ emitInfoMessage( i18n("Removed partial file '%1'.").arg(m_tracks[d->currentTrackIndex].second), K3bJob::INFO );
+ }
+ }
+
+ emitCanceled();
+ emitFinished(false);
+ }
+ else
+ emitFinished(success);
+}
+
+
+bool K3bAudioProjectConvertingThread::convertTrack( K3bAudioTrack* track, const QString& filename )
+{
+ QString dir = filename.left( filename.findRev("/") );
+ if( !KStandardDirs::makeDir( dir ) ) {
+ emitInfoMessage( i18n("Unable to create directory %1").arg(dir), K3bJob::ERROR );
+ return false;
+ }
+
+ // initialize
+ bool isOpen = true;
+ if( !m_singleFile ) {
+ if( d->encoder ) {
+ if( isOpen = d->encoder->openFile( d->fileType,
+ filename,
+ track->length() ) ) {
+
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_ARTIST, m_cddbEntry.artists[d->currentTrackIndex] );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_TITLE, m_cddbEntry.titles[d->currentTrackIndex] );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_COMMENT, m_cddbEntry.extInfos[d->currentTrackIndex] );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_NUMBER, QString::number(d->currentTrackIndex+1).rightJustify( 2, '0' ) );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_ARTIST, m_cddbEntry.cdArtist );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_TITLE, m_cddbEntry.cdTitle );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_COMMENT, m_cddbEntry.cdExtInfo );
+ d->encoder->setMetaData( K3bAudioEncoder::META_YEAR, QString::number(m_cddbEntry.year) );
+ d->encoder->setMetaData( K3bAudioEncoder::META_GENRE, m_cddbEntry.genre );
+ }
+ else
+ emitInfoMessage( d->encoder->lastErrorString(), K3bJob::ERROR );
+ }
+ else {
+ isOpen = d->waveFileWriter->open( filename );
+ }
+
+ if( !isOpen ) {
+ emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(filename), K3bJob::ERROR );
+ return false;
+ }
+ }
+
+
+ if( !m_cddbEntry.artists[d->currentTrackIndex].isEmpty() &&
+ !m_cddbEntry.titles[d->currentTrackIndex].isEmpty() )
+ emitNewSubTask( i18n("Converting track %1 (%2 - %3)")
+ .arg(d->currentTrackIndex+1)
+ .arg(m_cddbEntry.artists[d->currentTrackIndex])
+ .arg(m_cddbEntry.titles[d->currentTrackIndex]) );
+ else
+ emitNewSubTask( i18n("Converting track %1").arg(d->currentTrackIndex+1) );
+
+
+ // do the conversion
+ // ----------------------
+
+ char buffer[10*1024];
+ const int bufferLength = 10*1024;
+ int readLength = 0;
+ long long readFile = 0;
+ track->seek(0);
+ while( !d->canceled && ( readLength = track->read( buffer, bufferLength ) ) > 0 ) {
+
+ if( d->encoder ) {
+ // the tracks produce big endian samples
+ // so we need to swap the bytes here
+ char b;
+ for( int i = 0; i < bufferLength-1; i+=2 ) {
+ b = buffer[i];
+ buffer[i] = buffer[i+1];
+ buffer[i+1] = b;
+ }
+
+ if( d->encoder->encode( buffer, readLength ) < 0 ) {
+ kdDebug() << "(K3bAudioProjectConvertingThread) error while encoding." << endl;
+ emitInfoMessage( d->encoder->lastErrorString(), K3bJob::ERROR );
+ emitInfoMessage( i18n("Error while encoding track %1.").arg(d->currentTrackIndex+1), K3bJob::ERROR );
+ return false;
+ }
+ }
+ else {
+ d->waveFileWriter->write( buffer,
+ readLength,
+ K3bWaveFileWriter::BigEndian );
+ }
+
+ d->overallBytesRead += readLength;
+ readFile += readLength;
+ emitSubPercent( 100*readFile/track->size() );
+ emitPercent( 100*d->overallBytesRead/d->overallBytesToRead );
+ }
+
+ if( !m_singleFile ) {
+ if( d->encoder )
+ d->encoder->closeFile();
+ else
+ d->waveFileWriter->close();
+ }
+
+ return ( readLength == 0 );
+}
+
+
+void K3bAudioProjectConvertingThread::cancel()
+{
+ d->canceled = true;
+}
+
+
+bool K3bAudioProjectConvertingThread::writePlaylist()
+{
+ // this is an absolut path so there is always a "/"
+ QString playlistDir = m_playlistFilename.left( m_playlistFilename.findRev( "/" ) );
+
+ if( !KStandardDirs::makeDir( playlistDir ) ) {
+ emitInfoMessage( i18n("Unable to create directory %1").arg(playlistDir), K3bJob::ERROR );
+ return false;
+ }
+
+ emitInfoMessage( i18n("Writing playlist to %1.").arg( m_playlistFilename ), K3bJob::INFO );
+
+ QFile f( m_playlistFilename );
+ if( f.open( IO_WriteOnly ) ) {
+ QTextStream t( &f );
+
+ // format descriptor
+ t << "#EXTM3U" << endl;
+
+ // now write the entries (or the entry if m_singleFile)
+ if( m_singleFile ) {
+ // extra info
+ t << "#EXTINF:" << m_doc->length().lba() << ",";
+ if( !m_cddbEntry.cdArtist.isEmpty() && !m_cddbEntry.cdTitle.isEmpty() )
+ t << m_cddbEntry.cdArtist << " - " << m_cddbEntry.cdTitle << endl;
+ else
+ t << m_tracks[0].second.mid(m_tracks[0].second.findRev("/") + 1,
+ m_tracks[0].second.length() - m_tracks[0].second.findRev("/") - 5)
+ << endl; // filename without extension
+
+ // filename
+ if( m_relativePathInPlaylist )
+ t << findRelativePath( m_tracks[0].second, playlistDir )
+ << endl;
+ else
+ t << m_tracks[0].second << endl;
+ }
+ else {
+ for( unsigned int i = 0; i < m_tracks.count(); ++i ) {
+ int trackIndex = m_tracks[i].first-1;
+
+ // extra info
+ t << "#EXTINF:" << m_doc->length().totalFrames()/75 << ",";
+
+ if( !m_cddbEntry.artists[trackIndex].isEmpty() && !m_cddbEntry.titles[trackIndex].isEmpty() )
+ t << m_cddbEntry.artists[trackIndex] << " - " << m_cddbEntry.titles[trackIndex] << endl;
+ else
+ t << m_tracks[i].second.mid(m_tracks[i].second.findRev("/") + 1,
+ m_tracks[i].second.length()
+ - m_tracks[i].second.findRev("/") - 5)
+ << endl; // filename without extension
+
+ // filename
+ if( m_relativePathInPlaylist )
+ t << findRelativePath( m_tracks[i].second, playlistDir )
+ << endl;
+ else
+ t << m_tracks[i].second << endl;
+ }
+ }
+
+ return ( t.device()->status() == IO_Ok );
+ }
+ else {
+ emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(m_playlistFilename), K3bJob::ERROR );
+ kdDebug() << "(K3bAudioProjectConvertingThread) could not open file " << m_playlistFilename << " for writing." << endl;
+ return false;
+ }
+}
+
+
+bool K3bAudioProjectConvertingThread::writeCueFile()
+{
+ K3bCueFileWriter cueWriter;
+
+ // create a new toc and cd-text
+ K3bDevice::Toc toc;
+ K3bDevice::CdText text;
+ text.setPerformer( m_cddbEntry.cdArtist );
+ text.setTitle( m_cddbEntry.cdTitle );
+ text.reserve( m_tracks.count() );
+ K3b::Msf currentSector;
+ K3bAudioTrack* track = m_doc->firstTrack();
+ int trackNum = 1;
+ while( track ) {
+
+ K3bDevice::Track newTrack( currentSector, (currentSector+=track->length()) - 1, K3bDevice::Track::AUDIO );
+ toc.append( newTrack );
+
+ K3bDevice::TrackCdText trackText;
+ trackText.setPerformer( m_cddbEntry.artists[trackNum-1] );
+ trackText.setTitle( m_cddbEntry.titles[trackNum-1] );
+ text.append( trackText );
+
+ track = track->next();
+ ++trackNum;
+ }
+
+ cueWriter.setData( toc );
+ cueWriter.setCdText( text );
+
+
+ // we always use a relative filename here
+ QString imageFile = m_tracks[0].second.section( '/', -1 );
+ cueWriter.setImage( imageFile, ( d->fileType.isEmpty() ? QString("WAVE") : d->fileType ) );
+
+ // use the same base name as the image file
+ QString cueFile = m_tracks[0].second;
+ cueFile.truncate( cueFile.findRev(".") );
+ cueFile += ".cue";
+
+ emitInfoMessage( i18n("Writing cue file to %1.").arg(cueFile), K3bJob::INFO );
+
+ return cueWriter.save( cueFile );
+}
+
+
+QString K3bAudioProjectConvertingThread::findRelativePath( const QString& absPath, const QString& baseDir )
+{
+ QString baseDir_ = K3b::prepareDir( K3b::fixupPath(baseDir) );
+ QString path = K3b::fixupPath( absPath );
+
+ // both paths have an equal beginning. That's just how it's configured by K3b
+ int pos = baseDir_.find( "/" );
+ int oldPos = pos;
+ while( pos != -1 && path.left( pos+1 ) == baseDir_.left( pos+1 ) ) {
+ oldPos = pos;
+ pos = baseDir_.find( "/", pos+1 );
+ }
+
+ // now the paths are equal up to oldPos, so that's how "deep" we go
+ path = path.mid( oldPos+1 );
+ baseDir_ = baseDir_.mid( oldPos+1 );
+ int numberOfDirs = baseDir_.contains( '/' );
+ for( int i = 0; i < numberOfDirs; ++i )
+ path.prepend( "../" );
+
+ return path;
+}
+
+
+QString K3bAudioProjectConvertingThread::jobDescription() const
+{
+ if( m_cddbEntry.cdTitle.isEmpty() )
+ return i18n("Converting Audio Tracks");
+ else
+ return i18n("Converting Audio Tracks From '%1'").arg(m_cddbEntry.cdTitle);
+}
+
+QString K3bAudioProjectConvertingThread::jobDetails() const
+{
+ if( d->encoder )
+ return i18n("1 track (encoding to %1)",
+ "%n tracks (encoding to %1)",
+ m_tracks.count() ).arg(d->encoder->fileTypeComment(d->fileType));
+ else
+ return i18n("1 track", "%n tracks", m_doc->numOfTracks() );
+}
+
diff --git a/src/rip/k3baudioprojectconvertingthread.h b/src/rip/k3baudioprojectconvertingthread.h
new file mode 100644
index 0000000..aeda217
--- /dev/null
+++ b/src/rip/k3baudioprojectconvertingthread.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * $Id: k3baudioprojectconvertingthread.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_AUDIO_PROJECT_CONVERTING_THREAD_H
+#define K3B_AUDIO_PROJECT_CONVERTING_THREAD_H
+
+#include <k3bthread.h>
+#include <qobject.h>
+#include <qvaluevector.h>
+#include <qpair.h>
+
+#include <k3bcddbresult.h>
+
+
+class K3bAudioEncoder;
+class K3bAudioDoc;
+class K3bAudioTrack;
+
+
+class K3bAudioProjectConvertingThread : public K3bThread
+{
+ public:
+ K3bAudioProjectConvertingThread( K3bAudioDoc* );
+ ~K3bAudioProjectConvertingThread();
+
+ QString jobDescription() const;
+ QString jobDetails() const;
+
+ void setSingleFile( bool b ) { m_singleFile = b; }
+
+ void setCddbEntry( const K3bCddbResultEntry& e ) { m_cddbEntry = e; }
+
+ // if 0 (default) wave files are created
+ void setEncoder( K3bAudioEncoder* f );
+
+ /**
+ * Used for encoders that support multiple formats
+ */
+ void setFileType( const QString& );
+
+ /**
+ * 1 is the first track
+ */
+ void setTracksToRip( const QValueVector<QPair<int, QString> >& t ) { m_tracks = t; }
+
+ void setWritePlaylist( bool b ) { m_writePlaylist = b; }
+ void setPlaylistFilename( const QString& s ) { m_playlistFilename = s; }
+ void setUseRelativePathInPlaylist( bool b ) { m_relativePathInPlaylist = b; }
+ void setWriteCueFile( bool b ) { m_writeCueFile = b; }
+
+ /**
+ * \reimplemented from K3bThread
+ */
+ void init();
+
+ void cancel();
+
+ private:
+ /** reimplemented from QThread. Does the work */
+ void run();
+
+ bool convertTrack( K3bAudioTrack*, const QString& filename );
+ bool writePlaylist();
+ bool writeCueFile();
+
+ /**
+ * Finds a relative path from baseDir to absPath
+ */
+ QString findRelativePath( const QString& absPath, const QString& baseDir );
+
+ K3bCddbResultEntry m_cddbEntry;
+
+ bool m_singleFile;
+ bool m_writePlaylist;
+ bool m_relativePathInPlaylist;
+ QString m_playlistFilename;
+
+ bool m_writeCueFile;
+
+ QValueVector<QPair<int, QString> > m_tracks;
+
+ K3bAudioDoc* m_doc;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/rip/k3baudioripjob.cpp b/src/rip/k3baudioripjob.cpp
new file mode 100644
index 0000000..ef520e1
--- /dev/null
+++ b/src/rip/k3baudioripjob.cpp
@@ -0,0 +1,77 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3baudioripjob.h"
+#include "k3baudioripthread.h"
+
+#include <k3bthreadjob.h>
+#include <k3bcore.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+
+K3bAudioRipJob::K3bAudioRipJob( K3bJobHandler* hdl, QObject* parent )
+ : K3bJob( hdl, parent )
+{
+ m_thread = new K3bAudioRipThread();
+ m_threadJob = new K3bThreadJob( m_thread, this, this );
+ connectSubJob( m_threadJob,
+ SLOT(slotRippingFinished(bool)),
+ SIGNAL(newTask(const QString&)),
+ SIGNAL(newSubTask(const QString&)),
+ SIGNAL(percent(int)),
+ SIGNAL(subPercent(int)) );
+}
+
+
+K3bAudioRipJob::~K3bAudioRipJob()
+{
+}
+
+
+QString K3bAudioRipJob::jobDescription() const
+{
+ return m_thread->jobDescription();
+}
+
+
+QString K3bAudioRipJob::jobDetails() const
+{
+ return m_thread->jobDetails();
+}
+
+
+void K3bAudioRipJob::start()
+{
+ jobStarted();
+ k3bcore->blockDevice( m_thread->m_device );
+ m_threadJob->start();
+}
+
+
+void K3bAudioRipJob::cancel()
+{
+ m_threadJob->cancel();
+}
+
+
+void K3bAudioRipJob::slotRippingFinished( bool success )
+{
+ k3bcore->unblockDevice( m_thread->m_device );
+ jobFinished( success );
+}
+
+#include "k3baudioripjob.moc"
diff --git a/src/rip/k3baudioripjob.h b/src/rip/k3baudioripjob.h
new file mode 100644
index 0000000..adf47f3
--- /dev/null
+++ b/src/rip/k3baudioripjob.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_AUDIORIP_JOB_H_
+#define _K3B_AUDIORIP_JOB_H_
+
+#include <k3bjob.h>
+
+#include "k3baudioripthread.h"
+#include <k3bdevice.h>
+#include <k3bcddbresult.h>
+#include <k3baudioencoder.h>
+
+#include <qvaluevector.h>
+
+class K3bInterferingSystemsHandler;
+class K3bThreadJob;
+
+
+class K3bAudioRipJob : public K3bJob
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioRipJob( K3bJobHandler* hdl, QObject* parent );
+ ~K3bAudioRipJob();
+
+ QString jobDescription() const;
+ QString jobDetails() const;
+
+ public slots:
+ void start();
+ void cancel();
+
+ void setDevice( K3bDevice::Device* dev ) { m_thread->setDevice( dev ); }
+ void setCddbEntry( const K3bCddbResultEntry& entry ) { m_thread->setCddbEntry( entry ); }
+ void setTracksToRip( const QValueVector<QPair<int, QString> >& tracksToRip ) { m_thread->setTracksToRip( tracksToRip ); }
+ void setParanoiaMode( int mode ) { m_thread->setParanoiaMode( mode ); }
+ void setMaxRetries( int retries ) { m_thread->setMaxRetries( retries ); }
+ void setNeverSkip( bool neverSkip ) { m_thread->setNeverSkip( neverSkip ); }
+ void setSingleFile( bool singleFile ) { m_thread->setSingleFile( singleFile ); }
+ void setWriteCueFile( bool cue ) { m_thread->setWriteCueFile( cue ); }
+ void setEncoder( K3bAudioEncoder* encoder ) { m_thread->setEncoder( encoder ); }
+ void setWritePlaylist( bool playlist ) { m_thread->setWritePlaylist( playlist ); }
+ void setPlaylistFilename( const QString& filename ) { m_thread->setPlaylistFilename( filename ); }
+ void setUseRelativePathInPlaylist( bool relative ) { m_thread->setUseRelativePathInPlaylist( relative ); }
+ void setUseIndex0( bool index0 ) { m_thread->setUseIndex0( index0 ); }
+ void setFileType( const QString& filetype ) { m_thread->setFileType( filetype ); }
+
+ private slots:
+ void slotRippingFinished( bool );
+
+ private:
+ K3bInterferingSystemsHandler* m_interferingSystemsHandler;
+ K3bThreadJob* m_threadJob;
+ K3bAudioRipThread* m_thread;
+};
+
+#endif
diff --git a/src/rip/k3baudiorippingdialog.cpp b/src/rip/k3baudiorippingdialog.cpp
new file mode 100644
index 0000000..693230f
--- /dev/null
+++ b/src/rip/k3baudiorippingdialog.cpp
@@ -0,0 +1,470 @@
+/*
+ *
+ * $Id: k3baudiorippingdialog.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3baudiorippingdialog.h"
+#include "k3baudioripjob.h"
+#include "k3bpatternparser.h"
+#include "k3bcddbpatternwidget.h"
+#include "k3baudioconvertingoptionwidget.h"
+
+#include <k3bjobprogressdialog.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+#include <k3btrack.h>
+#include <k3bstdguiitems.h>
+#include <k3bfilesysteminfo.h>
+#include <k3bpluginmanager.h>
+#include <k3baudioencoder.h>
+
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <klistview.h>
+#include <kurlrequester.h>
+#include <kfiledialog.h>
+#include <kio/global.h>
+#include <kiconloader.h>
+#include <kstdguiitem.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kurllabel.h>
+
+#include <qgroupbox.h>
+#include <qheader.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <qmessagebox.h>
+#include <qfont.h>
+#include <qhbox.h>
+#include <qtoolbutton.h>
+#include <qtabwidget.h>
+#include <qspinbox.h>
+#include <qptrlist.h>
+#include <qintdict.h>
+#include <qpair.h>
+#include <qvalidator.h>
+
+
+class K3bAudioRippingDialog::Private
+{
+public:
+ Private() {
+ }
+
+ QValueVector<QString> filenames;
+ QString playlistFilename;
+ K3bFileSystemInfo fsInfo;
+};
+
+
+K3bAudioRippingDialog::K3bAudioRippingDialog(const K3bDevice::Toc& toc,
+ K3bDevice::Device* device,
+ const K3bCddbResultEntry& entry,
+ const QValueList<int>& tracks,
+ QWidget *parent, const char *name )
+ : K3bInteractionDialog( parent, name,
+ QString::null,
+ QString::null,
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "Audio Ripping" ), // config group
+ m_toc( toc ),
+ m_device( device ),
+ m_cddbEntry( entry ),
+ m_trackNumbers( tracks )
+{
+ d = new Private();
+
+ setupGui();
+ setupContextHelp();
+
+ K3b::Msf length;
+ for( QValueList<int>::const_iterator it = m_trackNumbers.begin();
+ it != m_trackNumbers.end(); ++it ) {
+ length += m_toc[*it-1].length();
+ }
+ setTitle( i18n("CD Ripping"),
+ i18n("1 track (%1)", "%n tracks (%1)",
+ m_trackNumbers.count()).arg(length.toString()) );
+}
+
+
+K3bAudioRippingDialog::~K3bAudioRippingDialog()
+{
+ delete d;
+}
+
+
+void K3bAudioRippingDialog::setupGui()
+{
+ QWidget *frame = mainWidget();
+ QGridLayout* Form1Layout = new QGridLayout( frame );
+ Form1Layout->setSpacing( KDialog::spacingHint() );
+ Form1Layout->setMargin( 0 );
+
+ m_viewTracks = new KListView( frame, "m_viewTracks" );
+ m_viewTracks->addColumn(i18n( "Filename") );
+ m_viewTracks->addColumn(i18n( "Length") );
+ m_viewTracks->addColumn(i18n( "File Size") );
+ m_viewTracks->addColumn(i18n( "Type") );
+ m_viewTracks->setSorting(-1);
+ m_viewTracks->setAllColumnsShowFocus(true);
+ m_viewTracks->setFullWidth(true);
+
+ QTabWidget* mainTab = new QTabWidget( frame );
+
+ m_optionWidget = new K3bAudioConvertingOptionWidget( mainTab );
+ mainTab->addTab( m_optionWidget, i18n("Settings") );
+
+
+ // setup filename pattern page
+ // -------------------------------------------------------------------------------------------
+ m_patternWidget = new K3bCddbPatternWidget( mainTab );
+ mainTab->addTab( m_patternWidget, i18n("File Naming") );
+ connect( m_patternWidget, SIGNAL(changed()), this, SLOT(refresh()) );
+
+
+ // setup advanced page
+ // -------------------------------------------------------------------------------------------
+ QWidget* advancedPage = new QWidget( mainTab );
+ QGridLayout* advancedPageLayout = new QGridLayout( advancedPage );
+ advancedPageLayout->setMargin( marginHint() );
+ advancedPageLayout->setSpacing( spacingHint() );
+ mainTab->addTab( advancedPage, i18n("Advanced") );
+
+ m_comboParanoiaMode = K3bStdGuiItems::paranoiaModeComboBox( advancedPage );
+ m_spinRetries = new QSpinBox( advancedPage );
+ m_checkIgnoreReadErrors = new QCheckBox( i18n("Ignore read errors"), advancedPage );
+ m_checkUseIndex0 = new QCheckBox( i18n("Don't read pregaps"), advancedPage );
+
+ advancedPageLayout->addWidget( new QLabel( i18n("Paranoia mode:"), advancedPage ), 0, 0 );
+ advancedPageLayout->addWidget( m_comboParanoiaMode, 0, 1 );
+ advancedPageLayout->addWidget( new QLabel( i18n("Read retries:"), advancedPage ), 1, 0 );
+ advancedPageLayout->addWidget( m_spinRetries, 1, 1 );
+ advancedPageLayout->addMultiCellWidget( m_checkIgnoreReadErrors, 2, 2, 0, 1 );
+ advancedPageLayout->addMultiCellWidget( m_checkUseIndex0, 3, 3, 0, 1 );
+ advancedPageLayout->setRowStretch( 4, 1 );
+ advancedPageLayout->setColStretch( 2, 1 );
+
+ // -------------------------------------------------------------------------------------------
+
+
+ Form1Layout->addWidget( m_viewTracks, 0, 0 );
+ Form1Layout->addWidget( mainTab, 1, 0 );
+ Form1Layout->setRowStretch( 0, 1 );
+
+ setStartButtonText( i18n( "Start Ripping" ), i18n( "Starts copying the selected tracks") );
+
+ connect( m_checkUseIndex0, SIGNAL(toggled(bool)), this, SLOT(refresh()) );
+ connect( m_optionWidget, SIGNAL(changed()), this, SLOT(refresh()) );
+}
+
+
+void K3bAudioRippingDialog::setupContextHelp()
+{
+ QToolTip::add( m_spinRetries, i18n("Maximal number of read retries") );
+ QWhatsThis::add( m_spinRetries, i18n("<p>This specifies the maximum number of retries to "
+ "read a sector of audio data from the cd. After that "
+ "K3b will either skip the sector if the <em>Ignore Read Errors</em> "
+ "option is enabled or stop the process.") );
+ QToolTip::add( m_checkUseIndex0, i18n("Do not read the pregaps at the end of every track") );
+ QWhatsThis::add( m_checkUseIndex0, i18n("<p>If this option is checked K3b will not rip the audio "
+ "data in the pregaps. Most audio tracks contain an empty "
+ "pregap which does not belong to the track itself.</p>"
+ "<p>Although the default behaviour of nearly all ripping "
+ "software is to include the pregaps for most CDs it makes more "
+ "sense to ignore them. When creating a K3b audio project you "
+ "will regenerate these pregaps anyway.</p>") );
+}
+
+
+void K3bAudioRippingDialog::init()
+{
+ refresh();
+}
+
+
+void K3bAudioRippingDialog::slotStartClicked()
+{
+ // check if all filenames differ
+ if( d->filenames.count() > 1 ) {
+ bool differ = true;
+ // the most stupid version to compare but most cds have about 12 tracks
+ // that's a size where algorithms do not need any optimization! ;)
+ for( unsigned int i = 0; i < d->filenames.count(); ++i ) {
+ for( unsigned int j = i+1; j < d->filenames.count(); ++j )
+ if( d->filenames[i] == d->filenames[j] ) {
+ differ = false;
+ break;
+ }
+ }
+
+ if( !differ ) {
+ KMessageBox::sorry( this, i18n("Please check the naming pattern. All filenames need to be unique.") );
+ return;
+ }
+ }
+
+ // check if we need to overwrite some files...
+ QListViewItemIterator it( m_viewTracks );
+ QStringList filesToOverwrite;
+ for( unsigned int i = 0; i < d->filenames.count(); ++i ) {
+ if( QFile::exists( d->filenames[i] ) )
+ filesToOverwrite.append( d->filenames[i] );
+ }
+
+ if( m_optionWidget->createPlaylist() && QFile::exists( d->playlistFilename ) )
+ filesToOverwrite.append( d->playlistFilename );
+
+ if( !filesToOverwrite.isEmpty() )
+ if( KMessageBox::questionYesNoList( this,
+ i18n("Do you want to overwrite these files?"),
+ filesToOverwrite,
+ i18n("Files Exist"), i18n("Overwrite"), KStdGuiItem::cancel() ) == KMessageBox::No )
+ return;
+
+
+ // prepare list of tracks to rip
+ QValueVector<QPair<int, QString> > tracksToRip;
+ unsigned int i = 0;
+ for( QValueList<int>::const_iterator trackIt = m_trackNumbers.begin();
+ trackIt != m_trackNumbers.end(); ++trackIt ) {
+ tracksToRip.append( qMakePair( *trackIt, d->filenames[(m_optionWidget->createSingleFile() ? 0 : i)] ) );
+ ++i;
+ }
+
+ K3bJobProgressDialog ripDialog( parentWidget(), "Ripping" );
+
+ K3bAudioEncoder* encoder = m_optionWidget->encoder();
+ K3bAudioRipJob* job = new K3bAudioRipJob( &ripDialog, this );
+ job->setDevice( m_device );
+ job->setCddbEntry( m_cddbEntry );
+ job->setTracksToRip( tracksToRip );
+ job->setParanoiaMode( m_comboParanoiaMode->currentText().toInt() );
+ job->setMaxRetries( m_spinRetries->value() );
+ job->setNeverSkip( !m_checkIgnoreReadErrors->isChecked() );
+ job->setSingleFile( m_optionWidget->createSingleFile() );
+ job->setWriteCueFile( m_optionWidget->createCueFile() );
+ job->setEncoder( encoder );
+ job->setWritePlaylist( m_optionWidget->createPlaylist() );
+ job->setPlaylistFilename( d->playlistFilename );
+ job->setUseRelativePathInPlaylist( m_optionWidget->playlistRelativePath() );
+ job->setUseIndex0( m_checkUseIndex0->isChecked() );
+ if( encoder )
+ job->setFileType( m_optionWidget->extension() );
+
+ hide();
+ ripDialog.startJob(job);
+
+ kdDebug() << "(K3bAudioRippingDialog) deleting ripjob." << endl;
+ delete job;
+
+ close();
+}
+
+
+void K3bAudioRippingDialog::refresh()
+{
+ m_viewTracks->clear();
+ d->filenames.clear();
+
+ QString baseDir = K3b::prepareDir( m_optionWidget->baseDir() );
+ d->fsInfo.setPath( baseDir );
+
+ KIO::filesize_t overallSize = 0;
+
+ if( m_optionWidget->createSingleFile() ) {
+ long length = 0;
+ for( QValueList<int>::const_iterator it = m_trackNumbers.begin();
+ it != m_trackNumbers.end(); ++it ) {
+ length += ( m_checkUseIndex0->isChecked()
+ ? m_toc[*it-1].realAudioLength().lba()
+ : m_toc[*it-1].length().lba() );
+ }
+
+ QString filename;
+ QString extension;
+ long long fileSize = 0;
+ if( m_optionWidget->encoder() == 0 ) {
+ extension = "wav";
+ fileSize = length * 2352 + 44;
+ }
+ else {
+ extension = m_optionWidget->extension();
+ fileSize = m_optionWidget->encoder()->fileSize( extension, length );
+ }
+
+ if( fileSize > 0 )
+ overallSize = fileSize;
+
+ if( (int)m_cddbEntry.titles.count() >= 1 ) {
+ filename = K3bPatternParser::parsePattern( m_cddbEntry, 1,
+ m_patternWidget->filenamePattern(),
+ m_patternWidget->replaceBlanks(),
+ m_patternWidget->blankReplaceString() );
+ }
+ else {
+ filename = i18n("Album");
+ }
+
+ filename = d->fsInfo.fixupPath( filename );
+
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename + "." + extension,
+ K3b::Msf(length).toString(),
+ fileSize < 0 ? i18n("unknown") : KIO::convertSize( fileSize ),
+ i18n("Audio") );
+ d->filenames.append( baseDir + "/" + filename + "." + extension );
+
+ if( m_optionWidget->createCueFile() )
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename + ".cue",
+ "-",
+ "-",
+ i18n("Cue-file") );
+ }
+ else {
+ for( QValueList<int>::const_iterator it = m_trackNumbers.begin();
+ it != m_trackNumbers.end(); ++it ) {
+ int index = *it - 1;
+
+ QString extension;
+ long long fileSize = 0;
+ K3b::Msf trackLength = ( m_checkUseIndex0->isChecked()
+ ? m_toc[index].realAudioLength()
+ : m_toc[index].length() );
+ if( m_optionWidget->encoder() == 0 ) {
+ extension = "wav";
+ fileSize = trackLength.audioBytes() + 44;
+ }
+ else {
+ extension = m_optionWidget->extension();
+ fileSize = m_optionWidget->encoder()->fileSize( extension, trackLength );
+ }
+
+ if( fileSize > 0 )
+ overallSize += fileSize;
+
+ if( m_toc[index].type() == K3bTrack::DATA ) {
+ extension = ".iso";
+ continue; // TODO: find out how to rip the iso data
+ }
+
+
+ QString filename;
+
+ if( (int)m_cddbEntry.titles.count() >= *it ) {
+ filename = K3bPatternParser::parsePattern( m_cddbEntry, *it,
+ m_patternWidget->filenamePattern(),
+ m_patternWidget->replaceBlanks(),
+ m_patternWidget->blankReplaceString() ) + "." + extension;
+ }
+ else {
+ filename = i18n("Track%1").arg( QString::number( *it ).rightJustify( 2, '0' ) ) + "." + extension;
+ }
+
+ filename = d->fsInfo.fixupPath( filename );
+
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename,
+ trackLength.toString(),
+ fileSize < 0 ? i18n("unknown") : KIO::convertSize( fileSize ),
+ (m_toc[index].type() == K3bTrack::AUDIO ? i18n("Audio") : i18n("Data") ) );
+
+ d->filenames.append( baseDir + "/" + filename );
+ }
+ }
+
+ // create playlist item
+ if( m_optionWidget->createPlaylist() ) {
+ QString filename = K3bPatternParser::parsePattern( m_cddbEntry, 1,
+ m_patternWidget->playlistPattern(),
+ m_patternWidget->replaceBlanks(),
+ m_patternWidget->blankReplaceString() ) + ".m3u";
+
+ (void)new KListViewItem( m_viewTracks,
+ m_viewTracks->lastItem(),
+ filename,
+ "-",
+ "-",
+ i18n("Playlist") );
+
+ d->playlistFilename = d->fsInfo.fixupPath( baseDir + "/" + filename );
+ }
+
+ if( overallSize > 0 )
+ m_optionWidget->setNeededSize( overallSize );
+ else
+ m_optionWidget->setNeededSize( 0 );
+}
+
+
+void K3bAudioRippingDialog::setStaticDir( const QString& path )
+{
+ m_optionWidget->setBaseDir( path );
+}
+
+
+void K3bAudioRippingDialog::loadK3bDefaults()
+{
+ m_comboParanoiaMode->setCurrentItem( 0 );
+ m_spinRetries->setValue(5);
+ m_checkIgnoreReadErrors->setChecked( true );
+ m_checkUseIndex0->setChecked( false );
+
+ m_optionWidget->loadDefaults();
+ m_patternWidget->loadDefaults();
+
+ refresh();
+}
+
+void K3bAudioRippingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_comboParanoiaMode->setCurrentItem( c->readNumEntry( "paranoia_mode", 0 ) );
+ m_spinRetries->setValue( c->readNumEntry( "read_retries", 5 ) );
+ m_checkIgnoreReadErrors->setChecked( !c->readBoolEntry( "never_skip", true ) );
+ m_checkUseIndex0->setChecked( c->readBoolEntry( "use_index0", false ) );
+
+ m_optionWidget->loadConfig( c );
+ m_patternWidget->loadConfig( c );
+
+ refresh();
+}
+
+void K3bAudioRippingDialog::saveUserDefaults( KConfigBase* c )
+{
+ c->writeEntry( "paranoia_mode", m_comboParanoiaMode->currentText().toInt() );
+ c->writeEntry( "read_retries", m_spinRetries->value() );
+ c->writeEntry( "never_skip", !m_checkIgnoreReadErrors->isChecked() );
+ c->writeEntry( "use_index0", m_checkUseIndex0->isChecked() );
+
+ m_optionWidget->saveConfig( c );
+ m_patternWidget->saveConfig( c );
+}
+
+
+#include "k3baudiorippingdialog.moc"
diff --git a/src/rip/k3baudiorippingdialog.h b/src/rip/k3baudiorippingdialog.h
new file mode 100644
index 0000000..83fe0dc
--- /dev/null
+++ b/src/rip/k3baudiorippingdialog.h
@@ -0,0 +1,92 @@
+/*
+ *
+ * $Id: k3baudiorippingdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_AUDIO_RIPPING_DIALOG_H_
+#define _K3B_AUDIO_RIPPING_DIALOG_H_
+
+#include <k3binteractiondialog.h>
+
+#include <qstringlist.h>
+
+#include <k3bcddbquery.h>
+
+namespace K3bDevice {
+ class Device;
+ class Toc;
+}
+
+
+class KListView;
+class QCheckBox;
+class QSpinBox;
+class QComboBox;
+class K3bCddbPatternWidget;
+class QToolButton;
+class K3bAudioConvertingOptionWidget;
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bAudioRippingDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioRippingDialog( const K3bDevice::Toc&,
+ K3bDevice::Device*,
+ const K3bCddbResultEntry&,
+ const QValueList<int>&,
+ QWidget *parent = 0, const char *name = 0 );
+ ~K3bAudioRippingDialog();
+
+ void setStaticDir( const QString& path );
+
+ public slots:
+ void refresh();
+ void init();
+
+ private:
+ K3bDevice::Toc m_toc;
+ K3bDevice::Device* m_device;
+ K3bCddbResultEntry m_cddbEntry;
+ QValueList<int> m_trackNumbers;
+
+ KListView* m_viewTracks;
+
+ QComboBox* m_comboParanoiaMode;
+ QSpinBox* m_spinRetries;
+ QCheckBox* m_checkIgnoreReadErrors;
+ QCheckBox* m_checkUseIndex0;
+
+ K3bCddbPatternWidget* m_patternWidget;
+ K3bAudioConvertingOptionWidget* m_optionWidget;
+
+ void setupGui();
+ void setupContextHelp();
+
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+
+ class Private;
+ Private* d;
+
+ private slots:
+ void slotStartClicked();
+};
+
+#endif
diff --git a/src/rip/k3baudioripthread.cpp b/src/rip/k3baudioripthread.cpp
new file mode 100644
index 0000000..8a5a6e9
--- /dev/null
+++ b/src/rip/k3baudioripthread.cpp
@@ -0,0 +1,602 @@
+/*
+ *
+ * $Id: k3baudioripthread.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3baudioripthread.h"
+#include "k3bpatternparser.h"
+
+#include <k3bcdparanoialib.h>
+#include <k3bjob.h>
+#include <k3baudioencoder.h>
+#include <k3bwavefilewriter.h>
+#include <k3bglobalsettings.h>
+#include <k3bcore.h>
+#include "k3bcuefilewriter.h"
+
+#include <k3bdevice.h>
+#include <k3btoc.h>
+#include <k3btrack.h>
+#include <k3bglobals.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtimer.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+
+
+
+class K3bAudioRipThread::Private
+{
+public:
+ Private()
+ : paranoiaRetries(5),
+ neverSkip(false),
+ encoder(0),
+ waveFileWriter(0),
+ paranoiaLib(0),
+ canceled(false) {
+ }
+
+ // the index of the currently ripped track in m_tracks
+ int currentTrackIndex;
+ long overallSectorsRead;
+ long overallSectorsToRead;
+
+ int paranoiaMode;
+ int paranoiaRetries;
+ int neverSkip;
+
+ K3bAudioEncoder* encoder;
+ K3bWaveFileWriter* waveFileWriter;
+
+ K3bCdparanoiaLib* paranoiaLib;
+
+ bool canceled;
+
+ K3bDevice::Toc toc;
+
+ QString fileType;
+};
+
+
+K3bAudioRipThread::K3bAudioRipThread()
+ : QObject(),
+ K3bThread(),
+ m_device(0),
+ m_useIndex0(false)
+{
+ d = new Private();
+}
+
+
+K3bAudioRipThread::~K3bAudioRipThread()
+{
+ delete d->waveFileWriter;
+ delete d->paranoiaLib;
+ delete d;
+}
+
+
+void K3bAudioRipThread::setFileType( const QString& t )
+{
+ d->fileType = t;
+}
+
+
+void K3bAudioRipThread::setParanoiaMode( int mode )
+{
+ d->paranoiaMode = mode;
+}
+
+
+void K3bAudioRipThread::setMaxRetries( int r )
+{
+ d->paranoiaRetries = r;
+}
+
+
+void K3bAudioRipThread::setNeverSkip( bool b )
+{
+ d->neverSkip = b;
+}
+
+
+void K3bAudioRipThread::setEncoder( K3bAudioEncoder* f )
+{
+ d->encoder = f;
+}
+
+
+void K3bAudioRipThread::run()
+{
+ emitStarted();
+ emitNewTask( i18n("Extracting Digital Audio") );
+
+ if( !d->paranoiaLib ) {
+ d->paranoiaLib = K3bCdparanoiaLib::create();
+ }
+
+ if( !d->paranoiaLib ) {
+ emitInfoMessage( i18n("Could not load libcdparanoia."), K3bJob::ERROR );
+ emitFinished(false);
+ return;
+ }
+
+ // try to open the device
+ if( !m_device ) {
+ emitFinished(false);
+ return;
+ }
+
+ m_device->block(true);
+
+ emitInfoMessage( i18n("Reading CD table of contents."), K3bJob::INFO );
+ d->toc = m_device->readToc();
+
+ if( !d->paranoiaLib->initParanoia( m_device, d->toc ) ) {
+ emitInfoMessage( i18n("Could not open device %1").arg(m_device->blockDeviceName()),
+ K3bJob::ERROR );
+ m_device->block(false);
+
+ // check if we have write access to the generic device
+ if( m_device->interfaceType() == K3bDevice::SCSI &&
+ !m_device->genericDevice().isEmpty() &&
+ !QFileInfo( m_device->genericDevice() ).isWritable() )
+ emitInfoMessage( i18n("You need write access to %1").arg( m_device->genericDevice() ), K3bJob::ERROR );
+
+ emitFinished(false);
+ return;
+ }
+ d->paranoiaLib->setParanoiaMode( d->paranoiaMode );
+ d->paranoiaLib->setNeverSkip( d->neverSkip );
+ d->paranoiaLib->setMaxRetries( d->paranoiaRetries );
+
+
+ if( !d->encoder )
+ if( !d->waveFileWriter ) {
+ d->waveFileWriter = new K3bWaveFileWriter();
+ }
+
+
+ if( m_useIndex0 ) {
+ emitNewSubTask( i18n("Searching index 0 for all tracks") );
+ m_device->indexScan( d->toc );
+ }
+
+
+ d->canceled = false;
+ d->overallSectorsRead = 0;
+ d->overallSectorsToRead = 0;
+ for( unsigned int i = 0; i < m_tracks.count(); ++i ) {
+ if( m_useIndex0 )
+ d->overallSectorsToRead += d->toc[m_tracks[i].first-1].realAudioLength().lba();
+ else
+ d->overallSectorsToRead += d->toc[m_tracks[i].first-1].length().lba();
+ }
+
+
+ if( m_singleFile ) {
+ QString& filename = m_tracks[0].second;
+
+ QString dir = filename.left( filename.findRev("/") );
+ if( !KStandardDirs::makeDir( dir, 0777 ) ) {
+ d->paranoiaLib->close();
+ emitInfoMessage( i18n("Unable to create directory %1").arg(dir), K3bJob::ERROR );
+ m_device->block(false);
+ emitFinished(false);
+ return;
+ }
+
+ // initialize
+ bool isOpen = true;
+ if( d->encoder ) {
+ if( isOpen = d->encoder->openFile( d->fileType, filename, d->overallSectorsToRead ) ) {
+ // here we use cd Title and Artist
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_ARTIST, m_cddbEntry.cdArtist );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_TITLE, m_cddbEntry.cdTitle );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_COMMENT, m_cddbEntry.cdExtInfo );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_ARTIST, m_cddbEntry.cdArtist );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_TITLE, m_cddbEntry.cdTitle );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_COMMENT, m_cddbEntry.cdExtInfo );
+ d->encoder->setMetaData( K3bAudioEncoder::META_YEAR, QString::number(m_cddbEntry.year) );
+ d->encoder->setMetaData( K3bAudioEncoder::META_GENRE, m_cddbEntry.genre );
+ }
+ else
+ emitInfoMessage( d->encoder->lastErrorString(), K3bJob::ERROR );
+ }
+ else {
+ isOpen = d->waveFileWriter->open( filename );
+ }
+
+ if( !isOpen ) {
+ d->paranoiaLib->close();
+ emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(filename), K3bJob::ERROR );
+ m_device->block(false);
+ emitFinished(false);
+ return;
+ }
+
+ emitInfoMessage( i18n("Ripping to single file '%1'.").arg(filename), K3bJob::INFO );
+ }
+
+ emitInfoMessage( i18n("Starting digital audio extraction (ripping)."), K3bJob::INFO );
+
+ bool success = true;
+ for( unsigned int i = 0; i < m_tracks.count(); ++i ) {
+ d->currentTrackIndex = i;
+ if( !ripTrack( m_tracks[i].first, m_singleFile ? m_tracks[0].second : m_tracks[i].second ) ) {
+ success = false;
+ break;
+ }
+ }
+
+ if( m_singleFile ) {
+ if( d->encoder )
+ d->encoder->closeFile();
+ else
+ d->waveFileWriter->close();
+
+ if( success && !d->canceled ) {
+ QString& filename = m_tracks[0].second;
+ emitInfoMessage( i18n("Successfully ripped to %2.").arg(filename), K3bJob::INFO );
+ }
+ }
+
+ if( !d->canceled && m_writePlaylist ) {
+ success = success && writePlaylist();
+ }
+
+ if( !d->canceled && m_writeCueFile && m_singleFile ) {
+ if( !m_useIndex0 ) {
+ emitNewSubTask( i18n("Searching index 0 for all tracks") );
+ m_device->indexScan( d->toc );
+ }
+ success = success && writeCueFile();
+ }
+
+ d->paranoiaLib->close();
+ m_device->block(false);
+
+ if( d->canceled ) {
+ emitCanceled();
+ emitFinished(false);
+ }
+ else {
+ if( k3bcore->globalSettings()->ejectMedia() )
+ m_device->eject();
+
+ emitFinished(success);
+ }
+}
+
+
+bool K3bAudioRipThread::ripTrack( int track, const QString& filename )
+{
+ const K3bTrack& tt = d->toc[track-1];
+
+ long endSec = ( (m_useIndex0 && tt.index0() > 0)
+ ? tt.firstSector().lba() + tt.index0().lba() - 1
+ : tt.lastSector().lba() );
+
+ if( d->paranoiaLib->initReading( tt.firstSector().lba(), endSec ) ) {
+
+ long trackSectorsRead = 0;
+
+ QString dir = filename.left( filename.findRev("/") );
+ if( !KStandardDirs::makeDir( dir, 0777 ) ) {
+ emitInfoMessage( i18n("Unable to create directory %1").arg(dir), K3bJob::ERROR );
+ return false;
+ }
+
+ // initialize
+ bool isOpen = true;
+ if( !m_singleFile ) {
+ if( d->encoder ) {
+ if( isOpen = d->encoder->openFile( d->fileType,
+ filename,
+ m_useIndex0 ? d->toc[track-1].realAudioLength() : d->toc[track-1].length() ) ) {
+
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_ARTIST, m_cddbEntry.artists[track-1] );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_TITLE, m_cddbEntry.titles[track-1] );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_COMMENT, m_cddbEntry.extInfos[track-1] );
+ d->encoder->setMetaData( K3bAudioEncoder::META_TRACK_NUMBER, QString::number(track).rightJustify( 2, '0' ) );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_ARTIST, m_cddbEntry.cdArtist );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_TITLE, m_cddbEntry.cdTitle );
+ d->encoder->setMetaData( K3bAudioEncoder::META_ALBUM_COMMENT, m_cddbEntry.cdExtInfo );
+ d->encoder->setMetaData( K3bAudioEncoder::META_YEAR, QString::number(m_cddbEntry.year) );
+ d->encoder->setMetaData( K3bAudioEncoder::META_GENRE, m_cddbEntry.genre );
+ }
+ else
+ emitInfoMessage( d->encoder->lastErrorString(), K3bJob::ERROR );
+ }
+ else {
+ isOpen = d->waveFileWriter->open( filename );
+ }
+
+ if( !isOpen ) {
+ emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(filename), K3bJob::ERROR );
+ return false;
+ }
+ }
+
+ if( !m_cddbEntry.artists[track-1].isEmpty() &&
+ !m_cddbEntry.titles[track-1].isEmpty() )
+ emitNewSubTask( i18n("Ripping track %1 (%2 - %3)").arg(track).arg(m_cddbEntry.artists[track-1]).arg(m_cddbEntry.titles[track-1]) );
+ else
+ emitNewSubTask( i18n("Ripping track %1").arg(track) );
+
+ int status;
+ while( 1 ) {
+ if( d->canceled ) {
+ cleanupAfterCancellation();
+ return false;
+ }
+
+ char* buf = d->paranoiaLib->read( &status );
+ if( status == K3bCdparanoiaLib::S_OK ) {
+ if( buf == 0 ) {
+ if( m_singleFile )
+ emitInfoMessage( i18n("Successfully ripped track %1.").arg(track), K3bJob::INFO );
+ else
+ emitInfoMessage( i18n("Successfully ripped track %1 to %2.").arg(track).arg(filename), K3bJob::INFO );
+
+ if( !m_singleFile ) {
+ if( d->encoder )
+ d->encoder->closeFile();
+ else
+ d->waveFileWriter->close();
+ }
+
+ return true;
+ }
+ else {
+ if( d->encoder ) {
+ if( d->encoder->encode( buf,
+ CD_FRAMESIZE_RAW ) < 0 ) {
+ kdDebug() << "(K3bAudioRipThread) error while encoding." << endl;
+ emitInfoMessage( d->encoder->lastErrorString(), K3bJob::ERROR );
+ emitInfoMessage( i18n("Error while encoding track %1.").arg(track), K3bJob::ERROR );
+ return false;
+ }
+ }
+ else
+ d->waveFileWriter->write( buf,
+ CD_FRAMESIZE_RAW,
+ K3bWaveFileWriter::LittleEndian );
+
+ trackSectorsRead++;
+ d->overallSectorsRead++;
+ emitSubPercent( 100*trackSectorsRead/d->toc[track-1].length().lba() );
+ emitPercent( 100*d->overallSectorsRead/d->overallSectorsToRead );
+ }
+ }
+ else {
+ emitInfoMessage( i18n("Unrecoverable error while ripping track %1.").arg(track), K3bJob::ERROR );
+ return false;
+ }
+ }
+ return true;
+ }
+ else {
+ emitInfoMessage( i18n("Error while initializing audio ripping."), K3bJob::ERROR );
+ return false;
+ }
+}
+
+
+void K3bAudioRipThread::cancel()
+{
+ d->canceled = true;
+
+ // what if paranoia is stuck in paranoia_read?
+ // we need to terminate in that case
+ // wait for 1 second. I the thread still is working terminate it
+ // and trigger the finished slot manually
+ emitInfoMessage( i18n("Cancellation could take a while..."), K3bJob::INFO );
+ QTimer::singleShot( 1000, this, SLOT(slotCheckIfThreadStillRunning()) );
+}
+
+
+void K3bAudioRipThread::slotCheckIfThreadStillRunning()
+{
+ if( running() ) {
+ d->paranoiaLib->close();
+ m_device->block(false);
+
+ // this could happen if the thread is stuck in paranoia_read
+ // because of an unreadable cd
+ terminate();
+ cleanupAfterCancellation();
+ emitCanceled();
+ emitFinished(false);
+ }
+}
+
+
+// this needs to be called if the thread was killed due to a hung paranoia_read
+void K3bAudioRipThread::cleanupAfterCancellation()
+{
+ if( d->currentTrackIndex >= 0 && d->currentTrackIndex < (int)m_tracks.count() ) {
+ if( QFile::exists( m_tracks[d->currentTrackIndex].second ) ) {
+ QFile::remove( m_tracks[d->currentTrackIndex].second );
+ emitInfoMessage( i18n("Removed partial file '%1'.").arg(m_tracks[d->currentTrackIndex].second), K3bJob::INFO );
+ }
+ }
+}
+
+
+bool K3bAudioRipThread::writePlaylist()
+{
+ // this is an absolut path so there is always a "/"
+ QString playlistDir = m_playlistFilename.left( m_playlistFilename.findRev( "/" ) );
+
+ if( !KStandardDirs::makeDir( playlistDir ) ) {
+ emitInfoMessage( i18n("Unable to create directory %1").arg(playlistDir), K3bJob::ERROR );
+ return false;
+ }
+
+ emitInfoMessage( i18n("Writing playlist to %1.").arg( m_playlistFilename ), K3bJob::INFO );
+
+ QFile f( m_playlistFilename );
+ if( f.open( IO_WriteOnly ) ) {
+ QTextStream t( &f );
+
+ // format descriptor
+ t << "#EXTM3U" << endl;
+
+ // now write the entries (or the entry if m_singleFile)
+ if( m_singleFile ) {
+ // extra info
+ t << "#EXTINF:" << d->overallSectorsToRead/75 << ",";
+ if( !m_cddbEntry.cdArtist.isEmpty() && !m_cddbEntry.cdTitle.isEmpty() )
+ t << m_cddbEntry.cdArtist << " - " << m_cddbEntry.cdTitle << endl;
+ else
+ t << m_tracks[0].second.mid(m_tracks[0].second.findRev("/") + 1,
+ m_tracks[0].second.length() - m_tracks[0].second.findRev("/") - 5)
+ << endl; // filename without extension
+
+ // filename
+ if( m_relativePathInPlaylist )
+ t << findRelativePath( m_tracks[0].second, playlistDir )
+ << endl;
+ else
+ t << m_tracks[0].second << endl;
+ }
+ else {
+ for( unsigned int i = 0; i < m_tracks.count(); ++i ) {
+ int trackIndex = m_tracks[i].first-1;
+
+ // extra info
+ t << "#EXTINF:" << d->toc[trackIndex].length().totalFrames()/75 << ",";
+
+ if( !m_cddbEntry.artists[trackIndex].isEmpty() && !m_cddbEntry.titles[trackIndex].isEmpty() )
+ t << m_cddbEntry.artists[trackIndex] << " - " << m_cddbEntry.titles[trackIndex] << endl;
+ else
+ t << m_tracks[i].second.mid(m_tracks[i].second.findRev("/") + 1,
+ m_tracks[i].second.length()
+ - m_tracks[i].second.findRev("/") - 5)
+ << endl; // filename without extension
+
+ // filename
+ if( m_relativePathInPlaylist )
+ t << findRelativePath( m_tracks[i].second, playlistDir )
+ << endl;
+ else
+ t << m_tracks[i].second << endl;
+ }
+ }
+
+ return ( t.device()->status() == IO_Ok );
+ }
+ else {
+ emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(m_playlistFilename), K3bJob::ERROR );
+ kdDebug() << "(K3bAudioRipThread) could not open file " << m_playlistFilename << " for writing." << endl;
+ return false;
+ }
+}
+
+
+bool K3bAudioRipThread::writeCueFile()
+{
+ K3bCueFileWriter cueWriter;
+
+ // create a new toc and cd-text
+ K3bDevice::Toc toc;
+ K3bDevice::CdText text;
+ text.setPerformer( m_cddbEntry.cdArtist );
+ text.setTitle( m_cddbEntry.cdTitle );
+ text.reserve( m_tracks.count() );
+ K3b::Msf currentSector;
+ for( unsigned int i = 0; i < m_tracks.count(); ++i ) {
+ int trackNum = m_tracks[i].first;
+
+ const K3bDevice::Track& oldTrack = d->toc[trackNum-1];
+ K3bDevice::Track newTrack( oldTrack );
+ newTrack.setFirstSector( currentSector );
+ newTrack.setLastSector( (currentSector+=oldTrack.length()) - 1 );
+ toc.append( newTrack );
+
+ K3bDevice::TrackCdText trackText;
+ trackText.setPerformer( m_cddbEntry.artists[trackNum-1] );
+ trackText.setTitle( m_cddbEntry.titles[trackNum-1] );
+ text.append( trackText );
+ }
+
+ cueWriter.setData( toc );
+ cueWriter.setCdText( text );
+
+
+ // we always use a relative filename here
+ QString imageFile = m_tracks[0].second.section( '/', -1 );
+ cueWriter.setImage( imageFile, ( d->fileType.isEmpty() ? QString("WAVE") : d->fileType ) );
+
+ // use the same base name as the image file
+ QString cueFile = m_tracks[0].second;
+ cueFile.truncate( cueFile.findRev(".") );
+ cueFile += ".cue";
+
+ emitInfoMessage( i18n("Writing cue file to %1.").arg(cueFile), K3bJob::INFO );
+
+ return cueWriter.save( cueFile );
+}
+
+
+QString K3bAudioRipThread::findRelativePath( const QString& absPath, const QString& baseDir )
+{
+ QString baseDir_ = K3b::prepareDir( K3b::fixupPath(baseDir) );
+ QString path = K3b::fixupPath( absPath );
+
+ // both paths have an equal beginning. That's just how it's configured by K3b
+ int pos = baseDir_.find( "/" );
+ int oldPos = pos;
+ while( pos != -1 && path.left( pos+1 ) == baseDir_.left( pos+1 ) ) {
+ oldPos = pos;
+ pos = baseDir_.find( "/", pos+1 );
+ }
+
+ // now the paths are equal up to oldPos, so that's how "deep" we go
+ path = path.mid( oldPos+1 );
+ baseDir_ = baseDir_.mid( oldPos+1 );
+ int numberOfDirs = baseDir_.contains( '/' );
+ for( int i = 0; i < numberOfDirs; ++i )
+ path.prepend( "../" );
+
+ return path;
+}
+
+
+QString K3bAudioRipThread::jobDescription() const
+{
+ if( m_cddbEntry.cdTitle.isEmpty() )
+ return i18n("Ripping Audio Tracks");
+ else
+ return i18n("Ripping Audio Tracks From '%1'").arg(m_cddbEntry.cdTitle);
+}
+
+QString K3bAudioRipThread::jobDetails() const
+{
+ if( d->encoder )
+ return i18n("1 track (encoding to %1)",
+ "%n tracks (encoding to %1)",
+ m_tracks.count() ).arg(d->encoder->fileTypeComment(d->fileType));
+ else
+ return i18n("1 track", "%n tracks", m_tracks.count() );
+}
+
+#include "k3baudioripthread.moc"
diff --git a/src/rip/k3baudioripthread.h b/src/rip/k3baudioripthread.h
new file mode 100644
index 0000000..93d600f
--- /dev/null
+++ b/src/rip/k3baudioripthread.h
@@ -0,0 +1,117 @@
+/*
+ *
+ * $Id: k3baudioripthread.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3B_AUDIO_RIP_THREAD_H
+#define K3B_AUDIO_RIP_THREAD_H
+
+#include <k3bthread.h>
+#include <qobject.h>
+#include <qvaluevector.h>
+#include <qpair.h>
+
+#include <k3bcddbquery.h>
+
+
+class K3bAudioEncoder;
+class K3bCdparanoiaLib;
+namespace K3bDevice {
+ class Device;
+}
+
+
+class K3bAudioRipThread : public QObject, public K3bThread
+{
+ Q_OBJECT
+
+ public:
+ K3bAudioRipThread();
+ ~K3bAudioRipThread();
+
+ QString jobDescription() const;
+ QString jobDetails() const;
+
+ // paranoia settings
+ void setParanoiaMode( int mode );
+ void setMaxRetries( int r );
+ void setNeverSkip( bool b );
+
+ void setSingleFile( bool b ) { m_singleFile = b; }
+
+ void setUseIndex0( bool b ) { m_useIndex0 = b; }
+
+ void setDevice( K3bDevice::Device* dev ) { m_device = dev; }
+
+ void setCddbEntry( const K3bCddbResultEntry& e ) { m_cddbEntry = e; }
+
+ // if 0 (default) wave files are created
+ void setEncoder( K3bAudioEncoder* f );
+
+ /**
+ * Used for encoders that support multiple formats
+ */
+ void setFileType( const QString& );
+
+ /**
+ * 1 is the first track
+ */
+ void setTracksToRip( const QValueVector<QPair<int, QString> >& t ) { m_tracks = t; }
+
+ void setWritePlaylist( bool b ) { m_writePlaylist = b; }
+ void setPlaylistFilename( const QString& s ) { m_playlistFilename = s; }
+ void setUseRelativePathInPlaylist( bool b ) { m_relativePathInPlaylist = b; }
+ void setWriteCueFile( bool b ) { m_writeCueFile = b; }
+
+ void cancel();
+
+ private slots:
+ void slotCheckIfThreadStillRunning();
+
+ private:
+ /** reimplemented from QThread. Does the work */
+ void run();
+
+ bool ripTrack( int track, const QString& filename );
+ void cleanupAfterCancellation();
+ bool writePlaylist();
+ bool writeCueFile();
+
+ /**
+ * Finds a relative path from baseDir to absPath
+ */
+ QString findRelativePath( const QString& absPath, const QString& baseDir );
+
+ K3bCddbResultEntry m_cddbEntry;
+ K3bDevice::Device* m_device;
+
+ bool m_bUsePattern;
+ bool m_singleFile;
+ bool m_useIndex0;
+
+ bool m_writePlaylist;
+ bool m_relativePathInPlaylist;
+ QString m_playlistFilename;
+
+ bool m_writeCueFile;
+
+ QValueVector<QPair<int, QString> > m_tracks;
+
+ friend class K3bAudioRipJob;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/rip/k3bcddbpatternwidget.cpp b/src/rip/k3bcddbpatternwidget.cpp
new file mode 100644
index 0000000..9cea4d5
--- /dev/null
+++ b/src/rip/k3bcddbpatternwidget.cpp
@@ -0,0 +1,175 @@
+/*
+ *
+ * $Id: k3bcddbpatternwidget.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bcddbpatternwidget.h"
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <kurllabel.h>
+#include <kdebug.h>
+
+#include <qregexp.h>
+#include <qvalidator.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+
+K3bCddbPatternWidget::K3bCddbPatternWidget( QWidget* parent, const char* name )
+ : base_K3bCddbPatternWidget( parent, name )
+{
+ // fix the layout
+ ((QGridLayout*)layout())->setRowStretch( 4, 1 );
+
+ // setup validators
+ // there can never be one of the following characters in both dir and filename:
+ // * ? "
+ // additional the filename can never contain a slash /
+ // and the dir should never start with a slash since it should always be a relative path
+
+ QRegExpValidator* dirValidator = new QRegExpValidator( QRegExp( "[^/][^?\\*\\\"]*" ), this );
+ m_comboFilenamePattern->setValidator( dirValidator );
+ m_comboPlaylistPattern->setValidator( dirValidator );
+ m_editBlankReplace->setValidator( dirValidator );
+
+ // default pattern
+ m_comboFilenamePattern->insertItem( i18n("%A - %T/%n - !a='%A'{%a - }%t") );
+ m_comboFilenamePattern->insertItem( i18n( "%{albumartist} - %{albumtitle}/%{number} - %{artist} - %{title}" ) );
+ m_comboFilenamePattern->insertItem( i18n( "%{genre}/%{albumartist} - %{albumtitle}/Track%{number}" ) );
+ m_comboFilenamePattern->insertItem( i18n( "music/ripped-tracks/%a - %t" ) );
+
+ m_comboPlaylistPattern->insertItem( i18n( "%{albumartist} - %{albumtitle}" ) );
+ m_comboPlaylistPattern->insertItem( i18n( "Playlist" ) );
+ m_comboPlaylistPattern->insertItem( i18n( "playlists/%{albumartist}/%{albumtitle }" ) );
+
+ connect( m_comboFilenamePattern, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(changed()) );
+ connect( m_comboPlaylistPattern, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(changed()) );
+ connect( m_editBlankReplace, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(changed()) );
+ connect( m_checkBlankReplace, SIGNAL(toggled(bool)),
+ this, SIGNAL(changed()) );
+ connect( m_specialStringsLabel, SIGNAL(leftClickedURL()),
+ this, SLOT(slotSeeSpecialStrings()) );
+ connect( m_conditionalInclusionLabel, SIGNAL(leftClickedURL()),
+ this, SLOT(slotSeeConditionalInclusion()) );
+}
+
+
+K3bCddbPatternWidget::~K3bCddbPatternWidget()
+{
+}
+
+
+QString K3bCddbPatternWidget::filenamePattern() const
+{
+ return m_comboFilenamePattern->currentText();
+}
+
+
+QString K3bCddbPatternWidget::playlistPattern() const
+{
+ return m_comboPlaylistPattern->currentText();
+}
+
+
+QString K3bCddbPatternWidget::blankReplaceString() const
+{
+ return m_editBlankReplace->text();
+}
+
+
+bool K3bCddbPatternWidget::replaceBlanks() const
+{
+ return m_checkBlankReplace->isChecked();
+}
+
+
+void K3bCddbPatternWidget::loadConfig( KConfigBase* c )
+{
+ m_comboPlaylistPattern->setEditText( c->readEntry( "playlist pattern", m_comboPlaylistPattern->text(0) ) );
+ m_comboFilenamePattern->setEditText( c->readEntry( "filename pattern", m_comboFilenamePattern->text(0) ) );
+ m_checkBlankReplace->setChecked( c->readBoolEntry( "replace blanks", false ) );
+ m_editBlankReplace->setText( c->readEntry( "blank replace string", "_" ) );
+}
+
+
+void K3bCddbPatternWidget::saveConfig( KConfigBase* c )
+{
+ c->writeEntry( "playlist pattern", m_comboPlaylistPattern->currentText() );
+ c->writeEntry( "filename pattern", m_comboFilenamePattern->currentText() );
+ c->writeEntry( "replace blanks", m_checkBlankReplace->isChecked() );
+ c->writeEntry( "blank replace string", m_editBlankReplace->text() );
+}
+
+
+void K3bCddbPatternWidget::loadDefaults()
+{
+ m_comboPlaylistPattern->setEditText( m_comboPlaylistPattern->text(0) );
+ m_comboFilenamePattern->setEditText( m_comboFilenamePattern->text(0) );
+ m_checkBlankReplace->setChecked( false );
+ m_editBlankReplace->setText( "_" );
+}
+
+
+void K3bCddbPatternWidget::slotSeeSpecialStrings()
+{
+ QWhatsThis::display( i18n( "<p><b>Pattern special strings:</b>"
+ "<p>The following strings will be replaced with their respective meaning in every "
+ "track name.<br>"
+ "<em>Hint:</em> %A differs from %a only on soundtracks or compilations."
+ "<p><table border=\"0\">"
+ "<tr><td></td><td><em>Meaning</em></td><td><em>Alternatives</em></td></tr>"
+ "<tr><td>%a</td><td>artist of the track</td><td>%{a} or %{artist}</td></tr>"
+ "<tr><td>%t</td><td>title of the track</td><td>%{t} or %{title}</td></tr>"
+ "<tr><td>%n</td><td>track number</td><td>%{n} or %{number}</td></tr>"
+ "<tr><td>%y</td><td>year of the CD</td><td>%{y} or %{year}</td></tr>"
+ "<tr><td>%c</td><td>extended track information</td><td>%{c} or %{comment}</td></tr>"
+ "<tr><td>%g</td><td>genre of the CD</td><td>%{g} or %{genre}</td></tr>"
+ "<tr><td>%A</td><td>album artist</td><td>%{A} or %{albumartist}</td></tr>"
+ "<tr><td>%T</td><td>album title</td><td>%{T} or %{albumtitle}</td></tr>"
+ "<tr><td>%C</td><td>extended CD information</td><td>%{C} or %{albumcomment}</td></tr>"
+ "<tr><td>%d</td><td>current date</td><td>%{d} or %{date}</td></tr>"
+ "</table>") );
+}
+
+void K3bCddbPatternWidget::slotSeeConditionalInclusion()
+{
+ QWhatsThis::display( i18n( "<p><b>Conditional inclusion:</b>"
+ "<p>These patterns make it possible to selectively include texts, "
+ "depending on the value of CDDB entries. You can choose only to "
+ "include or exclude texts if one of the entries is empty, "
+ "or if it has a specific value. Examples:"
+ "<ul>"
+ "<li>@T{TEXT} includes TEXT if the album title is specified"
+ "<li>!T{TEXT} includes TEXT if the album title is not specified"
+ "<li>@C=\'Soundtrack\'{TEXT} includes TEXT if the CD's extended "
+ "information is named Soundtrack"
+ "<li>!C=\'Soundtrack\'{TEXT} includes TEXT if the CD's extended "
+ "information is anything else but Soundtrack"
+ "<li>It is also possible to include special strings in texts and conditions, "
+ "e.g. !a='%A'{%a} only includes the title's artist information "
+ "if it does not differ from the album artist."
+ "</ul>"
+ "<p>Conditional includes make use of the same characters as the special "
+ "strings, which means that the X in @X{...} can be one character out of "
+ "[atnycgATCd]." ) );
+}
+
+#include "k3bcddbpatternwidget.moc"
+
diff --git a/src/rip/k3bcddbpatternwidget.h b/src/rip/k3bcddbpatternwidget.h
new file mode 100644
index 0000000..928b95b
--- /dev/null
+++ b/src/rip/k3bcddbpatternwidget.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * $Id: k3bcddbpatternwidget.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_CDDB_PATTERN_WIDGET_H_
+#define _K3B_CDDB_PATTERN_WIDGET_H_
+
+#include "base_k3bcddbpatternwidget.h"
+
+class KConfigBase;
+
+
+class K3bCddbPatternWidget : public base_K3bCddbPatternWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bCddbPatternWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bCddbPatternWidget();
+
+ QString filenamePattern() const;
+ QString playlistPattern() const;
+ QString blankReplaceString() const;
+ bool replaceBlanks() const;
+
+ signals:
+ void changed();
+
+ public slots:
+ void loadConfig( KConfigBase* );
+ void saveConfig( KConfigBase* );
+ void loadDefaults();
+
+ private slots:
+ void slotSeeSpecialStrings();
+ void slotSeeConditionalInclusion();
+};
+
+#endif
diff --git a/src/rip/k3bcuefilewriter.cpp b/src/rip/k3bcuefilewriter.cpp
new file mode 100644
index 0000000..087002d
--- /dev/null
+++ b/src/rip/k3bcuefilewriter.cpp
@@ -0,0 +1,91 @@
+/*
+ *
+ * $Id: k3bcuefilewriter.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bcuefilewriter.h"
+
+#include <k3btrack.h>
+#include <k3bmsf.h>
+#include <k3bcore.h>
+#include <k3bversion.h>
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qdatetime.h>
+
+
+K3bCueFileWriter::K3bCueFileWriter()
+{
+}
+
+
+bool K3bCueFileWriter::save( const QString& filename )
+{
+ QFile f( filename );
+
+ if( !f.open( IO_WriteOnly ) ) {
+ kdDebug() << "(K3bCueFileWriter) could not open file " << f.name() << endl;
+ return false;
+ }
+
+ QTextStream s( &f );
+
+ return save( s );
+}
+
+
+bool K3bCueFileWriter::save( QTextStream& t )
+{
+ t << "REM Cue file written by K3b " << k3bcore->version() << endl
+ << endl;
+
+ if( !m_cdText.isEmpty() ) {
+ t << "PERFORMER \"" << m_cdText.performer() << "\"" << endl;
+ t << "TITLE \"" << m_cdText.title() << "\"" << endl;
+ }
+
+ t << "FILE \"" << m_image << "\" " << m_dataType.upper() << endl;
+
+ // the tracks
+ unsigned int i = 0;
+ for( K3bDevice::Toc::const_iterator it = m_toc.begin();
+ it != m_toc.end(); ++it ) {
+
+ const K3bDevice::Track& track = *it;
+
+ t << " TRACK " << QString::number(i+1).rightJustify( 2, '0' ) << " AUDIO" << endl;
+
+ if( m_cdText.count() > i && !m_cdText[i].isEmpty() ) {
+ t << " PERFORMER \"" << m_cdText[i].performer() << "\"" << endl;
+ t << " TITLE \"" << m_cdText[i].title() << "\"" << endl;
+ }
+
+ //
+ // the pregap is part of the current track like in toc files
+ // and not part of the last track as on the CD
+ //
+ if( i > 0 ) {
+ --it;
+ if( (*it).index0() > 0 )
+ t << " INDEX 00 " << ((*it).firstSector() + (*it).index0()).toString() << endl;
+ ++it;
+ }
+ t << " INDEX 01 " << track.firstSector().toString() << endl;
+ // TODO: add additional indices
+
+ i++;
+ }
+
+ return ( t.device()->status() == IO_Ok );
+}
diff --git a/src/rip/k3bcuefilewriter.h b/src/rip/k3bcuefilewriter.h
new file mode 100644
index 0000000..88f7ffe
--- /dev/null
+++ b/src/rip/k3bcuefilewriter.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * $Id: k3bcuefilewriter.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_CUE_FILE_WRITER_H_
+#define _K3B_CUE_FILE_WRITER_H_
+
+#include <qtextstream.h>
+#include <qstringlist.h>
+
+#include <k3btoc.h>
+#include <k3bcdtext.h>
+
+namespace K3bDevice {
+ class TrackCdText;
+}
+
+/**
+ * Write a CDRWIN cue file.
+ * For now this writer only supports audio CDs
+ * for usage in the K3b audio CD ripper.
+ */
+
+class K3bCueFileWriter
+{
+ public:
+ K3bCueFileWriter();
+
+ bool save( QTextStream& );
+ bool save( const QString& filename );
+
+ void setData( const K3bDevice::Toc& toc ) { m_toc = toc; }
+ void setCdText( const K3bDevice::CdText& text ) { m_cdText = text; }
+ void setImage( const QString& name, const QString& type ) { m_image = name; m_dataType = type; }
+
+ private:
+ K3bDevice::Toc m_toc;
+ K3bDevice::CdText m_cdText;
+ QString m_image;
+ QString m_dataType;
+};
+
+#endif
diff --git a/src/rip/k3bpatternparser.cpp b/src/rip/k3bpatternparser.cpp
new file mode 100644
index 0000000..8ba04e6
--- /dev/null
+++ b/src/rip/k3bpatternparser.cpp
@@ -0,0 +1,305 @@
+/*
+ *
+ * $Id: k3bpatternparser.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ * Copyright (C) 2004-2005 Jakob Petsovits <jpetso@gmx.at>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#include "k3bpatternparser.h"
+
+#include <qregexp.h>
+#include <qdatetime.h>
+#include <qvaluestack.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+
+
+QString K3bPatternParser::parsePattern( const K3bCddbResultEntry& entry,
+ unsigned int trackNumber,
+ const QString& pattern,
+ bool replace,
+ const QString& replaceString )
+{
+ if( entry.titles.count() < trackNumber )
+ return "";
+
+ QString dir, s;
+ char c = ' '; // contains the character representation of a special string
+ unsigned int len; // length of the current special string
+
+
+ for( unsigned int i = 0; i < pattern.length(); ++i ) {
+
+ if( pattern[i] == '%' ) {
+
+ if( i + 1 < pattern.length() ) {
+ len = 2;
+
+ if( pattern[i+1] != '{' ) { // strings like %a
+ c = pattern[i+1];
+ }
+ else if( i + 3 >= pattern.length() ) { // too short to contain a %{*} string
+ c = ' ';
+ }
+ else { // long enough to contain %{*}
+
+ if( pattern[i+3] == '}' ) { // strings like %{a}
+ c = pattern[i+2];
+ len = 4;
+ }
+ else { // strings like %{artist}, or anything like %{*
+
+ while( i + len - 1 < pattern.length() ) {
+ ++len;
+
+ if( pattern[i + len - 1] == '%' ) { // don't touch other special strings
+ c = ' ';
+ --len;
+ break;
+ }
+ else if( pattern[i + len - 1] == '}' ) {
+ s = pattern.mid( i + 2, len - 3 );
+
+ if( s == "title" ) {
+ c = TITLE;
+ }
+ else if( s == "artist" ) {
+ c = ARTIST;
+ }
+ else if( s == "number" ) {
+ c = NUMBER;
+ }
+ else if( s == "comment" ) {
+ c = COMMENT;
+ }
+ else if( s == "year" ) {
+ c = YEAR;
+ }
+ else if( s == "genre" ) {
+ c = GENRE;
+ }
+ else if( s == "albumtitle" ) {
+ c = ALBUMTITLE;
+ }
+ else if( s == "albumartist" ) {
+ c = ALBUMARTIST;
+ }
+ else if( s == "albumcomment" ) {
+ c = ALBUMCOMMENT;
+ }
+ else if( s == "date" ) {
+ c = DATE;
+ }
+ else { // no valid pattern in here, don't replace anything
+ c = ' ';
+ }
+ break; // finished parsing %{* string
+ }
+ } // end of while(...)
+
+ } // end of %{* strings
+
+ } // end of if( long enough to contain %{*} )
+
+ switch( c ) {
+ case ARTIST:
+ s = entry.artists[trackNumber-1];
+ s.replace( '/', '_' );
+ s.replace( '*', '_' );
+ s.replace( '}', '*' ); // for conditional inclusion
+ dir.append( s.isEmpty()
+ ? i18n("unknown") + QString(" %1").arg(trackNumber)
+ : s );
+ break;
+ case TITLE:
+ s = entry.titles[trackNumber-1];
+ s.replace( '/', '_' );
+ s.replace( '*', '_' );
+ s.replace( '}', '*' );
+ dir.append( s.isEmpty()
+ ? i18n("Track %1").arg(trackNumber)
+ : s );
+ break;
+ case NUMBER:
+ dir.append( QString::number(trackNumber).rightJustify( 2, '0' ) );
+ break;
+ case YEAR:
+ dir.append( QString::number( entry.year ) );
+ break;
+ case COMMENT:
+ s = entry.extInfos[trackNumber-1];
+ s.replace( '/', '_' );
+ s.replace( '*', '_' );
+ s.replace( '}', '*' );
+ dir.append( s );
+ break;
+ case GENRE:
+ s = ( entry.genre.isEmpty() ? entry.category : entry.genre );
+ s.replace( '/', '_' );
+ s.replace( '*', '_' );
+ s.replace( '}', '*' );
+ dir.append( s );
+ break;
+ case ALBUMARTIST:
+ dir.append( entry.cdArtist.isEmpty()
+ ? i18n("unknown") : entry.cdArtist );
+ break;
+ case ALBUMTITLE:
+ s = entry.cdTitle;
+ s.replace( '/', '_' );
+ s.replace( '*', '_' );
+ s.replace( '}', '*' );
+ dir.append( s.isEmpty()
+ ? i18n("unknown") : s );
+ break;
+ case ALBUMCOMMENT:
+ s = entry.cdExtInfo;
+ s.replace( '/', '_' );
+ s.replace( '*', '_' );
+ s.replace( '}', '*' );
+ dir.append( s ); // I think it makes more sense to allow empty comments
+ break;
+ case DATE:
+ dir.append( KGlobal::locale()->formatDate( QDate::currentDate() ) );
+ break;
+ default:
+ dir.append( pattern.mid(i, len) );
+ break;
+ }
+ i += len - 1;
+ }
+ else { // end of pattern
+ dir.append( "%" );
+ }
+ }
+ else {
+ dir.append( pattern[i] );
+ }
+ }
+
+
+
+ // /* delete line comment to comment out
+ // the following part: Conditional Inclusion
+
+ QValueStack<int> offsetStack;
+ QString inclusion;
+ bool isIncluded;
+
+ static QRegExp conditionrx( "^[@|!][atyegrmx](?:='.*')?\\{" );
+ conditionrx.setMinimal( TRUE );
+
+ for( unsigned int i = 0; i < dir.length(); ++i ) {
+
+ offsetStack.push(
+ conditionrx.search(dir, i, QRegExp::CaretAtOffset) );
+
+ if( offsetStack.top() == -1 ) {
+ offsetStack.pop();
+ }
+ else {
+ i += conditionrx.matchedLength() - 1;
+ continue;
+ }
+
+ if( dir[i] == '}' && !offsetStack.isEmpty() ) {
+
+ int offset = offsetStack.pop();
+ int length = i - offset + 1;
+
+ switch( (QChar) dir[offset+1] ) {
+ case ARTIST:
+ s = entry.artists[trackNumber-1];
+ break;
+ case TITLE:
+ s = entry.titles[trackNumber-1];
+ break;
+ case NUMBER:
+ s = QString::number( trackNumber );
+ break;
+ case YEAR:
+ s = QString::number( entry.year );
+ break;
+ case COMMENT:
+ s = entry.extInfos[trackNumber-1];
+ break;
+ case GENRE:
+ s = ( entry.genre.isEmpty() ? entry.category : entry.genre );
+ break;
+ case ALBUMARTIST:
+ s = entry.cdArtist;
+ break;
+ case ALBUMTITLE:
+ s = entry.cdTitle;
+ break;
+ case ALBUMCOMMENT:
+ s = entry.cdExtInfo;
+ break;
+ case DATE:
+ s = KGlobal::locale()->formatDate( QDate::currentDate() );
+ break;
+ default: // we must never get here,
+ break; // all choices should be covered
+ }
+
+ if( dir[offset+2] == '{' ) { // no string matching, e.g. ?y{text}
+ switch( (QChar) dir[offset+1] ) {
+ case YEAR:
+ isIncluded = (s != "0");
+ break;
+ default:
+ isIncluded = !s.isEmpty();
+ break;
+ }
+ inclusion = dir.mid( offset + 3, length - 4 );
+ }
+ else { // with string matching, e.g. ?y='2004'{text}
+
+ // Be aware that there might be ' in the condition text
+ int endOfCondition = dir.find( '{', offset+4 )-1;
+ QString condition = dir.mid( offset+4,
+ endOfCondition - (offset+4) );
+
+ isIncluded = (s == condition);
+ inclusion = dir.mid( endOfCondition+2,
+ i - (endOfCondition+2) );
+ }
+
+ if( dir[offset] == '!' )
+ isIncluded = !isIncluded;
+ // Leave it when it's '@'.
+
+ dir.replace( offset, length, ( isIncluded ? inclusion : QString("") ) );
+
+ if( isIncluded == TRUE )
+ i -= length - inclusion.length();
+ else
+ i = offset - 1; // start next loop at offset
+
+ continue;
+
+ } // end of replace (at closing bracket '}')
+
+ } // end of conditional inclusion for(...)
+
+ // end of Conditional Inclusion */
+
+
+ dir.replace( '*', '}' ); // bring the brackets back, if there were any
+
+ if( replace )
+ dir.replace( QRegExp( "\\s" ), replaceString );
+
+ return dir;
+}
diff --git a/src/rip/k3bpatternparser.h b/src/rip/k3bpatternparser.h
new file mode 100644
index 0000000..88a725d
--- /dev/null
+++ b/src/rip/k3bpatternparser.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * $Id: k3bpatternparser.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef K3BPATTERNPARSER_H
+#define K3BPATTERNPARSER_H
+
+#include <qstring.h>
+
+#include <k3bcddbquery.h>
+
+
+/**
+ *@author Sebastian Trueg
+ */
+class K3bPatternParser
+{
+ public:
+ static QString parsePattern( const K3bCddbResultEntry& entry,
+ unsigned int trackNumber,
+ const QString& pattern,
+ bool replace = false,
+ const QString& replaceString = "_" );
+
+ private:
+ enum {
+ TITLE = 't',
+ ARTIST = 'a',
+ NUMBER = 'n',
+ COMMENT = 'c',
+ YEAR = 'y',
+ GENRE = 'g',
+ ALBUMTITLE = 'T',
+ ALBUMARTIST = 'A',
+ ALBUMCOMMENT = 'C',
+ DATE = 'd'
+ };
+};
+
+#endif
diff --git a/src/rip/k3bvideocdinfo.cpp b/src/rip/k3bvideocdinfo.cpp
new file mode 100644
index 0000000..ac30d40
--- /dev/null
+++ b/src/rip/k3bvideocdinfo.cpp
@@ -0,0 +1,247 @@
+/*
+*
+* $Id: k3bvideocdinfo.cpp 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+#include <qdom.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "k3bvideocdinfo.h"
+
+#include <k3bprocess.h>
+#include <k3bexternalbinmanager.h>
+
+
+K3bVideoCdInfo::K3bVideoCdInfo( QObject* parent, const char* name )
+ : QObject( parent, name )
+{
+ m_process = 0L;
+ m_isXml = false;
+}
+
+
+K3bVideoCdInfo::~K3bVideoCdInfo()
+{
+ delete m_process;
+}
+
+void K3bVideoCdInfo::cancelAll()
+{
+ if ( m_process->isRunning() ) {
+ m_process->disconnect( this );
+ m_process->kill();
+ }
+}
+
+void K3bVideoCdInfo::info( const QString& device )
+{
+ if ( !k3bcore ->externalBinManager() ->foundBin( "vcdxrip" ) ) {
+ kdDebug() << "(K3bVideoCdInfo::info) could not find vcdxrip executable" << endl;
+ emit infoFinished( false );
+ return ;
+ }
+
+ delete m_process;
+ m_process = new K3bProcess();
+
+ *m_process << k3bcore ->externalBinManager() ->binPath( "vcdxrip" );
+
+ *m_process << "-q" << "--norip" << "-i" << device << "-o" << "-";
+
+ connect( m_process, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ this, SLOT( slotParseOutput( KProcess*, char*, int ) ) );
+ connect( m_process, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ this, SLOT( slotParseOutput( KProcess*, char*, int ) ) );
+ connect( m_process, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( slotInfoFinished() ) );
+
+ if ( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) {
+ kdDebug() << "(K3bVideoCdInfo::info) could not start vcdxrip" << endl;
+ cancelAll();
+ emit infoFinished( false );
+ }
+}
+
+void K3bVideoCdInfo::slotParseOutput( KProcess*, char* output, int len )
+{
+ QString buffer = QString::fromLocal8Bit( output, len );
+
+ // split to lines
+ QStringList lines = QStringList::split( "\n", buffer );
+ QStringList::Iterator end( lines.end());
+ for ( QStringList::Iterator str = lines.begin(); str != end; ++str ) {
+
+ if ( ( *str ).contains( "<?xml" ) )
+ m_isXml = true;
+
+ if ( m_isXml )
+ m_xmlData += *str;
+ else
+ kdDebug() << "(K3bVideoCdInfo::slotParseOutput) " << *str << endl;
+
+ if ( ( *str ).contains( "</videocd>" ) )
+ m_isXml = false;
+ }
+}
+
+void K3bVideoCdInfo::slotInfoFinished()
+{
+ if ( m_process->normalExit() ) {
+ // TODO: check the process' exitStatus()
+ switch ( m_process->exitStatus() ) {
+ case 0:
+ break;
+ default:
+ cancelAll();
+ emit infoFinished( false );
+ return ;
+ }
+ } else {
+ cancelAll();
+ emit infoFinished( false );
+ return ;
+ }
+
+ if ( m_xmlData.isEmpty() ) {
+ emit infoFinished( false );
+ return ;
+ }
+
+ parseXmlData();
+ emit infoFinished( true );
+}
+
+void K3bVideoCdInfo::parseXmlData()
+{
+ QDomDocument xml_doc;
+ QDomElement xml_root;
+
+ m_Result.xmlData = m_xmlData;
+
+ xml_doc.setContent( m_xmlData );
+ xml_root = xml_doc.documentElement();
+
+ m_Result.type = xml_root.attribute( "class" );
+ m_Result.version = xml_root.attribute( "version" );
+
+ for ( QDomNode node = xml_root.firstChild(); !node.isNull(); node = node.nextSibling() ) {
+ QDomElement el = node.toElement();
+ QString tagName = el.tagName().lower();
+
+ if ( tagName == "pvd" ) {
+ for ( QDomNode snode = node.firstChild(); !snode.isNull(); snode = snode.nextSibling() ) {
+ QDomElement sel = snode.toElement();
+ QString pvdElement = sel.tagName().lower();
+ QString pvdElementText = sel.text();
+ if ( pvdElement == "volume-id" )
+ m_Result.volumeId = pvdElementText;
+ }
+
+ } else if ( tagName == "sequence-items" ) {
+ for ( QDomNode snode = node.firstChild(); !snode.isNull(); snode = snode.nextSibling() ) {
+ QDomElement sel = snode.toElement();
+ QString seqElement = sel.tagName().lower();
+ m_Result.addEntry( K3bVideoCdInfoResultEntry(
+ sel.attribute( "src" ),
+ sel.attribute( "id" ) ),
+ K3bVideoCdInfoResult::SEQUENCE
+ );
+ }
+ } else if ( tagName == "segment-items" ) {
+ for ( QDomNode snode = node.firstChild(); !snode.isNull(); snode = snode.nextSibling() ) {
+ QDomElement sel = snode.toElement();
+ QString seqElement = sel.tagName().lower();
+ m_Result.addEntry( K3bVideoCdInfoResultEntry(
+ sel.attribute( "src" ),
+ sel.attribute( "id" ) ),
+ K3bVideoCdInfoResult::SEGMENT
+ );
+ }
+ } else {
+ kdDebug() << QString( "(K3bVideoCdInfo::parseXmlData) tagName '%1' not used" ).arg( tagName ) << endl;
+ }
+ }
+}
+
+const K3bVideoCdInfoResult& K3bVideoCdInfo::result() const
+{
+ return m_Result;
+}
+
+const K3bVideoCdInfoResultEntry& K3bVideoCdInfoResult::entry( unsigned int number, int type ) const
+{
+ switch ( type ) {
+ case K3bVideoCdInfoResult::FILE:
+ if ( number >= m_fileEntry.count() )
+ return m_emptyEntry;
+ return m_fileEntry[ number ];
+ case K3bVideoCdInfoResult::SEGMENT:
+ if ( number >= m_segmentEntry.count() )
+ return m_emptyEntry;
+ return m_segmentEntry[ number ];
+ case K3bVideoCdInfoResult::SEQUENCE:
+ if ( number >= m_sequenceEntry.count() )
+ return m_emptyEntry;
+ return m_sequenceEntry[ number ];
+ default:
+ kdDebug() << "(K3bVideoCdInfoResult::entry) not supported entrytype." << endl;
+ }
+
+ return m_emptyEntry;
+
+}
+
+
+void K3bVideoCdInfoResult::addEntry( const K3bVideoCdInfoResultEntry& entry, int type )
+{
+ switch ( type ) {
+ case K3bVideoCdInfoResult::FILE:
+ m_fileEntry.append( entry );
+ break;
+ case K3bVideoCdInfoResult::SEGMENT:
+ m_segmentEntry.append( entry );
+ break;
+ case K3bVideoCdInfoResult::SEQUENCE:
+ m_sequenceEntry.append( entry );
+ break;
+ default:
+ kdDebug() << "(K3bVideoCdInfoResult::addEntry) not supported entrytype." << endl;
+ }
+}
+
+int K3bVideoCdInfoResult::foundEntries( int type ) const
+{
+ switch ( type ) {
+ case K3bVideoCdInfoResult::FILE:
+ return m_fileEntry.count();
+ case K3bVideoCdInfoResult::SEGMENT:
+ return m_segmentEntry.count();
+ case K3bVideoCdInfoResult::SEQUENCE:
+ return m_sequenceEntry.count();
+ default:
+ kdDebug() << "(K3bVideoCdInfoResult::addEntry) not supported entrytype." << endl;
+ }
+ return 0;
+}
+
+#include "k3bvideocdinfo.moc"
+
diff --git a/src/rip/k3bvideocdinfo.h b/src/rip/k3bvideocdinfo.h
new file mode 100644
index 0000000..0b295e6
--- /dev/null
+++ b/src/rip/k3bvideocdinfo.h
@@ -0,0 +1,107 @@
+/*
+*
+* $Id: k3bvideocdinfo.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+
+#ifndef K3BVIDEOCDINFO_H
+#define K3BVIDEOCDINFO_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qobject.h>
+
+#include <k3btoc.h>
+#include <k3bcore.h>
+
+class KProcess;
+
+class K3bVideoCdInfoResultEntry
+{
+ public:
+ K3bVideoCdInfoResultEntry() : name( 0 ), id( 0 )
+ {}
+
+ K3bVideoCdInfoResultEntry( const QString& name, const QString& id )
+ : name( name ), id( id )
+ {}
+
+ QString name;
+ QString id;
+
+ long size;
+};
+
+class K3bVideoCdInfoResult
+{
+ public:
+ K3bVideoCdInfoResult()
+ {}
+
+ enum type {NONE = 0, FILE, SEGMENT, SEQUENCE};
+
+ void addEntry( const K3bVideoCdInfoResultEntry& = K3bVideoCdInfoResultEntry(), int type = K3bVideoCdInfoResult::SEQUENCE );
+ const K3bVideoCdInfoResultEntry& entry( unsigned int number = 0 , int type = K3bVideoCdInfoResult::SEQUENCE ) const;
+ int foundEntries( int type = K3bVideoCdInfoResult::SEQUENCE ) const;
+
+ QString volumeId;
+ QString type;
+ QString version;
+
+ QString xmlData;
+
+ private:
+ QValueList<K3bVideoCdInfoResultEntry> m_fileEntry;
+ QValueList<K3bVideoCdInfoResultEntry> m_segmentEntry;
+ QValueList<K3bVideoCdInfoResultEntry> m_sequenceEntry;
+
+ K3bVideoCdInfoResultEntry m_emptyEntry;
+};
+
+class K3bVideoCdInfo : public QObject
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoCdInfo( QObject* parent = 0, const char* name = 0 );
+ ~K3bVideoCdInfo();
+
+ /**
+ * Do NOT call this before queryResult has
+ * been emitted
+ */
+ const K3bVideoCdInfoResult& result() const;
+
+ void info( const QString& );
+
+ signals:
+ void infoFinished( bool success );
+
+ private slots:
+ void slotInfoFinished();
+ void slotParseOutput( KProcess*, char* output, int len );
+
+ private:
+ void cancelAll();
+
+ K3bVideoCdInfoResult m_Result;
+ void parseXmlData();
+
+ KProcess* m_process;
+
+ QString m_xmlData;
+ bool m_isXml;
+
+};
+
+#endif
diff --git a/src/rip/k3bvideocdrip.cpp b/src/rip/k3bvideocdrip.cpp
new file mode 100644
index 0000000..a7467c9
--- /dev/null
+++ b/src/rip/k3bvideocdrip.cpp
@@ -0,0 +1,355 @@
+/*
+*
+* $Id: k3bvideocdrip.cpp 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kio/global.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kurl.h>
+
+#include <qdatetime.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qurl.h>
+
+// K3b Includes
+#include "k3bvideocdrip.h"
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bglobals.h>
+#include <k3bprocess.h>
+
+K3bVideoCdRip::K3bVideoCdRip( K3bJobHandler* hdl, K3bVideoCdRippingOptions* options, QObject* parent, const char* name )
+ : K3bJob( hdl, parent, name ),
+ m_ripsourceType( 0 ),
+ m_subPosition ( 0 ),
+ m_videooptions( options ),
+ m_canceled( false ),
+ m_process( 0 )
+{}
+
+
+K3bVideoCdRip::~K3bVideoCdRip()
+{
+ if ( m_process )
+ delete m_process;
+
+}
+
+
+void K3bVideoCdRip::cancel()
+{
+ cancelAll();
+
+ emit infoMessage( i18n( "Job canceled by user." ), K3bJob::ERROR );
+ emit canceled();
+ jobFinished( false );
+}
+
+
+void K3bVideoCdRip::cancelAll()
+{
+ m_canceled = true;
+
+ if ( m_process->isRunning() ) {
+ m_process->disconnect( this );
+ m_process->kill();
+ }
+}
+
+
+void K3bVideoCdRip::start()
+{
+ kdDebug() << "(K3bVideoCdRip) starting job" << endl;
+
+ jobStarted();
+ m_canceled = false;
+
+ vcdxRip();
+}
+
+void K3bVideoCdRip::vcdxRip()
+{
+ emit newTask( i18n( "Check files" ) );
+
+ m_stage = stageUnknown;
+ delete m_process;
+ m_process = new K3bProcess();
+
+ const K3bExternalBin* bin = k3bcore ->externalBinManager() ->binObject( "vcdxrip" );
+
+ if ( !bin ) {
+ kdDebug() << "(K3bVideoCdRip) could not find vcdxrip executable" << endl;
+ emit infoMessage( i18n( "Could not find %1 executable." ).arg( "vcdxrip" ), K3bJob::ERROR );
+ emit infoMessage( i18n( "To rip VideoCD's you must install VcdImager Version %1." ).arg( ">= 0.7.12" ), K3bJob::INFO );
+ emit infoMessage( i18n( "You can find this on your distribution disks or download it from http://www.vcdimager.org" ), K3bJob::INFO );
+ cancelAll();
+ jobFinished( false );
+ return ;
+ }
+
+ if( bin->version < K3bVersion("0.7.12") ) {
+ kdDebug() << "(K3bVideoCdRip) vcdxrip executable too old!" << endl;
+ emit infoMessage( i18n( "%1 executable too old! Need version %2 or greater" ).arg( "Vcdxrip" ).arg( "0.7.12" ), K3bJob::ERROR );
+ emit infoMessage( i18n( "You can find this on your distribution disks or download it from http://www.vcdimager.org" ), K3bJob::INFO );
+ cancelAll();
+ jobFinished( false );
+ return ;
+ }
+
+ if ( !bin->copyright.isEmpty() )
+ emit infoMessage( i18n( "Using %1 %2 - Copyright (C) %3" ).arg( bin->name() ).arg( bin->version ).arg( bin->copyright ), INFO );
+
+
+ *m_process << k3bcore ->externalBinManager() ->binPath( "vcdxrip" );
+
+ // additional user parameters from config
+ const QStringList& params = k3bcore->externalBinManager() ->program( "vcdxrip" ) ->userParameters();
+ for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it )
+ *m_process << *it;
+
+ *m_process << "--gui" << "--progress";
+
+ if ( !m_videooptions ->getVideoCdRipFiles() )
+ *m_process << "--nofiles";
+
+ if ( !m_videooptions ->getVideoCdRipSegments() )
+ *m_process << "--nosegments";
+
+ if ( !m_videooptions ->getVideoCdRipSequences() )
+ *m_process << "--nosequences";
+
+ if ( m_videooptions ->getVideoCdIgnoreExt() )
+ *m_process << "--no-ext-psd";
+
+ if ( m_videooptions ->getVideoCdSector2336() )
+ *m_process << "--sector-2336";
+
+ *m_process << "-i" << QString( "%1" ).arg( QFile::encodeName( m_videooptions ->getVideoCdSource() ) );
+
+ if ( m_videooptions ->getVideoCdExtractXml() )
+ *m_process << "-o" << QString( "%1" ).arg( QFile::encodeName( m_videooptions ->getVideoCdDescription() + ".xml" ) );
+ else
+ *m_process << "-o" << "/dev/null";
+
+
+ connect( m_process, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ this, SLOT( slotParseVcdXRipOutput( KProcess*, char*, int ) ) );
+ connect( m_process, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ this, SLOT( slotParseVcdXRipOutput( KProcess*, char*, int ) ) );
+ connect( m_process, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( slotVcdXRipFinished() ) );
+
+ m_process->setWorkingDirectory( QUrl( m_videooptions ->getVideoCdDestination() ).dirPath() );
+
+ // vcdxrip commandline parameters
+ kdDebug() << "***** vcdxrip parameters:" << endl;
+ ;
+ const QValueList<QCString>& args = m_process->args();
+ QString s;
+ for ( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) {
+ s += *it + " ";
+ }
+ kdDebug() << s << flush << endl;
+ emit debuggingOutput( "vcdxrip command:", s );
+
+ emit newTask( i18n( "Extracting" ) );
+ emit infoMessage( i18n( "Start extracting." ), K3bJob::INFO );
+ emit infoMessage( i18n( "Extract files from %1 to %2." ).arg( m_videooptions ->getVideoCdSource() ).arg( m_videooptions ->getVideoCdDestination() ), K3bJob::INFO );
+
+ if ( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) {
+ kdDebug() << "(K3bVideoCdRip) could not start vcdxrip" << endl;
+ emit infoMessage( i18n( "Could not start %1." ).arg( "vcdxrip" ), K3bJob::ERROR );
+ cancelAll();
+ jobFinished( false );
+ }
+}
+
+void K3bVideoCdRip::slotParseVcdXRipOutput( KProcess*, char* output, int len )
+{
+ QString buffer = QString::fromLocal8Bit( output, len );
+
+ // split to lines
+ QStringList lines = QStringList::split( "\n", buffer );
+
+ QDomDocument xml_doc;
+ QDomElement xml_root;
+
+ // do every line
+ QStringList::Iterator end( lines.end());
+ for ( QStringList::Iterator str = lines.begin(); str != end; ++str ) {
+ *str = ( *str ).stripWhiteSpace();
+
+ emit debuggingOutput( "vcdxrip", *str );
+
+ xml_doc.setContent( QString( "<?xml version='1.0'?><vcdxrip>" ) + *str + "</vcdxrip>" );
+
+ xml_root = xml_doc.documentElement();
+
+ for ( QDomNode node = xml_root.firstChild(); !node.isNull(); node = node.nextSibling() ) {
+ QDomElement el = node.toElement();
+ if ( el.isNull() )
+ continue;
+
+ const QString tagName = el.tagName().lower();
+
+ if ( tagName == "progress" ) {
+ const QString oper = el.attribute( "operation" ).lower();
+ const unsigned long long overallPos = el.attribute( "position" ).toLong();
+ const unsigned long long pos = overallPos - m_subPosition;
+ const unsigned long long size = el.attribute( "size" ).toLong() - m_subPosition;
+
+ if ( oper == "extract" ) {
+ emit subPercent( ( int ) ( 100.0 * ( double ) pos / ( double ) size ) );
+ emit processedSubSize( ( pos * 2352 ) / 1024 / 1024 , ( size * 2352 ) / 1024 / 1024 );
+
+ m_bytesFinished = pos;
+
+ kdDebug() << "(slotParseVcdXRipOutput) overall: " << ((long)overallPos * 2352)
+ << ", videocdsize: " << m_videooptions->getVideoCdSize() << endl;
+ double relOverallWritten = ( ( double ) overallPos * 2352 ) / ( double ) m_videooptions ->getVideoCdSize() ;
+ int newpercent = ( int ) ( 100 * relOverallWritten );
+ if ( newpercent > m_oldpercent ) {
+ emit percent( newpercent );
+ m_oldpercent = newpercent;
+ }
+
+ } else {
+ return ;
+ }
+
+ } else if ( tagName == "log" ) {
+ QDomText tel = el.firstChild().toText();
+ const QString level = el.attribute( "level" ).lower();
+ if ( tel.isText() ) {
+ const QString text = tel.data();
+ if ( level == "information" ) {
+ kdDebug() << QString( "(K3bVideoCdRip) vcdxrip information, %1" ).arg( text ) << endl;
+ parseInformation( text );
+ } else {
+ if ( level != "error" ) {
+ kdDebug() << QString( "(K3bVideoCdRip) vcdxrip warning, %1" ).arg( text ) << endl;
+ emit debuggingOutput( "vcdxrip", text );
+ parseInformation( text );
+ } else {
+ kdDebug() << QString( "(K3bVideoCdRip) vcdxrip error, %1" ).arg( text ) << endl;
+ emit infoMessage( text, K3bJob::ERROR );
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void K3bVideoCdRip::slotVcdXRipFinished()
+{
+ if ( m_process->normalExit() ) {
+ // TODO: check the process' exitStatus()
+ switch ( m_process->exitStatus() ) {
+ case 0:
+ emit infoMessage( i18n( "Files successfully extracted." ), K3bJob::SUCCESS );
+ break;
+ default:
+ emit infoMessage( i18n( "%1 returned an unknown error (code %2)." ).arg( "vcdxrip" ).arg( m_process->exitStatus() ), K3bJob::ERROR );
+ emit infoMessage( i18n( "Please send me an email with the last output..." ), K3bJob::ERROR );
+ cancelAll();
+ jobFinished( false );
+ return ;
+ }
+ } else {
+ emit infoMessage( i18n( "%1 did not exit cleanly." ).arg( "Vcdxrip" ), K3bJob::ERROR );
+ cancelAll();
+ jobFinished( false );
+ return ;
+ }
+
+ jobFinished( true );
+}
+
+void K3bVideoCdRip::parseInformation( QString text )
+{
+ // parse warning
+ if ( text.contains( "encountered non-form2 sector" ) ) {
+ // I think this is an error not a warning. Finish ripping with invalid mpegs.
+ emit infoMessage( i18n( "%1 encountered non-form2 sector" ).arg("Vcdxrip"), K3bJob::ERROR );
+ emit infoMessage( i18n( "leaving loop" ), K3bJob::ERROR );
+ cancelAll();
+ jobFinished( false );
+ return;
+ }
+
+ // parse extra info
+ else if ( text.contains( "detected extended VCD2.0 PBC files" ) )
+ emit infoMessage( i18n( "detected extended VCD2.0 PBC files" ), K3bJob::INFO );
+
+ // parse startposition and extracting sequence info
+ // extracting avseq05.mpg... (start lsn 32603 (+28514))
+ else if ( text.startsWith( "extracting" ) ) {
+ if ( text.contains( "(start lsn" ) ) {
+ int index = text.find( "(start lsn" );
+ int end = text.find( " (+" );
+ if ( end > 0) {
+ m_subPosition = text.mid( index + 11, end - index - 11 ).stripWhiteSpace().toLong();
+ }
+ else {
+ // found segment here we can get only the start lsn :)
+ // extracting item0001.mpg... (start lsn 225, 1 segments)
+ int end = text.find( ",", index );
+ int overallPos = text.mid( index + 11, end - index - 11 ).stripWhiteSpace().toLong();
+ double relOverallWritten = ( ( double ) overallPos * 2352 ) / ( double ) m_videooptions ->getVideoCdSize() ;
+ int newpercent = ( int ) ( 100 * relOverallWritten );
+ if ( newpercent > m_oldpercent ) {
+ emit percent( newpercent );
+ m_oldpercent = newpercent;
+ }
+ }
+
+
+ index = 11;
+ end = text.find( "(start lsn" );
+ emit newSubTask( i18n( "Extracting %1" ).arg( text.mid( index, end - index ).stripWhiteSpace() ) );
+ }
+ // parse extracting files info
+ // extracting CDI/CDI_IMAG.RTF to _cdi_cdi_imag.rtf (lsn 258, size 1315168, raw 1)
+ else if ( text.contains( "(lsn" ) && text.contains( "size" ) ) {
+ int index = 11;
+ int end = text.find( "to" );
+ QString extractFileName = text.mid( index, end - index ).stripWhiteSpace();
+ index = text.find( " to " );
+ end = text.find( " (lsn" );
+ QString toFileName = text.mid( index + 4, end - index - 4 ).stripWhiteSpace();
+ emit newSubTask( i18n( "Extracting %1 to %2" ).arg( extractFileName ).arg( toFileName ) );
+ }
+ }
+}
+
+QString K3bVideoCdRip::jobDescription() const
+{
+ return i18n( "Extracting %1" ).arg( m_videooptions ->getVideoCdDescription() );
+}
+
+QString K3bVideoCdRip::jobDetails() const
+{
+ return QString( "(%1)" ).arg ( KIO::convertSize( m_videooptions ->getVideoCdSize() ) );
+}
+
+#include "k3bvideocdrip.moc"
diff --git a/src/rip/k3bvideocdrip.h b/src/rip/k3bvideocdrip.h
new file mode 100644
index 0000000..fe0d6f9
--- /dev/null
+++ b/src/rip/k3bvideocdrip.h
@@ -0,0 +1,74 @@
+/*
+*
+* $Id: k3bvideocdrip.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+#ifndef K3BVIDEOCDRIP_H
+#define K3BVIDEOCDRIP_H
+
+#include <k3bjob.h>
+#include <k3bdiskinfo.h>
+#include "k3bvideocdrippingoptions.h"
+
+class QString;
+class KProcess;
+class QDataStream;
+
+class K3bVideoCdRip : public K3bJob
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoCdRip( K3bJobHandler*, K3bVideoCdRippingOptions* options, QObject* parent = 0, const char* name = 0 );
+ ~K3bVideoCdRip();
+
+ enum { CDROM, BIN_IMAGE, NRG_IMAGE };
+
+ QString jobDescription() const;
+ QString jobDetails() const;
+
+ public slots:
+ void start();
+ void cancel();
+
+ private slots:
+ void cancelAll();
+
+ protected slots:
+ void slotVcdXRipFinished();
+ void slotParseVcdXRipOutput( KProcess*, char* output, int len );
+
+ private:
+ void vcdxRip();
+ void parseInformation( QString );
+
+ enum { stageUnknown, stageScan, stageFinished, _stage_max };
+
+ int m_stage;
+ int m_bytesFinished;
+ int m_ripsourceType;
+ int m_oldpercent;
+
+ long m_subPosition;
+
+ QString m_collectedOutput;
+
+ K3bVideoCdRippingOptions * m_videooptions;
+
+ bool m_canceled;
+
+ KProcess* m_process;
+
+};
+
+#endif
diff --git a/src/rip/k3bvideocdrippingdialog.cpp b/src/rip/k3bvideocdrippingdialog.cpp
new file mode 100644
index 0000000..490f531
--- /dev/null
+++ b/src/rip/k3bvideocdrippingdialog.cpp
@@ -0,0 +1,260 @@
+/*
+*
+* $Id: k3bvideocdrippingdialog.cpp 640370 2007-03-07 19:44:32Z trueg $
+* Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+
+// kde include
+#include <klocale.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kurlrequester.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+
+// qt includes
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qstringlist.h>
+#include <qhbox.h>
+
+// k3b includes
+#include "k3bvideocdrippingdialog.h"
+#include "k3bvideocdrip.h"
+
+#include <k3bjobprogressdialog.h>
+#include <k3bcore.h>
+#include <k3bglobals.h>
+#include <k3bstdguiitems.h>
+
+K3bVideoCdRippingDialog::K3bVideoCdRippingDialog( K3bVideoCdRippingOptions* options, QWidget* parent, const char* name )
+ : K3bInteractionDialog( parent, name,
+ i18n( "Video CD Ripping" ),
+ QString::null,
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "Video CD Ripping" ), // config group
+ m_videooptions( options )
+{
+ setupGui();
+ setupContextHelp();
+}
+
+
+K3bVideoCdRippingDialog::~K3bVideoCdRippingDialog()
+{
+}
+
+
+void K3bVideoCdRippingDialog::setupGui()
+{
+ QWidget * frame = mainWidget();
+ QGridLayout* MainLayout = new QGridLayout( frame );
+ MainLayout->setSpacing( KDialog::spacingHint() );
+ MainLayout->setMargin( 0 );
+
+ // ---------------------------------------------------- Directory group ---
+ QGroupBox* groupDirectory = new QGroupBox( 0, Qt::Vertical, i18n( "Destination Directory" ), frame );
+ groupDirectory->layout() ->setSpacing( KDialog::spacingHint() );
+ groupDirectory->layout() ->setMargin( KDialog::marginHint() );
+
+ QGridLayout* groupDirectoryLayout = new QGridLayout( groupDirectory->layout() );
+ groupDirectoryLayout->setAlignment( Qt::AlignTop );
+
+ QLabel* rippathLabel = new QLabel( i18n( "Rip files to:" ), groupDirectory );
+ m_editDirectory = new KURLRequester( groupDirectory, "m_editDirectory" );
+ m_editDirectory->setURL( QDir::homeDirPath() );
+ m_editDirectory->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+
+ rippathLabel->setBuddy( m_editDirectory );
+
+ QHBox* freeSpaceBox = new QHBox( groupDirectory );
+ freeSpaceBox->setSpacing( KDialog::spacingHint() );
+ ( void ) new QLabel( i18n( "Free space in directory:" ), freeSpaceBox, "FreeSpaceLabel" );
+ m_labelFreeSpace = new QLabel( " ", freeSpaceBox, "m_labelFreeSpace" );
+ m_labelFreeSpace->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+ QHBox* necessarySizeBox = new QHBox( groupDirectory );
+ necessarySizeBox->setSpacing( KDialog::spacingHint() );
+ ( void ) new QLabel( i18n( "Necessary storage size:" ), necessarySizeBox, "StorSize" );
+ m_labelNecessarySize = new QLabel( " ", necessarySizeBox, "m_labelNecessarySize" );
+ m_labelNecessarySize->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+
+ groupDirectoryLayout->addWidget( rippathLabel, 0, 0 );
+ groupDirectoryLayout->addWidget( m_editDirectory, 0, 1 );
+ groupDirectoryLayout->addWidget( freeSpaceBox, 1, 1 );
+ groupDirectoryLayout->addWidget( necessarySizeBox, 2, 1 );
+
+ // ---------------------------------------------------- Options group ---
+ QGroupBox* groupOptions = new QGroupBox( 4, Qt::Vertical, i18n( "Settings" ), frame );
+
+ m_ignoreExt = new QCheckBox( i18n( "Ignore /EXT/PSD_X.VCD" ), groupOptions );
+
+ m_sector2336 = new QCheckBox( i18n( "Use 2336 byte sector mode for image file" ), groupOptions );
+ // Only available for image file ripping
+ m_sector2336->setEnabled( false );
+ m_sector2336->setChecked( false );
+
+ m_extractXML = new QCheckBox( i18n( "Extract XML structure" ), groupOptions );
+
+
+ MainLayout->addWidget( groupDirectory, 0, 0 );
+ MainLayout->addWidget( groupOptions, 1, 0 );
+ MainLayout->setRowStretch( 0, 1 );
+
+ setStartButtonText( i18n( "Start Ripping" ), i18n( "Starts extracting the selected VideoCd tracks" ) );
+ // ----------------------------------------------------------------------------------
+
+ connect( m_editDirectory, SIGNAL(textChanged(const QString&)), this, SLOT(slotUpdateFreeSpace()) );
+
+ m_labelNecessarySize ->setText( KIO::convertSize( m_videooptions ->getVideoCdSize() ) );
+}
+
+
+void K3bVideoCdRippingDialog::setupContextHelp()
+{
+ QToolTip::add( m_labelFreeSpace, i18n("Free space on destination directory: %1").arg( m_editDirectory ->url() ) );
+
+ QToolTip::add( m_labelNecessarySize, i18n("Necessary space for extracted files") );
+
+ QToolTip::add( m_ignoreExt, i18n("Ignore extended PSD") );
+ QWhatsThis::add( m_ignoreExt, i18n("<p>Ignore extended PSD (located in the ISO-9660 filesystem under `/EXT/PSD_X.VCD') and use the <em>standard</em> PSD.</p>") );
+
+ QToolTip::add( m_sector2336, i18n("Assume a 2336-byte sector mode") );
+ QWhatsThis::add( m_sector2336, i18n("<p>This option only makes sense if you are reading from a BIN CD disk image. This indicates to `vcdxrip' to assume a 2336-byte sector mode for image file.</p>"
+ "<b>Note: This option is slated to disappear.</b>") );
+
+ QToolTip::add( m_extractXML, i18n("Create XML description file.") );
+ QWhatsThis::add( m_extractXML, i18n("<p>This option creates an XML description file with all video CD information.</p>"
+ "<p>This file will always contain all of the information.</p>"
+ "<p>Example: If you only extract sequences, the description file will also hold the information for files and segments.</p>"
+ "<p>The filename is the same as the video CD name, with a .xml extension. The default is VIDEOCD.xml.</p>") );
+}
+
+void K3bVideoCdRippingDialog::slotStartClicked()
+{
+
+ QStringList filesExists;
+ QDir d;
+ d.setPath( m_editDirectory ->url() );
+ if( !d.exists() ) {
+ if( KMessageBox::warningYesNo( this, i18n("Image folder '%1' does not exist. Do you want K3b to create it?").arg( m_editDirectory->url() ) )
+ == KMessageBox::Yes ) {
+ if( !KStandardDirs::makeDir( m_editDirectory->url() ) ) {
+ KMessageBox::error( this, i18n("Failed to create folder '%1'.").arg( m_editDirectory->url() ) );
+ return;
+ }
+ }
+ }
+ const QFileInfoList* list = d.entryInfoList();
+ QFileInfoListIterator it( *list );
+ QFileInfo* fi;
+ while ( ( fi = it.current() ) != 0 ) {
+ if ( fi ->fileName() != "." && fi ->fileName() != ".." )
+ filesExists.append( QString( "%1 (%2)" ).arg( QFile::encodeName( fi ->fileName() ) ).arg( KIO::convertSize( fi ->size() ) ) );
+ ++it;
+ }
+
+ if( !filesExists.isEmpty() )
+ if( KMessageBox::questionYesNoList( this,
+ i18n("Continue although the folder is not empty?"),
+ filesExists,
+ i18n("Files Exist"),KStdGuiItem::cont(),KStdGuiItem::cancel() ) == KMessageBox::No )
+ return;
+
+ m_videooptions ->setVideoCdIgnoreExt( m_ignoreExt ->isChecked() );
+ m_videooptions ->setVideoCdSector2336( m_sector2336 ->isChecked() );
+ m_videooptions ->setVideoCdExtractXml( m_extractXML ->isChecked() );
+ m_videooptions ->setVideoCdDestination( m_editDirectory ->url() );
+
+ K3bJobProgressDialog ripDialog( kapp->mainWidget(), "Ripping" );
+ K3bVideoCdRip * rip = new K3bVideoCdRip( &ripDialog, m_videooptions );
+
+ hide();
+ ripDialog.startJob( rip );
+
+ delete rip;
+
+ close();
+}
+
+void K3bVideoCdRippingDialog::slotFreeSpace(const QString&,
+ unsigned long,
+ unsigned long,
+ unsigned long kbAvail)
+{
+ m_labelFreeSpace->setText( KIO::convertSizeFromKB(kbAvail) );
+
+ m_freeSpace = kbAvail;
+
+ if( m_freeSpace < m_videooptions ->getVideoCdSize() /1024 )
+ m_labelNecessarySize->setPaletteForegroundColor( red );
+ else
+ m_labelNecessarySize->setPaletteForegroundColor( m_labelFreeSpace->paletteForegroundColor() );
+
+ QTimer::singleShot( 1000, this, SLOT(slotUpdateFreeSpace()) );
+}
+
+
+void K3bVideoCdRippingDialog::slotUpdateFreeSpace()
+{
+ QString path = m_editDirectory->url();
+
+ if( !QFile::exists( path ) )
+ path.truncate( path.findRev('/') );
+
+ unsigned long size, avail;
+ if( K3b::kbFreeOnFs( path, size, avail ) )
+ slotFreeSpace( path, size, 0, avail );
+ else
+ m_labelFreeSpace->setText("-");
+}
+
+void K3bVideoCdRippingDialog::loadK3bDefaults()
+{
+ m_editDirectory->setURL( QDir::homeDirPath() );
+ m_ignoreExt ->setChecked( false );
+ m_sector2336 ->setChecked( false );
+ m_extractXML ->setChecked( false );
+
+ slotUpdateFreeSpace();
+}
+
+void K3bVideoCdRippingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_editDirectory ->setURL( c->readPathEntry( "last ripping directory", QDir::homeDirPath() ) );
+ m_ignoreExt ->setChecked( c->readBoolEntry( "ignore ext", false ) );
+ m_sector2336 ->setChecked( c->readBoolEntry( "sector 2336", false ) );
+ m_extractXML ->setChecked( c->readBoolEntry( "extract xml", false ) );
+
+ slotUpdateFreeSpace();
+}
+
+void K3bVideoCdRippingDialog::saveUserDefaults( KConfigBase* c )
+{
+ c->writePathEntry( "last ripping directory", m_editDirectory->url() );
+ c->writeEntry( "ignore ext", m_ignoreExt ->isChecked( ) );
+ c->writeEntry( "sector 2336", m_sector2336 ->isChecked( ) );
+ c->writeEntry( "extract xml", m_extractXML ->isChecked( ) );
+}
+
+#include "k3bvideocdrippingdialog.moc"
diff --git a/src/rip/k3bvideocdrippingdialog.h b/src/rip/k3bvideocdrippingdialog.h
new file mode 100644
index 0000000..98d16f6
--- /dev/null
+++ b/src/rip/k3bvideocdrippingdialog.h
@@ -0,0 +1,73 @@
+/*
+ *
+ * $Id: k3bvideocdrippingdialog.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+
+#ifndef _K3B_VIDEOCD_RIPPING_DIALOG_H_
+#define _K3B_VIDEOCD_RIPPING_DIALOG_H_
+
+#include <qstringlist.h>
+
+#include <k3binteractiondialog.h>
+#include <k3bdiskinfo.h>
+#include "k3bvideocdrippingoptions.h"
+
+class KListView;
+class QCheckBox;
+class QLabel;
+class QSpinBox;
+class QComboBox;
+class QToolButton;
+class KURLRequester;
+class K3bTempDirSelectionWidget;
+
+class K3bVideoCdRippingDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoCdRippingDialog( K3bVideoCdRippingOptions* options, QWidget* parent = 0, const char* name = 0 );
+ ~K3bVideoCdRippingDialog();
+
+ private:
+ void setupGui();
+ void setupContextHelp();
+
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+
+ K3bTempDirSelectionWidget* m_tempDirSelectionWidget;
+
+ KURLRequester* m_editDirectory;
+
+ QLabel* m_labelFreeSpace;
+ QLabel* m_labelNecessarySize;
+ QCheckBox* m_ignoreExt;
+ QCheckBox* m_sector2336;
+ QCheckBox* m_extractXML;
+
+ K3bVideoCdRippingOptions* m_videooptions;
+
+ unsigned long m_freeSpace;
+
+ private slots:
+ void slotStartClicked();
+
+ void slotUpdateFreeSpace();
+ void slotFreeSpace(const QString&, unsigned long, unsigned long, unsigned long);
+
+};
+
+#endif
diff --git a/src/rip/k3bvideocdrippingoptions.h b/src/rip/k3bvideocdrippingoptions.h
new file mode 100644
index 0000000..bd8aea9
--- /dev/null
+++ b/src/rip/k3bvideocdrippingoptions.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * $Id: k3bvideocdrippingoptions.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_VIDEOCD_OPTIONS_H_
+#define _K3B_VIDEOCD_OPTIONS_H_
+
+#include <qstring.h>
+
+class K3bVideoCdRippingOptions
+{
+ public:
+ K3bVideoCdRippingOptions()
+ : m_videocdsize( 0 ),
+ m_videocdsource( "/dev/cdrom" ),
+ m_videocddestination( "/tmp" ),
+ m_videocddescription( i18n( "Video CD" ) ),
+ m_videocdripfiles( false ),
+ m_videocdripsegments( false ),
+ m_videocdripsequences( false ),
+ m_ignoreExt( false ),
+ m_sector2336( false ),
+ m_extractXML( false )
+ {}
+
+ void setVideoCdSize( unsigned long size ) { m_videocdsize = size;}
+ void setVideoCdSource( const QString& source ) { m_videocdsource = source;}
+ void setVideoCdDestination( const QString& destination ) { m_videocddestination = destination;}
+ void setVideoCdDescription( const QString& description ) { m_videocddescription = description;}
+ void setVideoCdRipFiles( bool ripfiles ) { m_videocdripfiles = ripfiles;}
+ void setVideoCdRipSegments( bool ripsegments ) { m_videocdripsegments = ripsegments;}
+ void setVideoCdRipSequences( bool ripsequences ) { m_videocdripsequences = ripsequences;}
+ void setVideoCdIgnoreExt( bool ignoreext ) { m_ignoreExt = ignoreext;}
+ void setVideoCdSector2336( bool sector2336 ) { m_sector2336 = sector2336;}
+ void setVideoCdExtractXml( bool extractxml ) { m_extractXML = extractxml;}
+
+ unsigned long getVideoCdSize( ) { return m_videocdsize;}
+ QString getVideoCdSource( ) { return m_videocdsource;}
+ QString getVideoCdDestination( ) { return m_videocddestination;}
+ QString getVideoCdDescription( ) { return m_videocddescription;}
+ bool getVideoCdRipFiles( ) { return m_videocdripfiles;}
+ bool getVideoCdRipSegments( ) { return m_videocdripsegments;}
+ bool getVideoCdRipSequences( ) { return m_videocdripsequences;}
+ bool getVideoCdIgnoreExt( ) { return m_ignoreExt;}
+ bool getVideoCdSector2336( ) { return m_sector2336;}
+ bool getVideoCdExtractXml( ) { return m_extractXML;}
+
+ private:
+ unsigned long m_videocdsize;
+
+ QString m_videocdsource;
+ QString m_videocddestination;
+ QString m_videocddescription;
+
+ bool m_videocdripfiles;
+ bool m_videocdripsegments;
+ bool m_videocdripsequences;
+ bool m_ignoreExt;
+ bool m_sector2336;
+ bool m_extractXML;
+};
+
+#endif
diff --git a/src/rip/k3bvideocdview.cpp b/src/rip/k3bvideocdview.cpp
new file mode 100644
index 0000000..c0f5ae2
--- /dev/null
+++ b/src/rip/k3bvideocdview.cpp
@@ -0,0 +1,509 @@
+/*
+*
+* $Id: k3bvideocdview.cpp 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+// kde includes
+#include <kaction.h>
+#include <kcutlabel.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kstdaction.h>
+
+// qt includes
+#include <qfont.h>
+#include <qframe.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qcursor.h>
+#include <qapplication.h>
+
+// k3b includes
+#include "k3bvideocdview.h"
+#include "k3bvideocdrippingdialog.h"
+
+#include <k3bdevice.h>
+#include <k3bmsf.h>
+#include <k3btoc.h>
+#include <k3bcore.h>
+#include <k3blistview.h>
+#include <k3bstdguiitems.h>
+#include <k3btoolbox.h>
+
+
+class K3bVideoCdView::VideoTrackViewItem : public QListViewItem
+{
+ public:
+ VideoTrackViewItem( QListViewItem* parent, QListViewItem* after )
+ : QListViewItem( parent, after )
+ {
+ setSelectable( false );
+ }
+
+ VideoTrackViewItem( QListView* parent, QListViewItem* after )
+ : QListViewItem( parent, after )
+ {
+ setSelectable( false );
+ }
+
+ VideoTrackViewItem( QListViewItem* parent,
+ const QString& name,
+ const QString& id,
+ int _trackNumber,
+ const K3b::Msf& length )
+ : QListViewItem( parent )
+ {
+ setText( 0, QString( "%1. %2" ).arg( _trackNumber ).arg( id ) );
+ setText( 1, name );
+ if ( length > 0 ) {
+ setText( 2, length.toString() );
+ setText( 3, KIO::convertSize( length.mode2Form2Bytes() ) );
+ }
+
+ trackNumber = _trackNumber;
+ setSelectable( false );
+ }
+
+ int trackNumber;
+
+ void updateData( const K3bVideoCdInfoResultEntry& resultEntry )
+ {
+ setText( 0, QString( "%1. %2" ).arg( trackNumber ).arg( resultEntry.id ) );
+ setText( 1, resultEntry.name );
+ }
+
+};
+
+class K3bVideoCdView::VideoTrackViewCheckItem : public QCheckListItem
+{
+ public:
+ VideoTrackViewCheckItem( QListViewItem* parent,
+ const QString& desc )
+ : QCheckListItem( parent,
+ QString::null,
+ QCheckListItem::CheckBox )
+ {
+ setText( 0, desc );
+
+ setOn( true );
+ }
+
+ VideoTrackViewCheckItem( QListView* parent,
+ const QString& desc )
+ : QCheckListItem( parent,
+ QString::null,
+ QCheckListItem::CheckBox )
+ {
+ setText( 0, desc );
+
+ setOn( true );
+ }
+
+ VideoTrackViewCheckItem( VideoTrackViewCheckItem* parent,
+ const QString& desc )
+ : QCheckListItem( parent,
+ QString::null,
+ QCheckListItem::CheckBox )
+ {
+ setText( 0, desc );
+
+ setOn( true );
+ }
+
+ void updateData( const K3b::Msf& length, bool form2 = false )
+ {
+ setText( 2, length.toString() );
+ if ( form2 )
+ setText( 3, KIO::convertSize( length.mode2Form2Bytes() ) );
+ else
+ setText( 3, KIO::convertSize( length.mode2Form1Bytes() ) );
+ }
+
+};
+
+K3bVideoCdView::K3bVideoCdView( QWidget* parent, const char *name )
+ : K3bMediaContentsView( true,
+ K3bMedium::CONTENT_VIDEO_CD,
+ K3bDevice::MEDIA_CD_ALL,
+ K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_COMPLETE,
+ parent, name )
+{
+ QGridLayout * mainGrid = new QGridLayout( mainWidget() );
+
+ // toolbox
+ // ----------------------------------------------------------------------------------
+ QHBoxLayout* toolBoxLayout = new QHBoxLayout( 0, 0, 0, "toolBoxLayout" );
+ m_toolBox = new K3bToolBox( mainWidget() );
+ toolBoxLayout->addWidget( m_toolBox );
+ QSpacerItem* spacer = new QSpacerItem( 10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ toolBoxLayout->addItem( spacer );
+ m_labelLength = new QLabel( mainWidget() );
+ m_labelLength->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ toolBoxLayout->addWidget( m_labelLength );
+
+ // the track view
+ // ----------------------------------------------------------------------------------
+ m_trackView = new K3bListView( mainWidget() );
+ m_trackView->setFullWidth( true );
+ m_trackView->setAllColumnsShowFocus( true );
+ m_trackView->setSelectionMode( QListView::Single );
+ m_trackView->setDragEnabled( true );
+ m_trackView->addColumn( i18n( "Item Name" ) );
+ m_trackView->addColumn( i18n( "Extracted Name" ) );
+ m_trackView->addColumn( i18n( "Length" ) );
+ m_trackView->addColumn( i18n( "Size" ) );
+
+ m_trackView->header() ->setClickEnabled( false );
+
+ m_trackView->setItemsRenameable( false );
+ m_trackView->setRootIsDecorated( true );
+
+ connect( m_trackView, SIGNAL( contextMenu( KListView*, QListViewItem*, const QPoint& ) ),
+ this, SLOT( slotContextMenu( KListView*, QListViewItem*, const QPoint& ) ) );
+ connect( m_trackView, SIGNAL( selectionChanged( QListViewItem* ) ),
+ this, SLOT( slotTrackSelectionChanged( QListViewItem* ) ) );
+ connect( m_trackView, SIGNAL( clicked( QListViewItem* ) ),
+ this, SLOT( slotStateChanged( QListViewItem* ) ) );
+ connect( m_trackView, SIGNAL( spacePressed( QListViewItem* ) ),
+ this, SLOT( slotStateChanged( QListViewItem* ) ) );
+
+
+ mainGrid->addLayout( toolBoxLayout, 0, 0 );
+ mainGrid->addWidget( m_trackView, 1, 0 );
+
+ initActions();
+ slotTrackSelectionChanged( 0 );
+
+ m_videocdinfo = 0L;
+ m_videooptions = new K3bVideoCdRippingOptions();
+
+ m_contentList.clear();
+}
+
+
+K3bVideoCdView::~K3bVideoCdView()
+{
+ delete m_videocdinfo;
+ delete m_videooptions;
+}
+
+
+void K3bVideoCdView::reloadMedium()
+{
+ m_toc = medium().toc();
+
+ m_trackView->clear();
+
+ m_trackView->setEnabled( false );
+ m_toolBox->setEnabled( false );
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+
+ m_contentList.append( new VideoTrackViewCheckItem( m_trackView, i18n("Video CD MPEG tracks") ) );
+ m_contentList.append( new VideoTrackViewCheckItem( m_trackView, i18n("Video CD DATA track" ) ) );
+
+ ( ( VideoTrackViewCheckItem* ) m_contentList[ 0 ] ) ->setOpen( true );
+
+ // create a listviewItem for every video track
+ int index = 0;
+ m_videocddatasize = 0;
+ m_videocdmpegsize = 0;
+
+ K3b::Msf sequenceSize;
+
+ for ( K3bDevice::Toc::const_iterator it = m_toc.begin();
+ it != m_toc.end(); ++it ) {
+
+ if ( index > 0 ) {
+ K3b::Msf length( ( *it ).length() );
+ sequenceSize += length;
+ m_videocdmpegsize += length.mode2Form2Bytes();
+ ( void ) new VideoTrackViewItem( ( VideoTrackViewCheckItem* ) m_contentList[ 0 ], i18n( "Sequence-%1" ).arg( index ), "", index, length );
+ } else {
+ K3b::Msf length( ( *it ).length() );
+ m_videocddatasize += length.mode2Form1Bytes();
+ ( ( VideoTrackViewCheckItem* ) m_contentList[ 1 ] ) ->updateData( length );
+ ( void ) new VideoTrackViewCheckItem( ( VideoTrackViewCheckItem* ) m_contentList[ 1 ], i18n( "Files" ) );
+ ( void ) new VideoTrackViewCheckItem( ( VideoTrackViewCheckItem* ) m_contentList[ 1 ], i18n( "Segments" ) );
+ }
+
+ index++;
+ }
+
+ ( ( VideoTrackViewCheckItem* ) m_contentList[ 0 ] ) ->updateData( sequenceSize, true );
+
+ m_videooptions ->setVideoCdSource( device()->devicename() );
+
+ m_videocdinfo = new K3bVideoCdInfo( this );
+ m_videocdinfo->info( device()->devicename() );
+
+ connect( m_videocdinfo, SIGNAL( infoFinished( bool ) ),
+ this, SLOT( slotVideoCdInfoFinished( bool ) ) );
+
+}
+
+void K3bVideoCdView::slotVideoCdInfoFinished( bool success )
+{
+ if ( success ) {
+ m_videocdinfoResult = m_videocdinfo->result();
+ updateDisplay();
+ }
+
+ m_trackView->setEnabled( true );
+ m_toolBox->setEnabled( true );
+ QApplication::restoreOverrideCursor();
+
+}
+
+void K3bVideoCdView::updateDisplay()
+{
+ // update the listview
+
+ VideoTrackViewItem * item = ( VideoTrackViewItem* ) m_contentList[ 0 ] ->firstChild();
+ int index = 0;
+ while ( item ) {
+ item->updateData( m_videocdinfoResult.entry( index, K3bVideoCdInfoResult::SEQUENCE ) );
+ item = ( VideoTrackViewItem* ) item->nextSibling();
+ index++;
+ }
+
+ VideoTrackViewCheckItem* check_item = ( VideoTrackViewCheckItem* ) m_contentList[ 1 ] ->firstChild();
+ while ( check_item ) {
+ if ( check_item->key( 0, false ).compare( i18n( "Files" ) ) == 0 ) {
+ if ( domTree.setContent( m_videocdinfoResult.xmlData ) ) {
+
+ QDomElement root = domTree.documentElement();
+ QDomNode node;
+ node = root.firstChild();
+ while ( !node.isNull() ) {
+ if ( node.isElement() && node.nodeName() == "filesystem" ) {
+ QDomElement body = node.toElement();
+ buildTree( check_item, body );
+ break;
+ }
+ node = node.nextSibling();
+ }
+ }
+ } else {
+ for ( index = 0; index < m_videocdinfoResult.foundEntries( K3bVideoCdInfoResult::SEGMENT ); index++ ) {
+ ( void ) new VideoTrackViewItem( check_item, m_videocdinfoResult.entry( index, K3bVideoCdInfoResult::SEGMENT ).name, m_videocdinfoResult.entry( index, K3bVideoCdInfoResult::SEGMENT ).id , index + 1, 0 );
+ }
+ }
+ check_item = ( VideoTrackViewCheckItem* ) check_item->nextSibling();
+ }
+
+ if ( !m_videocdinfoResult.volumeId.isEmpty() ) {
+ QString description = m_videocdinfoResult.volumeId + " (" + m_videocdinfoResult.type + " " + m_videocdinfoResult.version + ")" ;
+ setTitle( description );
+ m_videooptions ->setVideoCdDescription( description );
+ }
+ else
+ setTitle( i18n( "Video CD" ) );
+
+ m_labelLength->setText( i18n( "1 track (%1)", "%n tracks (%1)", m_toc.count() ).arg( K3b::Msf( m_toc.length() ).toString() ) );
+}
+
+
+void K3bVideoCdView::initActions()
+{
+ m_actionCollection = new KActionCollection( this );
+
+ KAction* actionSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ),
+ m_actionCollection, "select_all" );
+ KAction* actionDeselectAll = KStdAction::deselect( this, SLOT( slotDeselectAll() ),
+ m_actionCollection, "deselect_all" );
+ actionDeselectAll->setText( i18n( "Dese&lect All" ) );
+ KAction* actionSelect = new KAction( i18n( "Select Track" ), 0, 0, this,
+ SLOT( slotSelect() ), actionCollection(),
+ "select_track" );
+ KAction* actionDeselect = new KAction( i18n( "Deselect Track" ), 0, 0, this,
+ SLOT( slotDeselect() ), actionCollection(),
+ "deselect_track" );
+
+ KAction* actionStartRip = new KAction( i18n( "Start Ripping" ), "run", 0, this,
+ SLOT( startRip() ), actionCollection(), "start_rip" );
+
+ // TODO: set the actions tooltips and whatsthis infos
+
+ // setup the popup menu
+ m_popupMenu = new KActionMenu( actionCollection(), "popup_menu" );
+ KAction* separator = new KActionSeparator( actionCollection(), "separator" );
+ m_popupMenu->insert( actionSelect );
+ m_popupMenu->insert( actionDeselect );
+ m_popupMenu->insert( actionSelectAll );
+ m_popupMenu->insert( actionDeselectAll );
+ m_popupMenu->insert( separator );
+ m_popupMenu->insert( actionStartRip );
+
+ // setup the toolbox
+ m_toolBox->addButton( actionStartRip, true );
+}
+
+
+void K3bVideoCdView::slotContextMenu( KListView*, QListViewItem*, const QPoint& p )
+{
+ m_popupMenu->popup( p );
+}
+
+
+void K3bVideoCdView::slotTrackSelectionChanged( QListViewItem* item )
+{
+ actionCollection() ->action( "select_track" ) ->setEnabled( item != 0 );
+ actionCollection() ->action( "deselect_track" ) ->setEnabled( item != 0 );
+}
+
+void K3bVideoCdView::slotStateChanged( QListViewItem* item )
+{
+ /* > QT 3.1
+ if ( !item == 0 && item ->isSelectable() ) {
+ if ( ( ( VideoTrackViewCheckItem* ) item) ->state() == QCheckListItem::On)
+ slotSelect();
+ else if ( ( ( VideoTrackViewCheckItem* ) item) ->state() == QCheckListItem::Off)
+ slotDeselect();
+ }
+ */
+ if ( !item == 0 && item ->isSelectable() ) {
+ if ( ( ( VideoTrackViewCheckItem* ) item) ->isOn() )
+ slotSelect();
+ else
+ slotDeselect();
+ }
+}
+
+void K3bVideoCdView::startRip()
+{
+
+ int selectedItems = 0;
+ for ( QListViewItemIterator it( m_trackView ); it.current(); ++it ) {
+ if ( it.current() ->isSelectable() ) {
+ if ( ( ( ( VideoTrackViewCheckItem* ) it.current()) ->key( 0, false ).compare( i18n("Video CD MPEG tracks" ) ) == 0 ) && ( ( VideoTrackViewCheckItem* ) it.current() ) ->isOn() ) {
+ m_videooptions ->setVideoCdRipSequences( true );
+ selectedItems++;
+ }
+ else if ( ( ( ( VideoTrackViewCheckItem* ) it.current()) ->key( 0, false ).compare( i18n("Files" ) ) == 0 ) && ( ( VideoTrackViewCheckItem* ) it.current() ) ->isOn() ) {
+ m_videooptions ->setVideoCdRipFiles( true );
+ selectedItems++;
+ }
+ else if ( ( ( ( VideoTrackViewCheckItem* ) it.current()) ->key( 0, false ).compare( i18n("Segments" ) ) == 0 ) && ( ( VideoTrackViewCheckItem* ) it.current() ) ->isOn() ) {
+ m_videooptions ->setVideoCdRipSegments( true );
+ selectedItems++;
+ }
+ }
+ }
+
+ if( selectedItems == 0 ) {
+ KMessageBox::error( this, i18n("Please select the tracks to rip."), i18n("No Tracks Selected") );
+ }
+ else {
+ unsigned long videocdsize = 0;
+ // TODO: split SegmentSize and FileSize. Have no infos now
+ if ( m_videooptions ->getVideoCdRipSegments() || m_videooptions ->getVideoCdRipFiles())
+ videocdsize += m_videocddatasize;
+ if ( m_videooptions ->getVideoCdRipSequences() )
+ videocdsize += m_videocdmpegsize;
+
+ kdDebug() << QString("(K3bVideoCdView::startRip()) m_videooptions ->setVideoCdSize( %1)").arg( videocdsize ) << endl;
+ m_videooptions ->setVideoCdSize( videocdsize );
+ K3bVideoCdRippingDialog rip( m_videooptions, this );
+ rip.exec();
+ }
+}
+
+void K3bVideoCdView::slotSelectAll()
+{
+ for ( QListViewItemIterator it( m_trackView ); it.current(); ++it )
+ if ( it.current() ->isSelectable() )
+ ( ( VideoTrackViewCheckItem* ) it.current() ) ->setOn( true );
+}
+
+void K3bVideoCdView::slotDeselectAll()
+{
+ for ( QListViewItemIterator it( m_trackView ); it.current(); ++it )
+ if ( it.current() ->isSelectable() )
+ ( ( VideoTrackViewCheckItem* ) it.current() ) ->setOn( false );
+}
+
+void K3bVideoCdView::slotSelect()
+{
+ if ( QListViewItem * sel = m_trackView->selectedItem() ) {
+ ( ( VideoTrackViewCheckItem* ) sel) ->setOn( true );
+ QListViewItem * item = sel ->firstChild();
+ while ( item ) {
+ if ( item ->isSelectable() )
+ ( ( VideoTrackViewCheckItem* ) item) ->setOn( true );
+
+ item = item->nextSibling();
+ }
+ }
+}
+
+void K3bVideoCdView::slotDeselect()
+{
+ if ( QListViewItem * sel = m_trackView->selectedItem() ) {
+ ( ( VideoTrackViewCheckItem* ) sel) ->setOn( false );
+ QListViewItem * item = sel ->firstChild();
+ while ( item ) {
+ if ( item ->isSelectable() )
+ ( ( VideoTrackViewCheckItem* ) item) ->setOn( false );
+
+ item = item->nextSibling();
+ }
+ }
+}
+
+void K3bVideoCdView::enableInteraction( bool b )
+{
+ actionCollection()->action( "start_rip" )->setEnabled( b );
+}
+
+void K3bVideoCdView::buildTree( QListViewItem *parentItem, const QDomElement &parentElement, const QString& pname )
+{
+ VideoTrackViewItem * thisItem = 0;
+ QDomNode node = parentElement.firstChild();
+
+ while ( !node.isNull() ) {
+ if ( node.isElement() && node.nodeName() == "folder" || node.nodeName() == "file" ) {
+ if ( parentItem == 0 )
+ thisItem = new VideoTrackViewItem( m_trackView, thisItem );
+ else
+ thisItem = new VideoTrackViewItem( parentItem, thisItem );
+
+ QString txt = node.firstChild().toElement().text();
+ thisItem->setText( 0, txt);
+ if ( node.nodeName() == "folder" ) {
+ buildTree( thisItem, node.toElement(), pname + "_" + txt.lower() );
+ }
+ else {
+ thisItem->setText( 1, pname + "_" + txt.lower() );
+ buildTree( thisItem, node.toElement(), pname );
+ }
+ } else if ( node.isElement() && node.nodeName() == "segment-item" || node.nodeName() == "sequence-item" ) {
+ if ( parentItem == 0 )
+ thisItem = new VideoTrackViewItem( m_trackView, thisItem );
+ else
+ thisItem = new VideoTrackViewItem( parentItem, thisItem );
+
+ thisItem->setText( 0, node.toElement().attribute( "src" ) );
+
+ buildTree( thisItem, node.toElement() );
+ }
+
+ node = node.nextSibling();
+ }
+}
+
+#include "k3bvideocdview.moc"
diff --git a/src/rip/k3bvideocdview.h b/src/rip/k3bvideocdview.h
new file mode 100644
index 0000000..cb3e7a6
--- /dev/null
+++ b/src/rip/k3bvideocdview.h
@@ -0,0 +1,105 @@
+/*
+*
+* $Id: k3bvideocdview.h 619556 2007-01-03 17:38:12Z trueg $
+* Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
+*
+* This file is part of the K3b project.
+* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* See the file "COPYING" for the exact licensing terms.
+*/
+
+
+#ifndef _K3B_VIDEOCDVIEW_H_
+#define _K3B_VIDEOCDVIEW_H_
+
+#include <qdom.h>
+
+#include <k3bmediacontentsview.h>
+#include <k3bmedium.h>
+
+#include "k3bvideocdinfo.h"
+
+class KActionCollection;
+class KActionMenu;
+class KListView;
+
+class QLabel;
+class QListViewItem;
+
+class K3bListView;
+class K3bToolBox;
+class K3bVideoCdRippingOptions;
+
+namespace K3bDevice
+{
+ class DiskInfoDetector;
+ class Toc;
+ class Device;
+}
+
+
+class K3bVideoCdView : public K3bMediaContentsView
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoCdView( QWidget* parent = 0, const char * name = 0 );
+ ~K3bVideoCdView();
+
+ KActionCollection* actionCollection() const
+ {
+ return m_actionCollection;
+ }
+
+ private slots:
+ void slotContextMenu( KListView*, QListViewItem*, const QPoint& );
+ void slotTrackSelectionChanged( QListViewItem* );
+ void slotStateChanged( QListViewItem* );
+ void slotVideoCdInfoFinished( bool );
+
+ void startRip();
+ void slotSelectAll();
+ void slotDeselectAll();
+ void slotSelect();
+ void slotDeselect();
+
+ private:
+
+ class VideoTrackViewCheckItem;
+ class VideoTrackViewItem;
+
+ void reloadMedium();
+
+ void initActions();
+ void updateDisplay();
+ void enableInteraction( bool );
+ void buildTree( QListViewItem *parentItem, const QDomElement &parentElement, const QString& pname = QString::null );
+
+ K3bDevice::Toc m_toc;
+
+ KActionCollection* m_actionCollection;
+ KActionMenu* m_popupMenu;
+
+ K3bVideoCdInfoResult m_videocdinfoResult;
+ K3bVideoCdInfo* m_videocdinfo;
+ K3bVideoCdRippingOptions* m_videooptions;
+
+ K3bListView* m_trackView;
+ K3bToolBox* m_toolBox;
+ QLabel* m_labelLength;
+
+ QDomDocument domTree;
+
+ QValueList<VideoTrackViewCheckItem *> m_contentList;
+
+ unsigned long m_videocddatasize;
+ unsigned long m_videocdmpegsize;
+
+};
+
+#endif
diff --git a/src/rip/videodvd/Makefile.am b/src/rip/videodvd/Makefile.am
new file mode 100644
index 0000000..bac9b0a
--- /dev/null
+++ b/src/rip/videodvd/Makefile.am
@@ -0,0 +1,16 @@
+AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/core \
+ -I$(srcdir)/../../../libk3bdevice \
+ -I$(srcdir)/../../../libk3b/tools \
+ -I$(srcdir)/../../../libk3b/videodvd/ \
+ -I$(srcdir)/../../../libk3b/jobs/ \
+ -I$(srcdir)/../.. \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libvideodvdrip.la
+
+libvideodvdrip_la_SOURCES = base_k3bvideodvdrippingwidget.ui k3bvideodvdrippingview.cpp \
+ k3bvideodvdrippingtitlelistview.cpp \
+ k3bvideodvdrippingjob.cpp k3bvideodvdrippingwidget.cpp \
+ k3bvideodvdrippingdialog.cpp k3bvideodvdrippingpreview.cpp
diff --git a/src/rip/videodvd/base_k3bvideodvdrippingwidget.ui b/src/rip/videodvd/base_k3bvideodvdrippingwidget.ui
new file mode 100644
index 0000000..72b03b4
--- /dev/null
+++ b/src/rip/videodvd/base_k3bvideodvdrippingwidget.ui
@@ -0,0 +1,721 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bVideoDVDRippingWidget</class>
+<author>Seastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>644</width>
+ <height>387</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Please select the audio streams you want to include in every ripped title</string>
+ </property>
+ </widget>
+ <widget class="KListView">
+ <property name="name">
+ <cstring>m_titleView</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Setti&amp;ngs</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="1">
+ <property name="name">
+ <cstring>groupBox6</cstring>
+ </property>
+ <property name="title">
+ <string>Video Quality</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Video Size:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_comboVideoSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonCustomPictureSize</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Custom...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2_3</cstring>
+ </property>
+ <property name="text">
+ <string>Video Bitrate:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_spinVideoBitrate</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> kbps</string>
+ </property>
+ <property name="maxValue">
+ <number>10000</number>
+ </property>
+ <property name="value">
+ <number>1800</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Target Folder</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Free space in directory:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_editBaseDir</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>m_labelFreeSpace</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Space needed:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>m_labelNeededSpace</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="1">
+ <property name="name">
+ <cstring>groupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Audio Quality</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QWidgetStack">
+ <property name="name">
+ <cstring>m_stackAudioQuality</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>m_stackPageAudioQualityMp3</cstring>
+ </property>
+ <attribute name="id">
+ <number>0</number>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkAudioVBR</cstring>
+ </property>
+ <property name="text">
+ <string>Variable &amp;Bitrate</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_labelAudioBitrate</cstring>
+ </property>
+ <property name="text">
+ <string>Audio Bitrate:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_comboAudioBitrate</cstring>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>m_stackPageAudioQualityAC3Pt</cstring>
+ </property>
+ <attribute name="id">
+ <number>1</number>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KActiveLabel">
+ <property name="name">
+ <cstring>m_labelNoAudioSettings</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p&gt;No Audio Quality settings available for &lt;em&gt;AC3 pass-through&lt;/em&gt;. The audio stream from the Video DVD is used without any changes.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>m_stackPageAudioQualityAC3</cstring>
+ </property>
+ <attribute name="id">
+ <number>2</number>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Audio Bitrate:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_spinAudioBitrate</cstring>
+ </property>
+ <property name="suffix">
+ <string> kbps</string>
+ </property>
+ <property name="maxValue">
+ <number>640</number>
+ </property>
+ <property name="minValue">
+ <number>32</number>
+ </property>
+ <property name="lineStep">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>128</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <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>
+ </vbox>
+ </widget>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Filetype</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Video Codec:</string>
+ </property>
+ </widget>
+ <widget class="K3bIntMapComboBox">
+ <property name="name">
+ <cstring>m_comboVideoCodec</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the Video codec used to encode the DVD titles</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Audio Codec:</string>
+ </property>
+ </widget>
+ <widget class="K3bIntMapComboBox">
+ <property name="name">
+ <cstring>m_comboAudioCodec</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the Audio codec used to encode the DVD titles</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>File Namin&amp;g</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_4</cstring>
+ </property>
+ <property name="text">
+ <string>Ripped files pattern:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_comboFilenamePattern</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="acceptDrops">
+ <bool>true</bool>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KURLLabel">
+ <property name="name">
+ <cstring>m_specialStringsLabel</cstring>
+ </property>
+ <property name="text">
+ <string>See special strings</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkBlankReplace</cstring>
+ </property>
+ <property name="text">
+ <string>Replace all &amp;blanks with:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editBlankReplace</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>_</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>5</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Advanced</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkTwoPassEncoding</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;2-pass encoding</string>
+ </property>
+ <property name="accel">
+ <string>Alt+2</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Enable 2-pass encoding</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b encodes the video titles in two passes. The first pass is used to gather information about the video in order to improve the distribution of bits in the second pass. The resulting video will have a higher quality using a variable bitrate.
+&lt;p&gt;If this option is not checked K3b will create video files with a constant bitrate and a lower quality.
+&lt;p&gt;2-pass encoding results in a doubled encoding time.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkAutoClipping</cstring>
+ </property>
+ <property name="text">
+ <string>Automatic &amp;Video Clipping</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Automatically detect the black borders of the video</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Most Video DVDs are encoded in a letterboxed format. &lt;em&gt;Letterboxed&lt;/em&gt; refers to black bars used at the top and bottom (and sometimes at the sides) of the video to force it into one of the aspect ratios supported by the Video DVD standard.
+&lt;p&gt;If this option is checked K3b will automatically detect and remove these black bars from the resulting video.
+&lt;p&gt;Although this method is very reliable there may be problems if the source material is exceptionally short or dark.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkAudioResampling</cstring>
+ </property>
+ <property name="text">
+ <string>Resample Audio to &amp;44.1 KHz</string>
+ </property>
+ <property name="accel">
+ <string>Alt+4</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Change the sample rate of the audio stream to 44.1 KHz</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Video DVD audio streams normally are encoded with a sampling rate of 48000 Hz. Audio CDs on the other hand are encoded with a sampling rate of 44100 Hz.
+&lt;p&gt;If this option is checked K3b will change the sampling rate of the audio stream to 44100 Hz.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkLowPriority</cstring>
+ </property>
+ <property name="text">
+ <string>Low s&amp;cheduling priority for the video transcoding process</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>K3bIntMapComboBox</class>
+ <header location="global">k3bintmapcombobox.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>m_checkBlankReplace</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_editBlankReplace</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kactivelabel.h</includehint>
+ <includehint>k3bintmapcombobox.h</includehint>
+ <includehint>k3bintmapcombobox.h</includehint>
+ <includehint>kurllabel.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/src/rip/videodvd/k3bvideodvdrippingdialog.cpp b/src/rip/videodvd/k3bvideodvdrippingdialog.cpp
new file mode 100644
index 0000000..ddb5ff2
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingdialog.cpp
@@ -0,0 +1,634 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdrippingdialog.h"
+#include "k3bvideodvdrippingwidget.h"
+#include <k3bvideodvdtitletranscodingjob.h>
+#include <k3bjobprogressdialog.h>
+#include <k3bapplication.h>
+#include <k3bmedium.h>
+#include <k3bmediacache.h>
+#include <k3bglobals.h>
+#include <k3bfilesysteminfo.h>
+
+#include <klocale.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kurlrequester.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <kio/global.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qstyle.h>
+#include <qfontmetrics.h>
+
+
+static QString videoCodecId( K3bVideoDVDTitleTranscodingJob::VideoCodec codec )
+{
+ switch( codec ) {
+ case K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_FFMPEG_MPEG4:
+ return "ffmpeg_mpeg4";
+ case K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_XVID:
+ return "xvid";
+ default:
+ return "none";
+ }
+}
+
+
+static QString audioCodecId( K3bVideoDVDTitleTranscodingJob::AudioCodec codec )
+{
+ switch( codec ) {
+ case K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3:
+ return "mp3";
+ case K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_STEREO:
+ return "ac3_stereo";
+ case K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH:
+ return "ac3_passthrough";
+ default:
+ return "none";
+ }
+}
+
+
+static K3bVideoDVDTitleTranscodingJob::VideoCodec videoCodecFromId( const QString& codec )
+{
+ if( codec == "xvid" )
+ return K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_XVID;
+ else // if( codec == "ffmpeg_mpeg4" )
+ return K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_FFMPEG_MPEG4;
+}
+
+
+static K3bVideoDVDTitleTranscodingJob::AudioCodec audioCodecFromId( const QString& codec )
+{
+ if( codec == "ac3_stereo" )
+ return K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_STEREO;
+ else if( codec == "ac3_passthrough" )
+ return K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH;
+ else // if( codec == "mp3" )
+ return K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3;
+}
+
+
+// resize according to aspect ratio
+static QSize resizeTitle( const K3bVideoDVD::VideoStream& title, const QSize& size )
+{
+ int w = size.width();
+ int h = size.height();
+ int rw = title.realPictureWidth();
+ int rh = title.realPictureHeight();
+
+ if( w == 0 && h == 0 ) {
+ w = rw;
+ h = rh;
+ }
+ else if( w == 0 ) {
+ w = h * rw / rh;
+ }
+ else if( h == 0 ) {
+ h = w * rh / rw;
+ }
+
+ return QSize(w,h);
+}
+
+
+
+class K3bVideoDVDRippingDialog::AudioStreamViewItem : public QCheckListItem
+{
+public:
+ AudioStreamViewItem( K3bVideoDVDRippingDialog* dlg,
+ QCheckListItem* parent, QListViewItem* after, const QString& text,
+ int audioStream )
+ : QCheckListItem( parent, after, text, RadioButton ),
+ m_audioStream( audioStream ),
+ m_dlg( dlg ) {
+ }
+
+private:
+ void stateChange( bool ) {
+ if( state() == On ) {
+ m_dlg->m_titleRipInfos[static_cast<QCheckListItem*>(parent())].audioStream = m_audioStream;
+ m_dlg->slotUpdateFilenames();
+ }
+ }
+
+ int m_audioStream;
+ K3bVideoDVDRippingDialog* m_dlg;
+};
+
+
+class K3bVideoDVDRippingDialog::Private
+{
+public:
+ K3bFileSystemInfo fsInfo;
+};
+
+
+K3bVideoDVDRippingDialog::K3bVideoDVDRippingDialog( const K3bVideoDVD::VideoDVD& dvd,
+ const QValueList<int>& titles,
+ QWidget* parent, const char* name )
+ : K3bInteractionDialog( parent, name,
+ i18n("Video DVD Ripping"),
+ QString::null,
+ START_BUTTON|CANCEL_BUTTON,
+ START_BUTTON,
+ "VideoDVD Ripping" ), // config group
+ m_dvd( dvd )
+{
+ d = new Private;
+
+ QWidget* frame = mainWidget();
+ QHBoxLayout* frameLayout = new QHBoxLayout( frame );
+ frameLayout->setMargin( 0 );
+ frameLayout->setAutoAdd( true );
+ m_w = new K3bVideoDVDRippingWidget( frame );
+
+ connect( m_w, SIGNAL(changed()),
+ this, SLOT(slotUpdateFilesizes()) );
+ connect( m_w, SIGNAL(changed()),
+ this, SLOT(slotUpdateFilenames()) );
+ connect( m_w, SIGNAL(changed()),
+ this, SLOT(slotUpdateVideoSizes()) );
+
+ setTitle( i18n("Video DVD Ripping"),
+ i18n("1 title from %1", "%n titles from %1", titles.count())
+ .arg( k3bappcore->mediaCache()->medium(m_dvd.device()).beautifiedVolumeId() ) );
+
+ // populate list map
+ populateTitleView( titles );
+}
+
+
+K3bVideoDVDRippingDialog::~K3bVideoDVDRippingDialog()
+{
+ delete d;
+}
+
+
+void K3bVideoDVDRippingDialog::populateTitleView( const QValueList<int>& titles )
+{
+ m_w->m_titleView->clear();
+ m_titleRipInfos.clear();
+
+ QCheckListItem* titleItem = 0;
+ for( QValueList<int>::const_iterator it = titles.begin(); it != titles.end(); ++it ) {
+ titleItem = new QCheckListItem( m_w->m_titleView,
+ titleItem,
+ i18n("Title %1 (%2)")
+ .arg(*it)
+ .arg(m_dvd[*it-1].playbackTime().toString()),
+ QCheckListItem::RadioButtonController );
+ titleItem->setText( 1, QString("%1x%2")
+ .arg(m_dvd[*it-1].videoStream().realPictureWidth())
+ .arg(m_dvd[*it-1].videoStream().realPictureHeight()) );
+ titleItem->setText( 3, QString("%1 Title %2.avi").arg(m_dvd.volumeIdentifier()).arg(*it) );
+
+ // now for the rip info
+ K3bVideoDVDRippingJob::TitleRipInfo ri( *it );
+
+ //
+ // Determine default language selection:
+ // first try the configured locale, if that fails, fall back to the first audio stream
+ //
+ ri.audioStream = 0;
+ for( unsigned int i = 0; i < m_dvd[*it-1].numAudioStreams(); ++i ) {
+ if( m_dvd[*it-1].audioStream(i).langCode() == KGlobal::locale()->language() &&
+ m_dvd[*it-1].audioStream(i).format() != K3bVideoDVD::AUDIO_FORMAT_DTS ) {
+ ri.audioStream = i;
+ break;
+ }
+ }
+
+ QListViewItem* asI = 0;
+ for( unsigned int i = 0; i < m_dvd[*it-1].numAudioStreams(); ++i ) {
+ QString text = i18n("%1 %2Ch (%3%4)")
+ .arg( K3bVideoDVD::audioFormatString( m_dvd[*it-1].audioStream(i).format() ) )
+ .arg( m_dvd[*it-1].audioStream(i).channels() )
+ .arg( m_dvd[*it-1].audioStream(i).langCode().isEmpty()
+ ? i18n("unknown language")
+ : KGlobal::locale()->twoAlphaToLanguageName( m_dvd[*it-1].audioStream(i).langCode() ) )
+ .arg( m_dvd[*it-1].audioStream(i).codeExtension() != K3bVideoDVD::AUDIO_CODE_EXT_UNSPECIFIED
+ ? QString(" ") + K3bVideoDVD::audioCodeExtensionString( m_dvd[*it-1].audioStream(i).codeExtension() )
+ : QString::null );
+
+ if( m_dvd[*it-1].audioStream(i).format() == K3bVideoDVD::AUDIO_FORMAT_DTS ) {
+ // width of the radio button from QCheckListItem::paintCell
+ int buttonSize = style().pixelMetric( QStyle::PM_CheckListButtonSize, m_w->m_titleView ) + 4;
+ int spaceWidth = fontMetrics().width( ' ' );
+ int numSpaces = buttonSize/spaceWidth;
+ asI = new QListViewItem( titleItem, asI, QString().fill( ' ', numSpaces ) + text + " (" + i18n("not supported") + ")" );
+ }
+ else {
+ asI = new AudioStreamViewItem( this, titleItem, asI, text, i );
+
+ if( ri.audioStream == (int)i )
+ ((AudioStreamViewItem*)asI)->setState( QCheckListItem::On );
+ }
+ }
+
+ titleItem->setOpen( true );
+
+ m_titleRipInfos[titleItem] = ri;
+ }
+}
+
+
+void K3bVideoDVDRippingDialog::slotUpdateFilenames()
+{
+ QString baseDir = K3b::prepareDir( m_w->m_editBaseDir->url() );
+ d->fsInfo.setPath( baseDir );
+
+ for( QMap<QCheckListItem*, K3bVideoDVDRippingJob::TitleRipInfo>::iterator it = m_titleRipInfos.begin();
+ it != m_titleRipInfos.end(); ++it ) {
+ QString f = d->fsInfo.fixupPath( createFilename( it.data(), m_w->m_comboFilenamePattern->currentText() ) );
+ if( m_w->m_checkBlankReplace->isChecked() )
+ f.replace( QRegExp( "\\s" ), m_w->m_editBlankReplace->text() );
+ it.data().filename = baseDir + f;
+ it.key()->setText( 3, f );
+ }
+}
+
+
+void K3bVideoDVDRippingDialog::slotUpdateFilesizes()
+{
+ double bitrate = (double)m_w->m_spinVideoBitrate->value();
+ KIO::filesize_t overallSize = 0ULL;
+
+ // update file sizes
+ for( QMap<QCheckListItem*, K3bVideoDVDRippingJob::TitleRipInfo>::iterator it = m_titleRipInfos.begin();
+ it != m_titleRipInfos.end(); ++it ) {
+
+ double sec = m_dvd[it.data().title-1].playbackTime().totalSeconds();
+
+ // estimate the filesize
+ KIO::filesize_t size = (KIO::filesize_t)( sec * bitrate * 1000.0 / 8.0 );
+
+ // add audio stream size
+ // FIXME: consider AC3 passthrough
+ size += (KIO::filesize_t)( sec * m_w->selectedAudioBitrate() / 8.0 * 1024.0 );
+
+ it.key()->setText( 2, KIO::convertSize( size ) );
+
+ overallSize += size;
+ }
+
+ m_w->setNeededSize( overallSize );
+}
+
+
+void K3bVideoDVDRippingDialog::slotUpdateVideoSizes()
+{
+ QSize size = m_w->selectedPictureSize();
+ for( QMap<QCheckListItem*, K3bVideoDVDRippingJob::TitleRipInfo>::iterator it = m_titleRipInfos.begin();
+ it != m_titleRipInfos.end(); ++it ) {
+ QSize s( resizeTitle( m_dvd[it.data().title-1].videoStream(), size ) );
+ it.key()->setText( 1, QString("%1x%2").arg(s.width()).arg(s.height()) );
+ }
+}
+
+
+void K3bVideoDVDRippingDialog::setBaseDir( const QString& path )
+{
+ m_w->m_editBaseDir->setURL( path );
+}
+
+
+QString K3bVideoDVDRippingDialog::createFilename( const K3bVideoDVDRippingJob::TitleRipInfo& info, const QString& pattern ) const
+{
+ QString f;
+
+ const K3bVideoDVD::Title& title = m_dvd[info.title-1];
+
+ for( unsigned int i = 0; i < pattern.length(); ++i ) {
+ //
+ // every pattern starts with a % sign
+ //
+ if( pattern[i] == '%' ) {
+ ++i; // skip the %
+ QChar c = pattern[i];
+
+ //
+ // first check if we have a long keyword instead of a one-char
+ //
+ if( pattern[i] == '{' ) {
+ int j = pattern.find( '}', i );
+ if( j < 0 ) // no closing bracket -> no valid pattern
+ c = '*';
+ else {
+ QString keyword = pattern.mid( i+1, j-i-1 );
+ if( keyword == "titlenumber" ||
+ keyword == "title_number" ||
+ keyword == "title" ) {
+ c = PATTERN_TITLE_NUMBER;
+ }
+ else if( keyword == "volumeid" ||
+ keyword == "volume_id" ||
+ keyword == "volid" ||
+ keyword == "vol_id" ) {
+ c = PATTERN_VOLUME_ID;
+ }
+ else if( keyword == "beautifiedvolumeid" ||
+ keyword == "beautified_volumeid" ||
+ keyword == "beautified_volume_id" ||
+ keyword == "beautifiedvolid" ||
+ keyword == "beautified_volid" ||
+ keyword == "beautified_vol_id" ||
+ keyword == "nicevolid" ||
+ keyword == "nice_volid" ||
+ keyword == "nice_vol_id" ) {
+ c = PATTERN_BEAUTIFIED_VOLUME_ID;
+ }
+ else if( keyword == "languagecode" ||
+ keyword == "language_code" ||
+ keyword == "langcode" ||
+ keyword == "lang_code" ) {
+ c = PATTERN_LANGUAGE_CODE;
+
+ }
+ else if( keyword == "lang" ||
+ keyword == "language" ||
+ keyword == "langname" ||
+ keyword == "languagename" ||
+ keyword == "lang_name" ||
+ keyword == "language_name" ) {
+ c = PATTERN_LANGUAGE_NAME;
+ }
+ else if( keyword == "audioformat" ||
+ keyword == "audio_format" ||
+ keyword == "audio" ) {
+ c = PATTERN_AUDIO_FORMAT;
+ }
+ else if( keyword == "channels" ||
+ keyword == "audiochannels" ||
+ keyword == "audio_channels" ||
+ keyword == "ch" ) {
+ c = PATTERN_AUDIO_CHANNELS;
+ }
+ else if( keyword == "videosize" ||
+ keyword == "video_size" ||
+ keyword == "vsize" ) {
+ c = PATTERN_VIDEO_SIZE;
+ }
+ else if( keyword == "originalvideosize" ||
+ keyword == "original_video_size" ||
+ keyword == "origvideosize" ||
+ keyword == "orig_video_size" ||
+ keyword == "origvsize" ) {
+ c = PATTERN_ORIG_VIDEO_SIZE;
+ }
+ else if( keyword == "aspect_ratio" ||
+ keyword == "aspectratio" ||
+ keyword == "ratio" ) {
+ c = PATTERN_ASPECT_RATIO;
+ }
+ else if( keyword == "current_date" ||
+ keyword == "currentdate" ||
+ keyword == "date" ) {
+ c = PATTERN_CURRENT_DATE;
+ }
+ else {
+ // unusable pattern
+ c = '*';
+ }
+
+ //
+ // skip the keyword and the closing bracket
+ //
+ if( c != '*' ) {
+ i += keyword.length() + 1;
+ }
+ }
+ }
+
+ switch( c ) {
+ case PATTERN_TITLE_NUMBER:
+ f.append( QString::number(info.title).rightJustify( 2, '0' ) );
+ break;
+ case PATTERN_VOLUME_ID:
+ f.append( m_dvd.volumeIdentifier() );
+ break;
+ case PATTERN_BEAUTIFIED_VOLUME_ID:
+ f.append( k3bappcore->mediaCache()->medium( m_dvd.device() ).beautifiedVolumeId() );
+ break;
+ case PATTERN_LANGUAGE_CODE:
+ if( title.numAudioStreams() > 0 )
+ f.append( title.audioStream( info.audioStream ).langCode() );
+ break;
+ case PATTERN_LANGUAGE_NAME:
+ if( title.numAudioStreams() > 0 )
+ f.append( KGlobal::locale()->twoAlphaToLanguageName( title.audioStream( info.audioStream ).langCode() ) );
+ break;
+ case PATTERN_AUDIO_FORMAT:
+ // FIXME: what about MPEG audio streams?
+ if( title.numAudioStreams() > 0 ) {
+ if( m_w->selectedAudioCodec() == K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3 )
+ f.append( K3bVideoDVDTitleTranscodingJob::audioCodecString( m_w->selectedAudioCodec() ) );
+ else
+ f.append( K3bVideoDVD::audioFormatString( title.audioStream( info.audioStream ).format() ) );
+ }
+ break;
+ case PATTERN_AUDIO_CHANNELS:
+ if( title.numAudioStreams() > 0 )
+ f.append( i18n("%nCh", "%nCh",
+ m_w->selectedAudioCodec() == K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH
+ ? title.audioStream( info.audioStream ).channels()
+ : 2 ) );
+ break;
+ case PATTERN_ORIG_VIDEO_SIZE:
+ f.append( QString("%1x%2")
+ .arg(title.videoStream().pictureWidth())
+ .arg(title.videoStream().pictureHeight()) );
+ break;
+ case PATTERN_VIDEO_SIZE: {
+ QSize s( resizeTitle( m_dvd[info.title-1].videoStream(), m_w->selectedPictureSize() ) );
+ f.append( QString("%1x%2").arg(s.width()).arg(s.height()) );
+ break;
+ }
+ case PATTERN_ASPECT_RATIO:
+ if( title.videoStream().displayAspectRatio() == K3bVideoDVD::VIDEO_ASPECT_RATIO_4_3 )
+ f.append( "4:3" );
+ else
+ f.append( "16:9" );
+ break;
+ case PATTERN_CURRENT_DATE:
+ f.append( KGlobal::locale()->formatDate( QDate::currentDate() ) );
+ break;
+ default:
+ f.append( pattern[i-1] );
+ f.append( pattern[i] );
+ }
+ }
+
+ //
+ // normal character -> just append to filename
+ //
+ else {
+ f.append( pattern[i] );
+ }
+ }
+
+ //
+ // and the extension (for now only avi)
+ //
+ f.append( ".avi" );
+
+ return f;
+}
+
+
+void K3bVideoDVDRippingDialog::loadK3bDefaults()
+{
+ m_w->m_spinVideoBitrate->setValue( 1800 );
+ m_w->m_checkTwoPassEncoding->setChecked( true );
+ m_w->m_checkAudioResampling->setChecked( false );
+ m_w->m_checkAutoClipping->setChecked( false );
+ m_w->m_checkLowPriority->setChecked( true );
+ m_w->m_checkAudioVBR->setChecked( true );
+ m_w->setSelectedAudioBitrate( 128 );
+ m_w->setSelectedVideoCodec( K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_FFMPEG_MPEG4 );
+ m_w->setSelectedAudioCodec( K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3 );
+ m_w->m_checkBlankReplace->setChecked( false );
+ m_w->m_editBlankReplace->setText( "_" );
+ m_w->m_comboFilenamePattern->setEditText( m_w->m_comboFilenamePattern->text(0) );
+ m_w->m_editBaseDir->setURL( K3b::defaultTempPath() );
+}
+
+
+void K3bVideoDVDRippingDialog::loadUserDefaults( KConfigBase* c )
+{
+ m_w->m_spinVideoBitrate->setValue( c->readNumEntry( "video bitrate", 1200 ) );
+ m_w->m_checkTwoPassEncoding->setChecked( c->readBoolEntry( "two pass encoding", true ) );
+ m_w->m_checkAudioResampling->setChecked( c->readBoolEntry( "audio resampling", false ) );
+ m_w->m_checkAutoClipping->setChecked( c->readBoolEntry( "auto clipping", false ) );
+ m_w->m_checkLowPriority->setChecked( c->readBoolEntry( "low priority", true ) );
+ m_w->m_checkAudioVBR->setChecked( c->readBoolEntry( "vbr audio", true ) );
+ m_w->setSelectedAudioBitrate( c->readNumEntry( "audio bitrate", 128 ) );
+ m_w->setSelectedVideoCodec( videoCodecFromId( c->readEntry( "video codec", videoCodecId( K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_FFMPEG_MPEG4 ) ) ) );
+ m_w->setSelectedAudioCodec( audioCodecFromId( c->readEntry( "audio codec", audioCodecId( K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3 ) ) ) );
+ m_w->m_checkBlankReplace->setChecked( c->readBoolEntry( "replace blanks", false ) );
+ m_w->m_editBlankReplace->setText( c->readEntry( "blank replace string", "_" ) );
+ m_w->m_comboFilenamePattern->setEditText( c->readEntry( "filename pattern", m_w->m_comboFilenamePattern->text(0) ) );
+ m_w->m_editBaseDir->setURL( c->readPathEntry( "base dir", K3b::defaultTempPath() ) );
+}
+
+
+void K3bVideoDVDRippingDialog::saveUserDefaults( KConfigBase* c )
+{
+ c->writeEntry( "video bitrate", m_w->m_spinVideoBitrate->value() );
+ c->writeEntry( "two pass encoding", m_w->m_checkTwoPassEncoding->isChecked() );
+ c->writeEntry( "audio resampling", m_w->m_checkAudioResampling->isChecked() );
+ c->writeEntry( "auto clipping", m_w->m_checkAutoClipping->isChecked() );
+ c->writeEntry( "low priority", m_w->m_checkLowPriority->isChecked() );
+ c->writeEntry( "vbr audio", m_w->m_checkAudioVBR->isChecked() );
+ c->writeEntry( "audio bitrate", m_w->selectedAudioBitrate() );
+ c->writeEntry( "video codec", videoCodecId( m_w->selectedVideoCodec() ) );
+ c->writeEntry( "audio codec", audioCodecId( m_w->selectedAudioCodec() ) );
+ c->writeEntry( "replace blanks", m_w->m_checkBlankReplace->isChecked() );
+ c->writeEntry( "blank replace string", m_w->m_editBlankReplace->text() );
+ c->writeEntry( "filename pattern", m_w->m_comboFilenamePattern->currentText() );
+ c->writePathEntry( "base dir", m_w->m_editBaseDir->url() );
+}
+
+
+void K3bVideoDVDRippingDialog::slotStartClicked()
+{
+ //
+ // check if the selected audio codec is usable for all selected audio streams
+ // We can only use the AC3 pass-through mode for AC3 streams
+ //
+ if( m_w->selectedAudioCodec() == K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH ) {
+ for( QMap<QCheckListItem*, K3bVideoDVDRippingJob::TitleRipInfo>::iterator it = m_titleRipInfos.begin();
+ it != m_titleRipInfos.end(); ++it ) {
+ if( m_dvd[it.data().title-1].numAudioStreams() > 0 &&
+ m_dvd[it.data().title-1].audioStream(it.data().audioStream).format() != K3bVideoDVD::AUDIO_FORMAT_AC3 ) {
+ KMessageBox::sorry( this, i18n("<p>When using the <em>AC3 pass-through</em> audio codec all selected audio "
+ "streams need to be in AC3 format. Please select another audio codec or "
+ "choose AC3 audio streams for all ripped titles."),
+ i18n("AC3 Pass-through") );
+ return;
+ }
+ }
+ }
+
+ // check if we need to overwrite some files...
+ QStringList filesToOverwrite;
+ for( QMap<QCheckListItem*, K3bVideoDVDRippingJob::TitleRipInfo>::iterator it = m_titleRipInfos.begin();
+ it != m_titleRipInfos.end(); ++it ) {
+ if( QFile::exists( it.data().filename ) )
+ filesToOverwrite.append( it.data().filename );
+ }
+
+ if( !filesToOverwrite.isEmpty() )
+ if( KMessageBox::questionYesNoList( this,
+ i18n("Do you want to overwrite these files?"),
+ filesToOverwrite,
+ i18n("Files Exist"), i18n("Overwrite"), KStdGuiItem::cancel() ) == KMessageBox::No )
+ return;
+
+
+ QSize videoSize = m_w->selectedPictureSize();
+ int i = 0;
+ QValueVector<K3bVideoDVDRippingJob::TitleRipInfo> titles( m_titleRipInfos.count() );
+ for( QMapConstIterator<QCheckListItem*, K3bVideoDVDRippingJob::TitleRipInfo> it = m_titleRipInfos.begin();
+ it != m_titleRipInfos.end(); ++it ) {
+ titles[i] = it.data();
+ titles[i].videoBitrate = 0; // use the global bitrate set below
+ titles[i].width = videoSize.width();
+ titles[i].height = videoSize.height();
+ ++i;
+ }
+
+ // sort the titles which come from a map and are thus not sorted properly
+ // simple bubble sort for these small arrays is sufficient
+ for( unsigned int i = 0; i < titles.count(); ++i ) {
+ for( unsigned int j = i+1; j < titles.count(); ++j ) {
+ if( titles[i].title > titles[j].title ) {
+ K3bVideoDVDRippingJob::TitleRipInfo tmp = titles[i];
+ titles[i] = titles[j];
+ titles[j] = tmp;
+ }
+ }
+ }
+
+ // start the job
+ K3bJobProgressDialog dlg( parentWidget() );
+ K3bVideoDVDRippingJob* job = new K3bVideoDVDRippingJob( &dlg, &dlg );
+ job->setVideoDVD( m_dvd );
+ job->setTitles( titles );
+
+ job->setVideoBitrate( m_w->m_spinVideoBitrate->value() );
+ job->setTwoPassEncoding( m_w->m_checkTwoPassEncoding->isChecked() );
+ job->setResampleAudioTo44100( m_w->m_checkAudioResampling->isChecked() );
+ job->setAutoClipping( m_w->m_checkAutoClipping->isChecked() );
+ job->setVideoCodec( m_w->selectedVideoCodec() );
+ job->setAudioCodec( m_w->selectedAudioCodec() );
+ job->setLowPriority( m_w->m_checkLowPriority->isChecked() );
+ job->setAudioBitrate( m_w->selectedAudioBitrate() );
+ job->setAudioVBR( m_w->m_checkAudioVBR->isChecked() );
+
+ hide();
+ dlg.startJob( job );
+ close();
+}
+
+#include "k3bvideodvdrippingdialog.moc"
diff --git a/src/rip/videodvd/k3bvideodvdrippingdialog.h b/src/rip/videodvd/k3bvideodvdrippingdialog.h
new file mode 100644
index 0000000..1acad53
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingdialog.h
@@ -0,0 +1,82 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_VIDEODVD_RIPPING_DIALOG_H_
+#define _K3B_VIDEODVD_RIPPING_DIALOG_H_
+
+#include <k3binteractiondialog.h>
+#include <k3bvideodvd.h>
+#include "k3bvideodvdrippingjob.h"
+
+#include <qvaluelist.h>
+#include <qmap.h>
+
+
+class K3bVideoDVDRippingWidget;
+class QCheckListItem;
+
+class K3bVideoDVDRippingDialog : public K3bInteractionDialog
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDVDRippingDialog( const K3bVideoDVD::VideoDVD& dvd,
+ const QValueList<int>& titles,
+ QWidget *parent = 0, const char *name = 0 );
+ ~K3bVideoDVDRippingDialog();
+
+ void setBaseDir( const QString& path );
+
+ enum FileNamingPattern {
+ PATTERN_TITLE_NUMBER = 't',
+ PATTERN_VOLUME_ID = 'i',
+ PATTERN_BEAUTIFIED_VOLUME_ID = 'b',
+ PATTERN_LANGUAGE_CODE = 'l',
+ PATTERN_LANGUAGE_NAME = 'n',
+ PATTERN_AUDIO_FORMAT = 'a',
+ PATTERN_AUDIO_CHANNELS = 'c',
+ PATTERN_ORIG_VIDEO_SIZE = 'v',
+ PATTERN_VIDEO_SIZE = 's',
+ PATTERN_ASPECT_RATIO = 'r',
+ PATTERN_CURRENT_DATE = 'd'
+ };
+
+ private slots:
+ void slotStartClicked();
+ void slotUpdateFilenames();
+ void slotUpdateFilesizes();
+ void slotUpdateVideoSizes();
+
+ private:
+ void populateTitleView( const QValueList<int>& titles );
+
+ QString createFilename( const K3bVideoDVDRippingJob::TitleRipInfo& info, const QString& pattern ) const;
+
+ void loadK3bDefaults();
+ void loadUserDefaults( KConfigBase* );
+ void saveUserDefaults( KConfigBase* );
+
+ K3bVideoDVDRippingWidget* m_w;
+
+ K3bVideoDVD::VideoDVD m_dvd;
+ QMap<QCheckListItem*, K3bVideoDVDRippingJob::TitleRipInfo> m_titleRipInfos;
+
+ class AudioStreamViewItem;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/rip/videodvd/k3bvideodvdrippingjob.cpp b/src/rip/videodvd/k3bvideodvdrippingjob.cpp
new file mode 100644
index 0000000..c10c127
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingjob.cpp
@@ -0,0 +1,385 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdrippingjob.h"
+
+#include <k3bvideodvdtitletranscodingjob.h>
+#include <k3bvideodvdtitledetectclippingjob.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+
+K3bVideoDVDRippingJob::TitleRipInfo::TitleRipInfo()
+ : title(1),
+ audioStream(0),
+ width(0),
+ height(0),
+ videoBitrate(0),
+ clipTop(0),
+ clipLeft(0),
+ clipBottom(0),
+ clipRight(0)
+{
+}
+
+
+K3bVideoDVDRippingJob::TitleRipInfo::TitleRipInfo( int _title,
+ int _audioStream,
+ const QString& fn,
+ int _width,
+ int _height,
+ int _videoBitrate,
+ int _clipTop,
+ int _clipLeft,
+ int _clipBottom,
+ int _clipRight )
+ : title(_title),
+ audioStream(_audioStream),
+ filename(fn),
+ width(_width),
+ height(_height),
+ videoBitrate(_videoBitrate),
+ clipTop(_clipTop),
+ clipLeft(_clipLeft),
+ clipBottom(_clipBottom),
+ clipRight(_clipRight)
+{
+}
+
+
+
+class K3bVideoDVDRippingJob::Private {
+public:
+ Private()
+ : autoClipping( true ) {
+ }
+
+ unsigned int currentTitleInfoIndex;
+ bool autoClipping;
+
+ bool canceled;
+
+ int videoBitrate;
+
+ int failedTitles;
+
+ QValueVector<double> titleProgressParts;
+ QValueVector<double> titleClippingProgressParts;
+};
+
+
+
+K3bVideoDVDRippingJob::K3bVideoDVDRippingJob( K3bJobHandler* hdl, QObject* parent )
+ : K3bJob( hdl, parent )
+{
+ d = new Private();
+
+ m_transcodingJob = new K3bVideoDVDTitleTranscodingJob( this, this );
+ connectSubJob( m_transcodingJob,
+ SLOT(slotTranscodingJobFinished(bool)),
+ SIGNAL(newTask(const QString&)),
+ SIGNAL(newSubTask(const QString&)),
+ SLOT(slotTranscodingProgress(int)),
+ SIGNAL(subPercent(int)),
+ 0,
+ 0 );
+ m_detectClippingJob = 0;
+}
+
+
+K3bVideoDVDRippingJob::~K3bVideoDVDRippingJob()
+{
+ delete d;
+}
+
+
+QString K3bVideoDVDRippingJob::jobDescription() const
+{
+ return i18n("Ripping Video DVD Titles");
+}
+
+
+QString K3bVideoDVDRippingJob::jobDetails() const
+{
+ return i18n("Transcoding %n title to %1/%2", "Transcoding %n titles to %1/%2", m_titleRipInfos.count() )
+ .arg( K3bVideoDVDTitleTranscodingJob::videoCodecString( m_transcodingJob->videoCodec() ) )
+ .arg( K3bVideoDVDTitleTranscodingJob::audioCodecString( m_transcodingJob->audioCodec() ) );
+}
+
+
+void K3bVideoDVDRippingJob::start()
+{
+ jobStarted();
+ d->canceled = false;
+ d->failedTitles = 0;
+
+ initProgressInfo();
+
+ if( d->autoClipping )
+ startDetectClipping( 0 );
+ else
+ startTranscoding( 0 );
+}
+
+
+void K3bVideoDVDRippingJob::slotTranscodingJobFinished( bool success )
+{
+ if( d->canceled ) {
+ emit canceled();
+ jobFinished( false );
+ }
+ else {
+ if( success )
+ emit infoMessage( i18n("Successfully ripped title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), SUCCESS );
+ else {
+ d->failedTitles++;
+ emit infoMessage( i18n("Failed to rip title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), ERROR );
+ }
+
+ ++d->currentTitleInfoIndex ;
+ if( d->currentTitleInfoIndex < m_titleRipInfos.count() ) {
+ if( d->autoClipping )
+ startDetectClipping( d->currentTitleInfoIndex );
+ else
+ startTranscoding( d->currentTitleInfoIndex );
+ }
+ else {
+ jobFinished( d->failedTitles == 0 );
+ }
+ }
+}
+
+
+void K3bVideoDVDRippingJob::slotDetectClippingJobFinished( bool success )
+{
+ if( d->canceled ) {
+ emit canceled();
+ jobFinished( false );
+ }
+ else {
+ m_titleRipInfos[d->currentTitleInfoIndex].clipTop = 0;
+ m_titleRipInfos[d->currentTitleInfoIndex].clipLeft = 0;
+ m_titleRipInfos[d->currentTitleInfoIndex].clipBottom = 0;
+ m_titleRipInfos[d->currentTitleInfoIndex].clipRight = 0;
+
+ if( success ) {
+ emit infoMessage( i18n("Determined clipping values for title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), SUCCESS );
+ emit infoMessage( i18n("Top: %1, Bottom: %2")
+ .arg(m_detectClippingJob->clippingTop()).arg(m_detectClippingJob->clippingBottom()), INFO );
+ emit infoMessage( i18n("Left: %1, Right: %2")
+ .arg(m_detectClippingJob->clippingLeft()).arg(m_detectClippingJob->clippingRight()), INFO );
+
+ // let's see if the clipping values make sense
+ if( m_detectClippingJob->clippingTop() + m_detectClippingJob->clippingBottom()
+ >= (int)m_dvd[d->currentTitleInfoIndex].videoStream().pictureHeight() ||
+ m_detectClippingJob->clippingLeft() + m_detectClippingJob->clippingRight()
+ >= (int)m_dvd[d->currentTitleInfoIndex].videoStream().pictureWidth() ) {
+ emit infoMessage( i18n("Insane clipping values. No clipping will be done at all."), WARNING );
+ }
+ else {
+ m_titleRipInfos[d->currentTitleInfoIndex].clipTop = m_detectClippingJob->clippingTop();
+ m_titleRipInfos[d->currentTitleInfoIndex].clipLeft = m_detectClippingJob->clippingLeft();
+ m_titleRipInfos[d->currentTitleInfoIndex].clipBottom = m_detectClippingJob->clippingBottom();
+ m_titleRipInfos[d->currentTitleInfoIndex].clipRight = m_detectClippingJob->clippingRight();
+ }
+ }
+ else
+ emit infoMessage( i18n("Failed to determine clipping values for title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), ERROR );
+
+ startTranscoding( d->currentTitleInfoIndex );
+ }
+}
+
+
+void K3bVideoDVDRippingJob::startTranscoding( int ripInfoIndex )
+{
+ d->currentTitleInfoIndex = ripInfoIndex;
+
+ m_transcodingJob->setVideoDVD( m_dvd );
+ m_transcodingJob->setTitle( m_titleRipInfos[ripInfoIndex].title );
+ m_transcodingJob->setAudioStream( m_titleRipInfos[ripInfoIndex].audioStream );
+ m_transcodingJob->setClipping( m_titleRipInfos[ripInfoIndex].clipTop,
+ m_titleRipInfos[ripInfoIndex].clipLeft,
+ m_titleRipInfos[ripInfoIndex].clipBottom,
+ m_titleRipInfos[ripInfoIndex].clipRight );
+ m_transcodingJob->setSize( m_titleRipInfos[ripInfoIndex].width, m_titleRipInfos[ripInfoIndex].height );
+ m_transcodingJob->setFilename( m_titleRipInfos[ripInfoIndex].filename );
+
+ if( m_titleRipInfos[ripInfoIndex].videoBitrate > 0 )
+ m_transcodingJob->setVideoBitrate( m_titleRipInfos[ripInfoIndex].videoBitrate );
+ else
+ m_transcodingJob->setVideoBitrate( d->videoBitrate );
+
+ m_transcodingJob->start();
+}
+
+
+void K3bVideoDVDRippingJob::startDetectClipping( int ripInfoIndex )
+{
+ d->currentTitleInfoIndex = ripInfoIndex;
+
+ if( !m_detectClippingJob ) {
+ m_detectClippingJob = new K3bVideoDVDTitleDetectClippingJob( this, this );
+ connectSubJob( m_detectClippingJob,
+ SLOT(slotDetectClippingJobFinished(bool)),
+ SIGNAL(newTask(const QString&)),
+ SIGNAL(newSubTask(const QString&)),
+ SLOT(slotDetectClippingProgress(int)),
+ SIGNAL(subPercent(int)),
+ 0,
+ 0 );
+ }
+
+ m_detectClippingJob->setVideoDVD( m_dvd );
+ m_detectClippingJob->setTitle( m_titleRipInfos[ripInfoIndex].title );
+ m_detectClippingJob->setLowPriority( m_transcodingJob->lowPriority() );
+
+ m_detectClippingJob->start();
+}
+
+
+void K3bVideoDVDRippingJob::slotTranscodingProgress( int p )
+{
+ // calculate the part already done
+ double doneParts = 0.0;
+ for( unsigned int i = 0; i < d->currentTitleInfoIndex; ++i ) {
+ doneParts += d->titleProgressParts[i];
+ if( d->autoClipping )
+ doneParts += d->titleClippingProgressParts[i];
+ }
+ if( d->autoClipping )
+ doneParts += d->titleClippingProgressParts[d->currentTitleInfoIndex];
+
+ // and the current thing
+ doneParts += (double)p/100.0*d->titleProgressParts[d->currentTitleInfoIndex];
+
+ emit percent( (int)( 100.0*doneParts ) );
+}
+
+
+void K3bVideoDVDRippingJob::slotDetectClippingProgress( int p )
+{
+ // calculate the part already done
+ double doneParts = 0.0;
+ for( unsigned int i = 0; i < d->currentTitleInfoIndex; ++i ) {
+ doneParts += d->titleProgressParts[i];
+ doneParts += d->titleClippingProgressParts[i];
+ }
+
+ // and the current thing
+ doneParts += (double)p/100.0*d->titleClippingProgressParts[d->currentTitleInfoIndex];
+
+ emit percent( (int)( 100.0*doneParts ) );
+}
+
+
+void K3bVideoDVDRippingJob::cancel()
+{
+ d->canceled = true;
+ if( m_transcodingJob->active() )
+ m_transcodingJob->cancel();
+ else if( m_detectClippingJob && m_detectClippingJob->active() )
+ m_detectClippingJob->cancel();
+}
+
+
+void K3bVideoDVDRippingJob::setVideoCodec( K3bVideoDVDTitleTranscodingJob::VideoCodec codec )
+{
+ m_transcodingJob->setVideoCodec( codec );
+}
+
+
+void K3bVideoDVDRippingJob::setVideoBitrate( int bitrate )
+{
+ d->videoBitrate = bitrate;
+}
+
+
+void K3bVideoDVDRippingJob::setTwoPassEncoding( bool b )
+{
+ m_transcodingJob->setTwoPassEncoding( b );
+}
+
+
+void K3bVideoDVDRippingJob::setAudioCodec( K3bVideoDVDTitleTranscodingJob::AudioCodec codec )
+{
+ m_transcodingJob->setAudioCodec( codec );
+}
+
+
+void K3bVideoDVDRippingJob::setAudioBitrate( int bitrate )
+{
+ m_transcodingJob->setAudioBitrate( bitrate );
+}
+
+
+void K3bVideoDVDRippingJob::setAudioVBR( bool vbr )
+{
+ m_transcodingJob->setAudioVBR( vbr );
+}
+
+
+void K3bVideoDVDRippingJob::setResampleAudioTo44100( bool b )
+{
+ m_transcodingJob->setResampleAudioTo44100( b );
+}
+
+
+void K3bVideoDVDRippingJob::setLowPriority( bool b )
+{
+ m_transcodingJob->setLowPriority( b );
+}
+
+
+void K3bVideoDVDRippingJob::setAutoClipping( bool b )
+{
+ d->autoClipping = b;
+}
+
+
+void K3bVideoDVDRippingJob::initProgressInfo()
+{
+ d->titleProgressParts.resize( m_titleRipInfos.count() );
+ d->titleClippingProgressParts.resize( m_titleRipInfos.count() );
+
+ unsigned long long totalFrames = 0ULL;
+ for( unsigned int i = 0; i < m_titleRipInfos.count(); ++i ) {
+ if( m_transcodingJob->twoPassEncoding() )
+ totalFrames += m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames() * 2;
+ else
+ totalFrames += m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames();
+
+ // using my knowledge of the internals of the clipping detection job: it decodes 200 frames
+ // of every chapter
+ if( d->autoClipping )
+ totalFrames += m_dvd[m_titleRipInfos[i].title-1].numChapters() * 200;
+ }
+
+ for( unsigned int i = 0; i < m_titleRipInfos.count(); ++i ) {
+ unsigned long long titleFrames = m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames();
+ if( m_transcodingJob->twoPassEncoding() )
+ titleFrames *= 2;
+
+ // using my knowledge of the internals of the clipping detection job: it decodes 200 frames
+ // of every chapter
+ unsigned long long titleClippingFrames = m_dvd[m_titleRipInfos[i].title-1].numChapters() * 200;
+
+ d->titleProgressParts[i] = (double)titleFrames/(double)totalFrames;
+ d->titleClippingProgressParts[i] = (double)titleClippingFrames/(double)totalFrames;
+ }
+}
+
+#include "k3bvideodvdrippingjob.moc"
diff --git a/src/rip/videodvd/k3bvideodvdrippingjob.h b/src/rip/videodvd/k3bvideodvdrippingjob.h
new file mode 100644
index 0000000..7c9f4d2
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingjob.h
@@ -0,0 +1,106 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_VIDEODVD_RIPPING_JOB_H_
+#define _K3B_VIDEODVD_RIPPING_JOB_H_
+
+#include <k3bjob.h>
+#include <k3bvideodvd.h>
+#include <k3bvideodvdtitletranscodingjob.h>
+
+#include <qvaluevector.h>
+
+
+class K3bVideoDVDTitleDetectClippingJob;
+
+
+/**
+ * For details on the options see K3bVideoDVDTitleTranscodingJob
+ */
+class K3bVideoDVDRippingJob : public K3bJob
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDVDRippingJob( K3bJobHandler* hdl, QObject* parent );
+ ~K3bVideoDVDRippingJob();
+
+ class TitleRipInfo {
+ public:
+ TitleRipInfo();
+ TitleRipInfo( int title,
+ int audioStream = 0,
+ const QString& fn = QString::null,
+ int width = 0, // 0 -> no resize
+ int height = 0, // 0 -> no resize
+ int videoBitrate = 0, // 0 -> use default from job settings
+ int clipTop = 0,
+ int clipLeft = 0,
+ int clipBottom = 0,
+ int clipRight = 0 );
+ int title;
+ int audioStream;
+ QString filename;
+ int width;
+ int height;
+ int videoBitrate;
+ int clipTop;
+ int clipLeft;
+ int clipBottom;
+ int clipRight;
+ };
+
+ QString jobDescription() const;
+ QString jobDetails() const;
+
+ public slots:
+ void start();
+ void cancel();
+
+ void setVideoDVD( const K3bVideoDVD::VideoDVD& dvd ) { m_dvd = dvd; }
+ void setTitles( const QValueVector<TitleRipInfo>& titles ) { m_titleRipInfos = titles; }
+
+ void setVideoCodec( K3bVideoDVDTitleTranscodingJob::VideoCodec codec );
+ void setVideoBitrate( int bitrate );
+ void setTwoPassEncoding( bool b );
+ void setAudioCodec( K3bVideoDVDTitleTranscodingJob::AudioCodec codec );
+ void setAudioBitrate( int bitrate );
+ void setAudioVBR( bool vbr );
+ void setResampleAudioTo44100( bool b );
+ void setLowPriority( bool b );
+ void setAutoClipping( bool b );
+
+ private slots:
+ void slotTranscodingJobFinished( bool );
+ void slotDetectClippingJobFinished( bool );
+ void slotTranscodingProgress( int );
+ void slotDetectClippingProgress( int );
+
+ private:
+ void startTranscoding( int ripInfoIndex );
+ void startDetectClipping( int ripInfoIndex );
+ void initProgressInfo();
+
+ K3bVideoDVD::VideoDVD m_dvd;
+ QValueVector<TitleRipInfo> m_titleRipInfos;
+
+ K3bVideoDVDTitleTranscodingJob* m_transcodingJob;
+ K3bVideoDVDTitleDetectClippingJob* m_detectClippingJob;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/src/rip/videodvd/k3bvideodvdrippingpreview.cpp b/src/rip/videodvd/k3bvideodvdrippingpreview.cpp
new file mode 100644
index 0000000..3ba7582
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingpreview.cpp
@@ -0,0 +1,135 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdrippingpreview.h"
+
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bdevice.h>
+
+#include <kprocess.h>
+#include <ktempdir.h>
+#include <kdebug.h>
+
+#include <qdir.h>
+
+
+
+K3bVideoDVDRippingPreview::K3bVideoDVDRippingPreview( QObject* parent )
+ : QObject( parent ),
+ m_tempDir( 0 ),
+ m_process( 0 )
+{
+}
+
+
+K3bVideoDVDRippingPreview::~K3bVideoDVDRippingPreview()
+{
+ delete m_process;
+ delete m_tempDir;
+}
+
+
+void K3bVideoDVDRippingPreview::generatePreview( const K3bVideoDVD::VideoDVD& dvd, int title, int chapter )
+{
+ // cleanup first
+ delete m_process;
+ delete m_tempDir;
+ m_process = 0;
+ m_tempDir = 0;
+ m_canceled = false;
+
+ const K3bExternalBin* bin = k3bcore->externalBinManager()->binObject("transcode");
+ if( !bin ) {
+ emit previewDone( false );
+ return;
+ }
+
+ // auto-select a chapter
+ // choose the center chapter, but not the first or last if possible
+ if( chapter == 0 )
+ chapter = QMIN( QMAX( dvd[title-1].numChapters()/2, 2 ), QMAX( dvd[title-1].numChapters() - 1, 1 ) );
+
+ // select a frame number
+ unsigned int frame = 30;
+ if( dvd[title-1][chapter-1].playbackTime().totalFrames() < frame )
+ frame = dvd[title-1][chapter-1].playbackTime().totalFrames() / 2;
+
+ m_dvd = dvd;
+ m_title = title;
+ m_chapter = chapter;
+
+ m_tempDir = new KTempDir();
+ m_tempDir->setAutoDelete( true );
+
+ m_process = new KProcess();
+ *m_process << bin->path;
+ *m_process << "-i" << dvd.device()->blockDeviceName();
+ *m_process << "-T" << QString("%1,%2").arg(title).arg(chapter);
+ *m_process << "-x" << "dvd,null";
+ *m_process << "--dvd_access_delay" << "0";
+ *m_process << "-y" << "ppm,null";
+ *m_process << "-c" << QString("%1-%2").arg( frame ).arg( frame+1 );
+ *m_process << "-Z" << "x200";
+ *m_process << "-o" << m_tempDir->name();
+
+ connect( m_process, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotTranscodeFinished(KProcess*)) );
+ if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { // we use AllOutput to not pollute stdout
+ // something went wrong when starting the program
+ // it "should" be the executable
+ kdDebug() << "(K3bVideoDVDRippingPreview) Could not start transcode." << endl;
+ delete m_process;
+ delete m_tempDir;
+ m_process = 0;
+ m_tempDir = 0;
+ emit previewDone( false );
+ }
+}
+
+
+void K3bVideoDVDRippingPreview::cancel()
+{
+ if( m_process && m_process->isRunning() ) {
+ m_canceled = true;
+ m_process->kill();
+ }
+}
+
+
+void K3bVideoDVDRippingPreview::slotTranscodeFinished( KProcess* )
+{
+ // read the image
+ QString filename = m_tempDir->name() + "000000.ppm";// + tempQDir->entryList( QDir::Files ).first();
+ kdDebug() << "(K3bVideoDVDRippingPreview) reading from file " << filename << endl;
+ m_preview = QImage( filename );
+ bool success = !m_preview.isNull() && !m_canceled;
+
+ // remove temp files
+ delete m_tempDir;
+ m_tempDir = 0;
+
+ // clean up
+ delete m_process;
+ m_process = 0;
+
+ // retry the first chapter in case another failed
+ if( !success && m_chapter > 1 )
+ generatePreview( m_dvd, m_title, 1 );
+ else
+ emit previewDone( success );
+}
+
+#include "k3bvideodvdrippingpreview.moc"
diff --git a/src/rip/videodvd/k3bvideodvdrippingpreview.h b/src/rip/videodvd/k3bvideodvdrippingpreview.h
new file mode 100644
index 0000000..f5beb69
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingpreview.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_VIDEODVD_RIPPING_PREVIEW_H_
+#define _K3B_VIDEODVD_RIPPING_PREVIEW_H_
+
+#include <qobject.h>
+#include <qimage.h>
+
+#include <k3bvideodvd.h>
+
+
+class KTempDir;
+class KProcess;
+
+class K3bVideoDVDRippingPreview : public QObject
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDVDRippingPreview( QObject* parent = 0 );
+ ~K3bVideoDVDRippingPreview();
+
+ const QImage& preview() const { return m_preview; }
+
+ public slots:
+ /**
+ * \param dvd The Video DVD object
+ * \param title The Video DVD title to generate the preview for
+ * \param chapter The Chapter number to use for the preview.
+ * If 0 the middle of the title is used.
+ */
+ void generatePreview( const K3bVideoDVD::VideoDVD& dvd, int title, int chapter = 0 );
+
+ void cancel();
+
+ signals:
+ void previewDone( bool );
+
+ private slots:
+ void slotTranscodeFinished( KProcess* );
+
+ private:
+ QImage m_preview;
+ KTempDir* m_tempDir;
+ KProcess* m_process;
+ int m_title;
+ int m_chapter;
+ K3bVideoDVD::VideoDVD m_dvd;
+
+ bool m_canceled;
+};
+
+#endif
diff --git a/src/rip/videodvd/k3bvideodvdrippingtitlelistview.cpp b/src/rip/videodvd/k3bvideodvdrippingtitlelistview.cpp
new file mode 100644
index 0000000..85379dc
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingtitlelistview.cpp
@@ -0,0 +1,410 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdrippingtitlelistview.h"
+#include "k3bvideodvdrippingpreview.h"
+
+#include <k3btooltip.h>
+#include <k3bapplication.h>
+#include <k3bmediacache.h>
+
+#include <k3bvideodvd.h>
+#include <k3bvideodvdaudiostream.h>
+#include <k3bvideodvdvideostream.h>
+#include <k3bvideodvdsubpicturestream.h>
+
+#include <qsimplerichtext.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+#include <qheader.h>
+#include <qtooltip.h>
+
+#include <klocale.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+
+static QString audioStreamString( const K3bVideoDVD::Title& title, unsigned int maxLines = 9999, bool includeExtInfo = true )
+{
+ QString s = "<p>";
+ for( unsigned int i = 0; i < QMIN( title.numAudioStreams(), maxLines ); ++i ) {
+ if( i > 0 )
+ s += "<br>";
+ s += QString::number(i+1) + ": "
+ + i18n("%1 %2Ch (%3<em>%4</em>)")
+ .arg( K3bVideoDVD::audioFormatString( title.audioStream(i).format() ) )
+ .arg( title.audioStream(i).channels() )
+ .arg( title.audioStream(i).langCode().isEmpty()
+ ? i18n("unknown language")
+ : KGlobal::locale()->twoAlphaToLanguageName( title.audioStream(i).langCode() ) )
+ .arg( includeExtInfo && title.audioStream(i).codeExtension() != K3bVideoDVD::AUDIO_CODE_EXT_UNSPECIFIED
+ ? QString(" ") + K3bVideoDVD::audioCodeExtensionString( title.audioStream(i).codeExtension() )
+ : QString::null );
+ }
+ if( title.numAudioStreams() > maxLines )
+ s += "...";
+
+ return s;
+}
+
+
+static QString subpictureStreamString( const K3bVideoDVD::Title& title, unsigned int maxLines = 9999, bool includeExtInfo = true )
+{
+ QString s = "<p>";
+ for( unsigned int i = 0; i < QMIN( title.numSubPictureStreams(), maxLines ); ++i ) {
+ if( i > 0 )
+ s += "<br>";
+ s += QString::number(i+1) + ": "
+ + QString("%1 (%2<em>%3</em>)")
+ .arg( title.subPictureStream(i).codeMode() == K3bVideoDVD::SUBPIC_CODE_MODE_RLE
+ ? i18n("RLE")
+ : i18n("Extended") )
+ .arg( title.subPictureStream(i).langCode().isEmpty()
+ ? i18n("unknown language")
+ : KGlobal::locale()->twoAlphaToLanguageName( title.subPictureStream(i).langCode() ) )
+ .arg( includeExtInfo && title.subPictureStream(i).codeExtension() != K3bVideoDVD::SUBPIC_CODE_EXT_UNSPECIFIED
+ ? QString(" ") + K3bVideoDVD::subPictureCodeExtensionString( title.subPictureStream(i).codeExtension() )
+ : QString::null );
+ }
+ if( title.numSubPictureStreams() > maxLines )
+ s += "...";
+
+ return s;
+}
+
+
+
+class K3bVideoDVDRippingTitleListView::TitleViewItem : public K3bCheckListViewItem
+{
+public:
+ TitleViewItem( K3bVideoDVDRippingTitleListView* parent, QListViewItem* after, const K3bVideoDVD::Title& title )
+ : K3bCheckListViewItem( parent, after ),
+ m_title( title ) {
+
+ setMarginVertical( 4 );
+ setMarginHorizontal( 1, 2 );
+ setMarginHorizontal( 2, 2 );
+ setMarginHorizontal( 3, 2 );
+ setMarginHorizontal( 4, 2 );
+ setMarginHorizontal( 5, 2 );
+ setChecked(true);
+
+ m_previewSet = false;
+ }
+
+ const K3bVideoDVD::Title& videoDVDTitle() const { return m_title; }
+
+ void setup() {
+ widthChanged();
+
+ // set a valid height
+ int maxH = 0;
+ for( int c = 1; c <= 4; ++c ) {
+ QSimpleRichText rt( text(c), listView()->font() );
+ rt.setWidth( 600 ); // way to big to avoid line breaks
+ maxH = QMAX( maxH, rt.height() );
+ }
+
+ setHeight( maxH + 2*marginVertical() );
+ }
+
+ int width( const QFontMetrics& fm, const QListView* lv, int c ) const {
+ if( c == 0 )
+ return K3bCheckListViewItem::width( fm, lv, c );
+ else {
+ QSimpleRichText rt( text(c), lv->font() );
+ rt.setWidth( 600 ); // way to big to avoid line breaks
+ return rt.widthUsed() + 2*marginHorizontal( c );
+ }
+ }
+
+ void setPreview( const QImage& preview ) {
+ m_preview = preview;
+ m_scaledPreview = QPixmap();
+
+ m_previewSet = true;
+
+ repaint();
+ }
+
+ const QImage& preview() const {
+ return m_preview;
+ }
+
+protected:
+ void paintK3bCell( QPainter* p, const QColorGroup& cg, int col, int w, int align ) {
+ p->save();
+
+ if( col == 0 ) {
+ // the check mark
+ K3bCheckListViewItem::paintK3bCell( p, cg, col, w, align );
+ }
+ else if( col == 2 ) {
+ if( isSelected() ) {
+ p->fillRect( 0, 0, w, height(),
+ cg.brush( QColorGroup::Highlight ) );
+ p->setPen( cg.highlightedText() );
+ }
+ else {
+ p->fillRect( 0, 0, w, height(), cg.base() );
+ p->setPen( cg.text() );
+ }
+
+ // draw the preview
+ int h = height();
+ h -= 2*marginVertical();
+ h -= 1; // the separator
+ if( !m_preview.isNull() ) {
+ if( m_scaledPreview.height() != h ) {
+ // recreate scaled preview
+ int preH = m_preview.height()*w/m_preview.width();
+ int preW = m_preview.width()*h/m_preview.height();
+ if( preH > h )
+ preH = m_preview.height()*preW/m_preview.width();
+ if( preW > w )
+ preW = m_preview.width()*preH/m_preview.height();
+ m_scaledPreview.convertFromImage( m_preview.smoothScale( preW, preH ), 0 );
+ }
+
+ // center the preview in the column
+ int yPos = ( height() - m_scaledPreview.height() ) / 2;
+ int xPos = ( w - m_scaledPreview.width() ) / 2;
+
+ p->drawPixmap( xPos, yPos, m_scaledPreview );
+ }
+ else if( m_previewSet ) {
+ int preW = 0;
+ if( m_title.videoStream().displayAspectRatio() == K3bVideoDVD::VIDEO_ASPECT_RATIO_4_3 )
+ preW = h*4/3;
+ else
+ preW = h*16/9;
+
+ p->drawRect( ( w - preW ) / 2, ( height() - h ) / 2, preW, h );
+ QPixmap noIcon = KApplication::kApplication()->iconLoader()->loadIcon( "no", KIcon::NoGroup, KIcon::SizeSmall, KIcon::DefaultState, 0, true );
+ p->drawPixmap( ( w - noIcon.width() ) / 2, ( height() - noIcon.height() ) / 2, noIcon );
+ }
+ else {
+ p->drawText( 0, 0, w, height(), Qt::AlignCenter, "..." );
+ }
+ }
+ else {
+ QString s = text( col );
+ if( s.isEmpty() )
+ K3bCheckListViewItem::paintK3bCell( p, cg, col, w, align );
+ else {
+ QColorGroup cg1( cg );
+ if( isSelected() ) {
+ p->fillRect( 0, 0, w, height(),
+ cg.brush( QColorGroup::Highlight ) );
+ cg1.setColor( QColorGroup::Text, cg.highlightedText() );
+ }
+ else {
+ p->fillRect( 0, 0, w, height(), cg.base() );
+ }
+
+ // paint using QSimpleRichText
+ QSimpleRichText rt( text(col), listView()->font() );
+ rt.setWidth( 600 ); // way to big to avoid line breaks
+ // normally we would have to clip the height to height()-2*marginVertical(). But if we do that
+ // some characters are cut (such as p or q). It seems as if QSimpleRichText does not properly
+ // calculate it's height...
+ rt.draw( p, 0, marginVertical(), QRect( 0, 0, w, height() ), cg1 );
+ }
+ }
+
+ // draw the separator
+ if( listView()->firstChild() != this ) {
+ p->translate( -1*marginHorizontal(col), 0 );
+ // FIXME: modify the value from palette().disabled().foreground() to be lighter (or darker, depending on the background color )
+ p->setPen( Qt::lightGray );
+ p->drawLine( 0, 0, w+2*marginHorizontal(col), 0 );
+ }
+
+ p->restore();
+ }
+
+private:
+ QString text( int col ) const {
+ switch( col ) {
+ case 1:
+ // Title X + length
+ return i18n("<p><b>Title %1 (%2)</b><br>"
+ "%3")
+ .arg( m_title.titleNumber(), 2 )
+ .arg( m_title.playbackTime().toString( false ) )
+ .arg( i18n("%n chapter", "%n chapters", m_title.numPTTs() ) );
+
+ case 3:
+ // video stream info
+ return QString("<p>%1 %2x%3<br>%4%5")
+ .arg( m_title.videoStream().mpegVersion() == 0 ? i18n("MPEG1") : i18n("MPEG2") )
+ .arg( m_title.videoStream().pictureWidth() )
+ .arg( m_title.videoStream().pictureHeight() )
+ .arg( m_title.videoStream().displayAspectRatio() == K3bVideoDVD::VIDEO_ASPECT_RATIO_4_3 ? "4:3" : "16:9" )
+ .arg( m_title.videoStream().letterboxed() ? QString(" - <em>") + i18n("letterboxed") + QString("</em>"):
+ m_title.videoStream().permittedDf() == K3bVideoDVD::VIDEO_PERMITTED_DF_LETTERBOXED
+ ? QString(" - <em>") + i18n("anamorph") + QString("</em>") : QString::null );
+
+ case 4:
+ // audio streams info
+ if( m_title.numAudioStreams() > 0 )
+ return audioStreamString( m_title, 2, false );
+ else
+ return "<p><small><em>" + i18n("No audio streams") + "</em>";
+
+ case 5:
+ // subpicture streams info
+ if( m_title.numSubPictureStreams() > 0 )
+ return subpictureStreamString( m_title, 2, false );
+ else
+ return "<p><small><em>" + i18n("No Subpicture streams") + "</em>";
+
+ default:
+ return K3bCheckListViewItem::text( col );
+ }
+ }
+
+ K3bVideoDVD::Title m_title;
+
+ bool m_previewSet;
+ QImage m_preview;
+ QPixmap m_scaledPreview;
+};
+
+
+class K3bVideoDVDRippingTitleListView::TitleToolTip : public K3bToolTip
+{
+public:
+ TitleToolTip( K3bVideoDVDRippingTitleListView* view )
+ : K3bToolTip( view->viewport() ),
+ m_view( view ) {
+ }
+
+ void maybeTip( const QPoint& pos ) {
+ TitleViewItem* item = static_cast<TitleViewItem*>( m_view->itemAt( pos ) );
+ QPoint contentsPos = m_view->viewportToContents( pos );
+ if( !item )
+ return;
+ int col = m_view->header()->sectionAt( contentsPos.x() );
+
+ QRect r = m_view->itemRect( item );
+ int headerPos = m_view->header()->sectionPos( col );
+ r.setLeft( headerPos );
+ r.setRight( headerPos + m_view->header()->sectionSize( col ) );
+
+ switch( col ) {
+ case 2:
+ if( !item->preview().isNull() ) {
+ QPixmap previewPix;
+ if( previewPix.convertFromImage( item->preview() ) )
+ tip( r, previewPix, 0 );
+ }
+ break;
+ case 4:
+ if( item->videoDVDTitle().numAudioStreams() > 0 )
+ tip( r, "<p><b>" + i18n("Audio Streams") + "</b><p>" + audioStreamString( item->videoDVDTitle() ), 0 );
+ break;
+ case 5:
+ if( item->videoDVDTitle().numSubPictureStreams() > 0 )
+ tip( r, "<p><b>" + i18n("Subpicture Streams") + "</b><p>" + subpictureStreamString( item->videoDVDTitle() ), 0 );
+ break;
+ }
+ }
+
+private:
+ K3bVideoDVDRippingTitleListView* m_view;
+};
+
+
+
+K3bVideoDVDRippingTitleListView::K3bVideoDVDRippingTitleListView( QWidget* parent )
+ : K3bListView( parent )
+{
+ setFullWidth(true);
+ setSorting(-1);
+ setAllColumnsShowFocus( true );
+ setSelectionModeExt( Single );
+
+ addColumn( "" );
+ addColumn( i18n("Title") );
+ addColumn( i18n("Preview") );
+ addColumn( i18n("Video") );
+ addColumn( i18n("Audio") );
+ addColumn( i18n("Subpicture") );
+
+ header()->setClickEnabled( false );
+ setColumnWidthMode( 0, QListView::Manual );
+ setColumnWidth( 0, 20 );
+ header()->setResizeEnabled( false, 0 );
+
+ m_toolTip = new TitleToolTip( this );
+
+ m_previewGen = new K3bVideoDVDRippingPreview( this );
+ connect( m_previewGen, SIGNAL(previewDone(bool)),
+ this, SLOT(slotPreviewDone(bool)) );
+}
+
+
+K3bVideoDVDRippingTitleListView::~K3bVideoDVDRippingTitleListView()
+{
+ delete m_toolTip;
+}
+
+
+void K3bVideoDVDRippingTitleListView::setVideoDVD( const K3bVideoDVD::VideoDVD& dvd )
+{
+ clear();
+
+ m_dvd = dvd;
+ m_medium = k3bappcore->mediaCache()->medium( m_dvd.device() );
+ m_itemMap.resize( dvd.numTitles() );
+
+ for( unsigned int i = 0; i < dvd.numTitles(); ++i )
+ m_itemMap[i] = new TitleViewItem( this, lastItem(), dvd.title(i) );
+
+ m_currentPreviewTitle = 1;
+ m_previewGen->generatePreview( m_dvd, 1 );
+}
+
+
+void K3bVideoDVDRippingTitleListView::slotPreviewDone( bool success )
+{
+ if( success )
+ m_itemMap[m_currentPreviewTitle-1]->setPreview( m_previewGen->preview() );
+ else
+ m_itemMap[m_currentPreviewTitle-1]->setPreview( QImage() );
+
+ // cancel if we got hidden or if the medium changed.
+ if( isVisible() && m_medium == k3bappcore->mediaCache()->medium( m_dvd.device() ) ) {
+ ++m_currentPreviewTitle;
+ if( m_currentPreviewTitle <= m_dvd.numTitles() )
+ m_previewGen->generatePreview( m_dvd, m_currentPreviewTitle );
+ }
+}
+
+
+void K3bVideoDVDRippingTitleListView::hideEvent( QHideEvent* e )
+{
+ //
+ // For now we do it the easy way: just stop the preview generation
+ // once this view is hidden
+ //
+ m_previewGen->cancel();
+
+ K3bListView::hideEvent( e );
+}
+
+#include "k3bvideodvdrippingtitlelistview.moc"
diff --git a/src/rip/videodvd/k3bvideodvdrippingtitlelistview.h b/src/rip/videodvd/k3bvideodvdrippingtitlelistview.h
new file mode 100644
index 0000000..7c21815
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingtitlelistview.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_VIDEODVD_RIPPING_TITLE_LISTVIEW_H_
+#define _K3B_VIDEODVD_RIPPING_TITLE_LISTVIEW_H_
+
+#include <k3blistview.h>
+#include <k3bvideodvd.h>
+#include <k3bmedium.h>
+
+#include <qvaluevector.h>
+
+
+class K3bVideoDVDRippingPreview;
+class QHideEvent;
+
+class K3bVideoDVDRippingTitleListView : public K3bListView
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDVDRippingTitleListView( QWidget* parent );
+ ~K3bVideoDVDRippingTitleListView();
+
+ void setVideoDVD( const K3bVideoDVD::VideoDVD& dvd );
+
+ private slots:
+ void slotPreviewDone( bool );
+
+ private:
+ void hideEvent( QHideEvent* );
+
+ class TitleViewItem;
+ class TitleToolTip;
+
+ TitleToolTip* m_toolTip;
+
+ QValueVector<TitleViewItem*> m_itemMap;
+ K3bVideoDVDRippingPreview* m_previewGen;
+ unsigned int m_currentPreviewTitle;
+
+ K3bVideoDVD::VideoDVD m_dvd;
+ K3bMedium m_medium;
+};
+
+#endif
diff --git a/src/rip/videodvd/k3bvideodvdrippingview.cpp b/src/rip/videodvd/k3bvideodvdrippingview.cpp
new file mode 100644
index 0000000..f6c8c8d
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingview.cpp
@@ -0,0 +1,256 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdrippingview.h"
+#include "k3bvideodvdrippingtitlelistview.h"
+#include "k3bvideodvdrippingdialog.h"
+
+#include <k3bvideodvd.h>
+#include <k3bvideodvdtitletranscodingjob.h>
+#include <k3btoolbox.h>
+#include <k3bthememanager.h>
+#include <k3bglobals.h>
+#include <k3blibdvdcss.h>
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+
+#include <qcursor.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kconfig.h>
+
+
+K3bVideoDVDRippingView::K3bVideoDVDRippingView( QWidget* parent, const char * name )
+ : K3bMediaContentsView( true,
+ K3bMedium::CONTENT_VIDEO_DVD,
+ K3bDevice::MEDIA_DVD_ALL,
+ K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_COMPLETE,
+ parent, name )
+{
+ QGridLayout* mainGrid = new QGridLayout( mainWidget() );
+
+ // toolbox
+ // ----------------------------------------------------------------------------------
+ QHBoxLayout* toolBoxLayout = new QHBoxLayout( 0, 0, 0, "toolBoxLayout" );
+ m_toolBox = new K3bToolBox( mainWidget() );
+ toolBoxLayout->addWidget( m_toolBox );
+ QSpacerItem* spacer = new QSpacerItem( 10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ toolBoxLayout->addItem( spacer );
+ m_labelLength = new QLabel( mainWidget() );
+ m_labelLength->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+ toolBoxLayout->addWidget( m_labelLength );
+
+
+ // the title view
+ // ----------------------------------------------------------------------------------
+ m_titleView = new K3bVideoDVDRippingTitleListView( mainWidget() );
+
+ connect( m_titleView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) );
+
+ // general layout
+ // ----------------------------------------------------------------------------------
+ mainGrid->addLayout( toolBoxLayout, 0, 0 );
+ mainGrid->addWidget( m_titleView, 1, 0 );
+
+
+ initActions();
+
+ m_toolBox->addButton( actionCollection()->action("start_rip"), true );
+
+ setLeftPixmap( K3bTheme::MEDIA_LEFT );
+ setRightPixmap( K3bTheme::MEDIA_VIDEO );
+}
+
+
+K3bVideoDVDRippingView::~K3bVideoDVDRippingView()
+{
+}
+
+
+void K3bVideoDVDRippingView::reloadMedium()
+{
+ //
+ // For VideoDVD reading it is important that the DVD is not mounted
+ //
+ if( K3b::isMounted( device() ) && !K3b::unmount( device() ) ) {
+ KMessageBox::error( this,
+ i18n("K3b was unable to unmount device '%1' containing medium '%2'. "
+ "Video DVD ripping will not work if the device is mounted. "
+ "Please unmount manually."),
+ i18n("Unmounting failed") );
+ }
+
+ //
+ // K3bVideoDVD::open does not necessarily fail on encrypted DVDs if dvdcss is not
+ // available. Thus, we test the availability of libdvdcss here
+ //
+ if( device()->copyrightProtectionSystemType() == 1 ) {
+ K3bLibDvdCss* css = K3bLibDvdCss::create();
+ if( !css ) {
+ KMessageBox::error( this, i18n("<p>Unable to read Video DVD contents: Found encrypted Video DVD."
+ "<p>Install <i>libdvdcss</i> to get Video DVD decryption support.") );
+ return;
+ }
+ else
+ delete css;
+ }
+
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+
+ if( m_dvd.open( device() ) ) {
+ setTitle( medium().beautifiedVolumeId() + " (" + i18n("Video DVD") + ")" );
+ m_labelLength->setText( i18n("%n title", "%n titles", m_dvd.numTitles() ) );
+ m_titleView->setVideoDVD( m_dvd );
+ QApplication::restoreOverrideCursor();
+
+ bool transcodeUsable = true;
+
+ if( !k3bcore ->externalBinManager() ->foundBin( "transcode" ) ) {
+ KMessageBox::sorry( this,
+ i18n("K3b uses transcode to rip Video DVDs. "
+ "Please make sure it is installed.") );
+ transcodeUsable = false;
+ }
+ else {
+ int vc = 0, ac = 0;
+ for( int i = 0; i < K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_NUM_ENTRIES; ++i )
+ if( K3bVideoDVDTitleTranscodingJob::transcodeBinaryHasSupportFor( (K3bVideoDVDTitleTranscodingJob::VideoCodec)i ) )
+ ++vc;
+ for( int i = 0; i < K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_NUM_ENTRIES; ++i )
+ if( K3bVideoDVDTitleTranscodingJob::transcodeBinaryHasSupportFor( (K3bVideoDVDTitleTranscodingJob::AudioCodec)i ) )
+ ++ac;
+ if( !ac || !vc ) {
+ KMessageBox::sorry( this,
+ i18n("<p>K3b uses transcode to rip Video DVDs. "
+ "Your installation of transcode (<em>%1</em>) lacks support for any of the "
+ "codecs supported by K3b."
+ "<p>Please make sure it is installed properly.") );
+ transcodeUsable = false;
+ }
+ }
+
+ actionCollection()->action("start_rip")->setEnabled( transcodeUsable );
+ }
+ else {
+ QApplication::restoreOverrideCursor();
+
+ KMessageBox::error( this, i18n("Unable to read Video DVD contents.") );
+ }
+}
+
+
+void K3bVideoDVDRippingView::slotStartRipping()
+{
+ QValueList<int> titles;
+ int i = 1;
+ for( QListViewItemIterator it( m_titleView ); *it; ++it, ++i )
+ if( static_cast<K3bCheckListViewItem*>( *it )->isChecked() )
+ titles.append( i );
+
+ if( titles.isEmpty() ) {
+ KMessageBox::error( this, i18n("Please select the titles to rip."),
+ i18n("No Titles Selected") );
+ }
+ else {
+ K3bVideoDVDRippingDialog dlg( m_dvd, titles, this );
+ dlg.exec();
+ }
+}
+
+
+void K3bVideoDVDRippingView::slotContextMenu( KListView*, QListViewItem*, const QPoint& p )
+{
+ m_popupMenu->popup(p);
+}
+
+
+void K3bVideoDVDRippingView::slotCheckAll()
+{
+ for( QListViewItemIterator it( m_titleView ); it.current(); ++it )
+ dynamic_cast<K3bCheckListViewItem*>(it.current())->setChecked(true);
+}
+
+
+void K3bVideoDVDRippingView::slotUncheckAll()
+{
+ for( QListViewItemIterator it( m_titleView ); it.current(); ++it )
+ dynamic_cast<K3bCheckListViewItem*>(it.current())->setChecked(false);
+}
+
+
+void K3bVideoDVDRippingView::slotCheck()
+{
+ QPtrList<QListViewItem> items( m_titleView->selectedItems() );
+ for( QPtrListIterator<QListViewItem> it( items );
+ it.current(); ++it )
+ dynamic_cast<K3bCheckListViewItem*>(it.current())->setChecked(true);
+}
+
+
+void K3bVideoDVDRippingView::slotUncheck()
+{
+ QPtrList<QListViewItem> items( m_titleView->selectedItems() );
+ for( QPtrListIterator<QListViewItem> it( items );
+ it.current(); ++it )
+ dynamic_cast<K3bCheckListViewItem*>(it.current())->setChecked(false);
+}
+
+
+void K3bVideoDVDRippingView::initActions()
+{
+ m_actionCollection = new KActionCollection( this );
+
+ KAction* actionSelectAll = new KAction( i18n("Check All"), 0, 0, this,
+ SLOT(slotCheckAll()), actionCollection(),
+ "check_all" );
+ KAction* actionDeselectAll = new KAction( i18n("Uncheck All"), 0, 0, this,
+ SLOT(slotUncheckAll()), actionCollection(),
+ "uncheck_all" );
+ KAction* actionSelect = new KAction( i18n("Check Track"), 0, 0, this,
+ SLOT(slotCheck()), actionCollection(),
+ "select_track" );
+ KAction* actionDeselect = new KAction( i18n("Uncheck Track"), 0, 0, this,
+ SLOT(slotUncheck()), actionCollection(),
+ "deselect_track" );
+ KAction* actionStartRip = new KAction( i18n("Start Ripping"), "gear", 0, this,
+ SLOT(slotStartRipping()), m_actionCollection, "start_rip" );
+
+ actionStartRip->setToolTip( i18n("Open the Video DVD ripping dialog") );
+
+ // setup the popup menu
+ m_popupMenu = new KActionMenu( actionCollection(), "popup_menu" );
+ KAction* separator = new KActionSeparator( actionCollection(), "separator" );
+ m_popupMenu->insert( actionSelect );
+ m_popupMenu->insert( actionDeselect );
+ m_popupMenu->insert( actionSelectAll );
+ m_popupMenu->insert( actionDeselectAll );
+ m_popupMenu->insert( separator );
+ m_popupMenu->insert( actionStartRip );
+}
+
+
+void K3bVideoDVDRippingView::enableInteraction( bool enable )
+{
+ actionCollection()->action( "start_rip" )->setEnabled( enable );
+}
+
+
+#include "k3bvideodvdrippingview.moc"
diff --git a/src/rip/videodvd/k3bvideodvdrippingview.h b/src/rip/videodvd/k3bvideodvdrippingview.h
new file mode 100644
index 0000000..679ea09
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingview.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_VIDEODVD_RIPPING_VIEW_H_
+#define _K3B_VIDEODVD_RIPPING_VIEW_H_
+
+#include <k3bmediacontentsview.h>
+#include <k3bmedium.h>
+#include <k3bvideodvd.h>
+
+class K3bVideoDVDRippingTitleListView;
+class K3bToolBox;
+class QLabel;
+class KActionCollection;
+class KActionMenu;
+class KListView;
+class QListViewItem;
+
+class K3bVideoDVDRippingView : public K3bMediaContentsView
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDVDRippingView( QWidget* parent = 0, const char * name = 0 );
+ ~K3bVideoDVDRippingView();
+
+ KActionCollection* actionCollection() const { return m_actionCollection; }
+
+ private slots:
+ void slotStartRipping();
+
+ void slotContextMenu( KListView*, QListViewItem*, const QPoint& );
+
+ void slotCheckAll();
+ void slotUncheckAll();
+ void slotCheck();
+ void slotUncheck();
+
+ private:
+ void reloadMedium();
+ void enableInteraction( bool enable );
+ void initActions();
+
+ KActionCollection* m_actionCollection;
+ KActionMenu* m_popupMenu;
+
+ K3bToolBox* m_toolBox;
+ QLabel* m_labelLength;
+ K3bVideoDVDRippingTitleListView* m_titleView;
+
+ K3bVideoDVD::VideoDVD m_dvd;
+};
+
+#endif
diff --git a/src/rip/videodvd/k3bvideodvdrippingwidget.cpp b/src/rip/videodvd/k3bvideodvdrippingwidget.cpp
new file mode 100644
index 0000000..721d191
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingwidget.cpp
@@ -0,0 +1,375 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include "k3bvideodvdrippingwidget.h"
+
+#include <k3bvideodvdtitletranscodingjob.h>
+#include <k3bglobals.h>
+#include <k3brichtextlabel.h>
+#include <k3bintmapcombobox.h>
+
+#include <klistview.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+#include <kio/global.h>
+#include <kurllabel.h>
+#include <kdialogbase.h>
+#include <klineedit.h>
+
+#include <qcombobox.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qwhatsthis.h>
+#include <qwidgetstack.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+
+static const int s_mp3Bitrates[] = {
+ 32,
+ 40,
+ 48,
+ 56,
+ 64,
+ 80,
+ 96,
+ 112,
+ 128,
+ 160,
+ 192,
+ 224,
+ 256,
+ 320,
+ 0 // just used for the loops below
+};
+
+
+static const int PICTURE_SIZE_ORIGINAL = 0;
+static const int PICTURE_SIZE_640 = 1;
+static const int PICTURE_SIZE_320 = 2;
+static const int PICTURE_SIZE_CUSTOM = 3;
+static const int PICTURE_SIZE_MAX = 4;
+
+static const char* s_pictureSizeNames[] = {
+ I18N_NOOP("Keep original dimensions"),
+ I18N_NOOP("640x? (automatic height)"),
+ I18N_NOOP("320x? (automatic height)"),
+ I18N_NOOP("Custom")
+};
+
+
+K3bVideoDVDRippingWidget::K3bVideoDVDRippingWidget( QWidget* parent )
+ : base_K3bVideoDVDRippingWidget( parent )
+{
+ m_editBaseDir->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+
+ m_titleView->addColumn( i18n("Title") );
+ m_titleView->addColumn( i18n("Video Size") );
+ m_titleView->addColumn( i18n("File Size") );
+ m_titleView->addColumn( i18n("Filename") );
+ m_titleView->setSorting( -1 );
+
+ //
+ // Example filename pattern
+ //
+ m_comboFilenamePattern->insertItem( QString( "%b - %1 %t (%n %a %c)" ).arg(i18n("Title") ) );
+ m_comboFilenamePattern->insertItem( QString( "%{volumeid} (%{title})" ) );
+
+
+ //
+ // Add the Audio bitrates
+ //
+ for( int i = 0; s_mp3Bitrates[i]; ++i )
+ m_comboAudioBitrate->insertItem( i18n("%1 kbps" ).arg(s_mp3Bitrates[i]) );
+
+
+ for( int i = 0; i < K3bVideoDVDTitleTranscodingJob::VIDEO_CODEC_NUM_ENTRIES; ++i ) {
+ K3bVideoDVDTitleTranscodingJob::VideoCodec codec( (K3bVideoDVDTitleTranscodingJob::VideoCodec)i );
+ if( K3bVideoDVDTitleTranscodingJob::transcodeBinaryHasSupportFor( codec ) )
+ m_comboVideoCodec->insertItem( i,
+ K3bVideoDVDTitleTranscodingJob::videoCodecString( codec ),
+ K3bVideoDVDTitleTranscodingJob::videoCodecDescription( codec ) );
+ }
+ for( int i = 0; i < K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_NUM_ENTRIES; ++i ) {
+ K3bVideoDVDTitleTranscodingJob::AudioCodec codec( (K3bVideoDVDTitleTranscodingJob::AudioCodec)i );
+ if( K3bVideoDVDTitleTranscodingJob::transcodeBinaryHasSupportFor( codec ) )
+ m_comboAudioCodec->insertItem( i,
+ K3bVideoDVDTitleTranscodingJob::audioCodecString( codec ),
+ K3bVideoDVDTitleTranscodingJob::audioCodecDescription( codec ) );
+ }
+
+ for( int i = 0; i < PICTURE_SIZE_MAX; ++i ) {
+ m_comboVideoSize->insertItem( i18n( s_pictureSizeNames[i] ) );
+ }
+
+ slotAudioCodecChanged( m_comboAudioCodec->selectedValue() );
+
+ connect( m_comboAudioBitrate, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(changed()) );
+ connect( m_spinVideoBitrate, SIGNAL(valueChanged(int)),
+ this, SIGNAL(changed()) );
+ connect( m_checkBlankReplace, SIGNAL(toggled(bool)),
+ this, SIGNAL(changed()) );
+ connect( m_editBlankReplace, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(changed()) );
+ connect( m_comboFilenamePattern, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(changed()) );
+ connect( m_editBaseDir, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(changed()) );
+
+ connect( m_comboAudioCodec, SIGNAL(valueChanged(int)),
+ this, SLOT(slotAudioCodecChanged(int)) );
+ connect( m_specialStringsLabel, SIGNAL(leftClickedURL()),
+ this, SLOT(slotSeeSpecialStrings()) );
+ connect( m_buttonCustomPictureSize, SIGNAL(clicked()),
+ this, SLOT(slotCustomPictureSize()) );
+ connect( m_comboVideoSize, SIGNAL(activated(int)),
+ this, SLOT(slotVideoSizeChanged(int)) );
+
+ // refresh every 2 seconds
+ m_freeSpaceUpdateTimer = new QTimer( this );
+ connect( m_freeSpaceUpdateTimer, SIGNAL(timeout()),
+ this, SLOT(slotUpdateFreeTempSpace()) );
+ m_freeSpaceUpdateTimer->start(2000);
+ slotUpdateFreeTempSpace();
+}
+
+
+K3bVideoDVDRippingWidget::~K3bVideoDVDRippingWidget()
+{
+}
+
+
+K3bVideoDVDTitleTranscodingJob::VideoCodec K3bVideoDVDRippingWidget::selectedVideoCodec() const
+{
+ return (K3bVideoDVDTitleTranscodingJob::VideoCodec)m_comboVideoCodec->selectedValue();
+}
+
+
+QSize K3bVideoDVDRippingWidget::selectedPictureSize() const
+{
+ switch( m_comboVideoSize->currentItem() ) {
+ case PICTURE_SIZE_ORIGINAL:
+ return QSize(0,0);
+ case PICTURE_SIZE_640:
+ return QSize(640,0);
+ case PICTURE_SIZE_320:
+ return QSize(320,0);
+ default:
+ return m_customVideoSize;
+ }
+}
+
+
+void K3bVideoDVDRippingWidget::setSelectedPictureSize( const QSize& size )
+{
+ m_customVideoSize = size;
+ if( size == QSize(0,0) )
+ m_comboVideoSize->setCurrentItem( PICTURE_SIZE_ORIGINAL );
+ else if( size == QSize(640,0) )
+ m_comboVideoSize->setCurrentItem( PICTURE_SIZE_640 );
+ else if( size == QSize(320,0) )
+ m_comboVideoSize->setCurrentItem( PICTURE_SIZE_320 );
+ else {
+ m_comboVideoSize->changeItem( i18n(s_pictureSizeNames[PICTURE_SIZE_CUSTOM])
+ + QString(" (%1x%2)")
+ .arg(size.width() == 0 ? i18n("auto") : QString::number(size.width()))
+ .arg(size.height() == 0 ? i18n("auto") : QString::number(size.height())),
+ PICTURE_SIZE_CUSTOM );
+ m_comboVideoSize->setCurrentItem( PICTURE_SIZE_CUSTOM );
+ }
+}
+
+
+void K3bVideoDVDRippingWidget::setSelectedVideoCodec( K3bVideoDVDTitleTranscodingJob::VideoCodec codec )
+{
+ m_comboVideoCodec->setSelectedValue( (int)codec );
+}
+
+
+K3bVideoDVDTitleTranscodingJob::AudioCodec K3bVideoDVDRippingWidget::selectedAudioCodec() const
+{
+ return (K3bVideoDVDTitleTranscodingJob::AudioCodec)m_comboAudioCodec->selectedValue();
+}
+
+
+void K3bVideoDVDRippingWidget::setSelectedAudioCodec( K3bVideoDVDTitleTranscodingJob::AudioCodec codec )
+{
+ m_comboAudioCodec->setSelectedValue( (int)codec );
+ slotAudioCodecChanged( (int)codec );
+}
+
+
+int K3bVideoDVDRippingWidget::selectedAudioBitrate() const
+{
+ if( selectedAudioCodec() == K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3 )
+ return s_mp3Bitrates[m_comboAudioBitrate->currentItem()];
+ else
+ return m_spinAudioBitrate->value();
+}
+
+
+void K3bVideoDVDRippingWidget::setSelectedAudioBitrate( int bitrate )
+{
+ m_spinAudioBitrate->setValue( bitrate );
+
+ // select the bitrate closest to "bitrate"
+ int bi = 0;
+ int diff = 1000;
+ for( int i = 0; s_mp3Bitrates[i]; ++i ) {
+ int newDiff = s_mp3Bitrates[i] - bitrate;
+ if( newDiff < 0 )
+ newDiff = -1 * newDiff;
+ if( newDiff < diff ) {
+ diff = newDiff;
+ bi = i;
+ }
+ }
+
+ m_comboAudioBitrate->setCurrentItem( bi );
+}
+
+
+void K3bVideoDVDRippingWidget::slotUpdateFreeTempSpace()
+{
+ QString path = m_editBaseDir->url();
+
+ if( !QFile::exists( path ) )
+ path.truncate( path.findRev('/') );
+
+ unsigned long size, avail;
+ if( K3b::kbFreeOnFs( path, size, avail ) ) {
+ m_labelFreeSpace->setText( KIO::convertSizeFromKB(avail) );
+ if( avail < m_neededSize/1024 )
+ m_labelNeededSpace->setPaletteForegroundColor( Qt::red );
+ else
+ m_labelNeededSpace->setPaletteForegroundColor( paletteForegroundColor() );
+ }
+ else {
+ m_labelFreeSpace->setText("-");
+ m_labelNeededSpace->setPaletteForegroundColor( paletteForegroundColor() );
+ }
+}
+
+
+void K3bVideoDVDRippingWidget::setNeededSize( KIO::filesize_t size )
+{
+ m_neededSize = size;
+ if( size > 0 )
+ m_labelNeededSpace->setText( KIO::convertSize( size ) );
+ else
+ m_labelNeededSpace->setText( i18n("unknown") );
+
+ slotUpdateFreeTempSpace();
+}
+
+
+void K3bVideoDVDRippingWidget::slotSeeSpecialStrings()
+{
+ QWhatsThis::display( i18n( "<p><b>Pattern special strings:</b>"
+ "<p>The following strings will be replaced with their respective meaning in every "
+ "track name.<br>"
+ "<p><table border=\"0\">"
+ "<tr><td></td><td><em>Meaning</em></td><td><em>Alternatives</em></td></tr>"
+ "<tr><td>%t</td><td>title number</td><td>%{t} or %{title_number}</td></tr>"
+ "<tr><td>%i</td><td>volume id (mostly the name of the Video DVD)</td><td>%{i} or %{volume_id}</td></tr>"
+ "<tr><td>%b</td><td>beautified volume id</td><td>%{b} or %{beautified_volume_id}</td></tr>"
+ "<tr><td>%l</td><td>two chars language code</td><td>%{l} or %{lang_code}</td></tr>"
+ "<tr><td>%n</td><td>language name</td><td>%{n} or %{lang_name}</td></tr>"
+ "<tr><td>%a</td><td>audio format (on the Video DVD)</td><td>%{a} or %{audio_format}</td></tr>"
+ "<tr><td>%c</td><td>number of audio channels (on the Video DVD)</td><td>%{c} or %{channels}</td></tr>"
+ "<tr><td>%v</td><td>size of the original video</td><td>%{v} or %{orig_video_size}</td></tr>"
+ "<tr><td>%s</td><td>size of the resulting video (<em>Caution: auto-clipping values are not taken into account!</em>)</td><td>%{s} or %{video_size}</td></tr>"
+ "<tr><td>%r</td><td>aspect ratio of the original video</td><td>%{r} or %{aspect_ratio}</td></tr>"
+ "<tr><td>%d</td><td>current date</td><td>%{d} or %{date}</td></tr>"
+ "</table>"
+ "<p><em>Hint: K3b also accepts slight variations of the long special strings. "
+ "One can, for example, leave out the underscores.</em>") );
+}
+
+
+void K3bVideoDVDRippingWidget::slotAudioCodecChanged( int codec )
+{
+ switch( codec ) {
+ case K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3:
+ m_stackAudioQuality->raiseWidget( m_stackPageAudioQualityMp3 );
+ break;
+ case K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_STEREO:
+ m_stackAudioQuality->raiseWidget( m_stackPageAudioQualityAC3 );
+ break;
+ case K3bVideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH:
+ m_stackAudioQuality->raiseWidget( m_stackPageAudioQualityAC3Pt );
+ break;
+ }
+
+ emit changed();
+}
+
+
+void K3bVideoDVDRippingWidget::slotVideoSizeChanged( int sizeIndex )
+{
+ if( sizeIndex == PICTURE_SIZE_CUSTOM )
+ slotCustomPictureSize();
+ else
+ emit changed();
+}
+
+
+void K3bVideoDVDRippingWidget::slotCustomPictureSize()
+{
+ KDialogBase dlg( KDialogBase::Plain,
+ i18n("Video Picture Size"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok,
+ this,
+ 0,
+ true,
+ true );
+ K3bRichTextLabel* label = new K3bRichTextLabel( i18n("<p>Please choose the width and height of the resulting video. "
+ "If one value is set to <em>Auto</em> K3b will choose this value "
+ "depending on the aspect ratio of the video picture.<br>"
+ "Be aware that setting both the width and the height to fixed values "
+ "will result in no aspect ratio correction to be performed."),
+ dlg.plainPage() );
+ QSpinBox* spinWidth = new QSpinBox( 0, 20000, 16, dlg.plainPage() );
+ QSpinBox* spinHeight = new QSpinBox( 0, 20000, 16, dlg.plainPage() );
+ spinWidth->setSpecialValueText( i18n("Auto") );
+ spinHeight->setSpecialValueText( i18n("Auto") );
+ QLabel* labelW = new QLabel( spinWidth, i18n("Width") + ':', dlg.plainPage() );
+ QLabel* labelH = new QLabel( spinHeight, i18n("Height") + ':', dlg.plainPage() );
+ labelW->setAlignment( Qt::AlignRight|Qt::AlignVCenter );
+ labelH->setAlignment( Qt::AlignRight|Qt::AlignVCenter );
+
+ QGridLayout* grid = new QGridLayout( dlg.plainPage() );
+ grid->setMargin( 0 );
+ grid->setSpacing( KDialog::spacingHint() );
+ grid->addMultiCellWidget( label, 0, 0, 0, 3 );
+ grid->addWidget( labelW, 1, 0 );
+ grid->addWidget( spinWidth, 1, 1 );
+ grid->addWidget( labelH, 1, 2 );
+ grid->addWidget( spinHeight, 1, 3 );
+
+ spinWidth->setValue( m_customVideoSize.width() );
+ spinHeight->setValue( m_customVideoSize.height() );
+
+ if( dlg.exec() ) {
+ setSelectedPictureSize( QSize( spinWidth->value(), spinHeight->value() ) );
+ emit changed();
+ }
+}
+
+#include "k3bvideodvdrippingwidget.moc"
diff --git a/src/rip/videodvd/k3bvideodvdrippingwidget.h b/src/rip/videodvd/k3bvideodvdrippingwidget.h
new file mode 100644
index 0000000..2d10da7
--- /dev/null
+++ b/src/rip/videodvd/k3bvideodvdrippingwidget.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_VIDEODVD_RIPPING_WIDGET_H_
+#define _K3B_VIDEODVD_RIPPING_WIDGET_H_
+
+#include "base_k3bvideodvdrippingwidget.h"
+
+#include <k3bvideodvdtitletranscodingjob.h>
+
+#include <qvaluevector.h>
+#include <qmap.h>
+
+#include <kio/global.h>
+
+class QTimer;
+
+class K3bVideoDVDRippingWidget : public base_K3bVideoDVDRippingWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bVideoDVDRippingWidget( QWidget* parent );
+ ~K3bVideoDVDRippingWidget();
+
+ K3bVideoDVDTitleTranscodingJob::VideoCodec selectedVideoCodec() const;
+ K3bVideoDVDTitleTranscodingJob::AudioCodec selectedAudioCodec() const;
+ int selectedAudioBitrate() const;
+ QSize selectedPictureSize() const;
+
+ void setSelectedVideoCodec( K3bVideoDVDTitleTranscodingJob::VideoCodec codec );
+ void setSelectedAudioCodec( K3bVideoDVDTitleTranscodingJob::AudioCodec codec );
+ void setSelectedAudioBitrate( int bitrate );
+ void setSelectedPictureSize( const QSize& );
+
+ void setNeededSize( KIO::filesize_t );
+
+ signals:
+ void changed();
+
+ private slots:
+ void slotUpdateFreeTempSpace();
+ void slotSeeSpecialStrings();
+ void slotAudioCodecChanged( int codec );
+ void slotVideoSizeChanged( int sizeIndex );
+ void slotCustomPictureSize();
+
+ private:
+ QTimer* m_freeSpaceUpdateTimer;
+ KIO::filesize_t m_neededSize;
+
+ QSize m_customVideoSize;
+};
+
+#endif
diff --git a/src/sounds/Makefile.am b/src/sounds/Makefile.am
new file mode 100644
index 0000000..28cec7c
--- /dev/null
+++ b/src/sounds/Makefile.am
@@ -0,0 +1,5 @@
+
+soundsdir = $(kde_sounddir)
+sounds_DATA = k3b_success1.wav k3b_error1.wav k3b_wait_media1.wav
+
+EXTRA_DIST = $(sounds_DATA)
diff --git a/src/sounds/k3b_error1.wav b/src/sounds/k3b_error1.wav
new file mode 100644
index 0000000..5b2e0b3
--- /dev/null
+++ b/src/sounds/k3b_error1.wav
Binary files differ
diff --git a/src/sounds/k3b_success1.wav b/src/sounds/k3b_success1.wav
new file mode 100644
index 0000000..7a42a2b
--- /dev/null
+++ b/src/sounds/k3b_success1.wav
Binary files differ
diff --git a/src/sounds/k3b_wait_media1.wav b/src/sounds/k3b_wait_media1.wav
new file mode 100644
index 0000000..a629bae
--- /dev/null
+++ b/src/sounds/k3b_wait_media1.wav
Binary files differ
diff --git a/src/sourceheader b/src/sourceheader
new file mode 100644
index 0000000..a83a4d5
--- /dev/null
+++ b/src/sourceheader
@@ -0,0 +1,15 @@
+/*
+ *
+ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
+ * Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2006 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
diff --git a/src/tips b/src/tips
new file mode 100644
index 0000000..3050e95
--- /dev/null
+++ b/src/tips
@@ -0,0 +1,47 @@
+<tip category="K3b">
+<html>
+<p>...that you do not need to erase a CDRW before rewriting it manually
+since K3b can do that automatically before writing.</p>
+</html>
+</tip>
+
+<tip category="K3b">
+<html>
+<p>...that you do not need to bother with any settings if you do not know
+what they mean. K3b is able to choose the settings best suited for you.</p>
+</html>
+</tip>
+
+<tip category="K3b">
+<html>
+<p>...that K3b has two types of settings. On the one hand K3b has settings like most
+KDE applications have accessable through the configuration dialog via the settings menu;
+on the other hand every K3b action dialog has three buttons to load and save defaults
+for that action. This way one may, for example, set the defaults for CD Copy: these defaults
+will then be loaded every time the CD Copy dialog is opened. The button <em>K3b defaults</em>
+will restore the <em>factory settings</em> in case you do not know if the settings you chose
+are appropriate.</p>
+</html>
+</tip>
+
+<tip category="K3b">
+<html>
+<p>...that you do not need to bother changing the settings marked as <em>advanced</em> if you
+do not know what they mean. K3b's defaults are suitable for most daily use.</p>
+</html>
+</tip>
+
+<tip category="K3b">
+<html>
+<p>Just left-click one of your devices in the device and file tree and see what happens. K3b opens a specific
+window based on the media's contents. For an audio CD for example you will be given a list of the tracks with
+the possibility to rip these tracks to any format supported by K3b (like mp3 or Ogg-Vorbis).</p>
+</html>
+</tip>
+
+<tip category="K3b">
+<html>
+<p>...that K3b lets you choose media instead of devices for burning. So if you want to burn to a certain
+medium simply insert it and wait for K3b to detect it. It will then appear as your burning medium.</p>
+</html>
+</tip>