From 50b48aec6ddd451a6d1709c0942477b503457663 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 3 Feb 2010 02:15:56 +0000 Subject: 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 --- src/projects/Makefile.am | 86 ++ src/projects/base_k3badvanceddataimagesettings.ui | 193 ++++ src/projects/base_k3baudiocdtextallfieldswidget.ui | 275 +++++ src/projects/base_k3baudiocdtextwidget.ui | 222 ++++ src/projects/base_k3baudiotrackwidget.ui | 336 ++++++ src/projects/base_k3bbootimageview.ui | 394 +++++++ src/projects/base_k3bdataimagesettings.ui | 274 +++++ src/projects/base_k3bdatavolumedescwidget.ui | 370 +++++++ src/projects/base_k3bmovixoptionswidget.ui | 337 ++++++ src/projects/k3baudioburndialog.cpp | 341 ++++++ src/projects/k3baudioburndialog.h | 81 ++ src/projects/k3baudiocdtextwidget.cpp | 236 +++++ src/projects/k3baudiocdtextwidget.h | 55 + src/projects/k3baudiodatasourceeditwidget.cpp | 166 +++ src/projects/k3baudiodatasourceeditwidget.h | 70 ++ src/projects/k3baudiodatasourceviewitem.cpp | 111 ++ src/projects/k3baudiodatasourceviewitem.h | 54 + src/projects/k3baudioeditorwidget.cpp | 877 ++++++++++++++++ src/projects/k3baudioeditorwidget.h | 220 ++++ src/projects/k3baudiotrackaddingdialog.cpp | 302 ++++++ src/projects/k3baudiotrackaddingdialog.h | 106 ++ src/projects/k3baudiotrackdialog.cpp | 113 ++ src/projects/k3baudiotrackdialog.h | 57 + src/projects/k3baudiotrackplayer.cpp | 365 +++++++ src/projects/k3baudiotrackplayer.h | 87 ++ src/projects/k3baudiotracksplitdialog.cpp | 232 +++++ src/projects/k3baudiotracksplitdialog.h | 71 ++ src/projects/k3baudiotracktrmlookupdialog.cpp | 131 +++ src/projects/k3baudiotracktrmlookupdialog.h | 54 + src/projects/k3baudiotrackview.cpp | 1005 ++++++++++++++++++ src/projects/k3baudiotrackview.h | 142 +++ src/projects/k3baudiotrackviewitem.cpp | 229 ++++ src/projects/k3baudiotrackviewitem.h | 66 ++ src/projects/k3baudiotrackwidget.cpp | 162 +++ src/projects/k3baudiotrackwidget.h | 48 + src/projects/k3baudioview.cpp | 136 +++ src/projects/k3baudioview.h | 61 ++ src/projects/k3bbootimagedialog.cpp | 45 + src/projects/k3bbootimagedialog.h | 44 + src/projects/k3bbootimageview.cpp | 273 +++++ src/projects/k3bbootimageview.h | 57 + .../k3bdataadvancedimagesettingswidget.cpp | 352 +++++++ src/projects/k3bdataadvancedimagesettingswidget.h | 69 ++ src/projects/k3bdataburndialog.cpp | 289 ++++++ src/projects/k3bdataburndialog.h | 75 ++ src/projects/k3bdatadirtreeview.cpp | 506 +++++++++ src/projects/k3bdatadirtreeview.h | 115 +++ src/projects/k3bdatafileview.cpp | 483 +++++++++ src/projects/k3bdatafileview.h | 115 +++ src/projects/k3bdataimagesettingswidget.cpp | 400 +++++++ src/projects/k3bdataimagesettingswidget.h | 54 + src/projects/k3bdatamultisessioncombobox.cpp | 177 ++++ src/projects/k3bdatamultisessioncombobox.h | 52 + src/projects/k3bdatapropertiesdialog.cpp | 248 +++++ src/projects/k3bdatapropertiesdialog.h | 61 ++ src/projects/k3bdatasessionimportdialog.cpp | 137 +++ src/projects/k3bdatasessionimportdialog.h | 64 ++ src/projects/k3bdataurladdingdialog.cpp | 826 +++++++++++++++ src/projects/k3bdataurladdingdialog.h | 110 ++ src/projects/k3bdataview.cpp | 196 ++++ src/projects/k3bdataview.h | 78 ++ src/projects/k3bdataviewitem.cpp | 340 ++++++ src/projects/k3bdataviewitem.h | 135 +++ src/projects/k3bdatavolumedescwidget.cpp | 93 ++ src/projects/k3bdatavolumedescwidget.h | 40 + src/projects/k3bdvdburndialog.cpp | 300 ++++++ src/projects/k3bdvdburndialog.h | 69 ++ src/projects/k3bdvdview.cpp | 48 + src/projects/k3bdvdview.h | 40 + src/projects/k3bencodingconverter.cpp | 130 +++ src/projects/k3bencodingconverter.h | 59 ++ src/projects/k3bfillstatusdisplay.cpp | 759 ++++++++++++++ src/projects/k3bfillstatusdisplay.h | 117 +++ src/projects/k3bmixedburndialog.cpp | 353 +++++++ src/projects/k3bmixedburndialog.h | 78 ++ src/projects/k3bmixeddirtreeview.cpp | 103 ++ src/projects/k3bmixeddirtreeview.h | 56 + src/projects/k3bmixedview.cpp | 155 +++ src/projects/k3bmixedview.h | 66 ++ src/projects/k3bmovixburndialog.cpp | 265 +++++ src/projects/k3bmovixburndialog.h | 64 ++ src/projects/k3bmovixdvdburndialog.cpp | 219 ++++ src/projects/k3bmovixdvdburndialog.h | 57 + src/projects/k3bmovixdvdview.cpp | 48 + src/projects/k3bmovixdvdview.h | 40 + src/projects/k3bmovixlistview.cpp | 327 ++++++ src/projects/k3bmovixlistview.h | 100 ++ src/projects/k3bmovixoptionswidget.cpp | 243 +++++ src/projects/k3bmovixoptionswidget.h | 50 + src/projects/k3bmovixview.cpp | 192 ++++ src/projects/k3bmovixview.h | 65 ++ src/projects/k3bmusicbrainzjob.cpp | 287 ++++++ src/projects/k3bmusicbrainzjob.h | 89 ++ src/projects/k3bprojectburndialog.cpp | 413 ++++++++ src/projects/k3bprojectburndialog.h | 191 ++++ src/projects/k3bprojectplugindialog.cpp | 68 ++ src/projects/k3bprojectplugindialog.h | 46 + src/projects/k3bvcdburndialog.cpp | 1088 ++++++++++++++++++++ src/projects/k3bvcdburndialog.h | 142 +++ src/projects/k3bvcdlistview.cpp | 271 +++++ src/projects/k3bvcdlistview.h | 90 ++ src/projects/k3bvcdlistviewitem.cpp | 129 +++ src/projects/k3bvcdlistviewitem.h | 50 + src/projects/k3bvcdtrackdialog.cpp | 802 +++++++++++++++ src/projects/k3bvcdtrackdialog.h | 123 +++ src/projects/k3bvcdview.cpp | 74 ++ src/projects/k3bvcdview.h | 55 + src/projects/k3bvideodvdburndialog.cpp | 198 ++++ src/projects/k3bvideodvdburndialog.h | 55 + src/projects/k3bvideodvdview.cpp | 84 ++ src/projects/k3bvideodvdview.h | 48 + src/projects/k3bview.cpp | 176 ++++ src/projects/k3bview.h | 112 ++ src/projects/kostore/Makefile.am | 11 + src/projects/kostore/README.k3b | 2 + src/projects/kostore/SPEC | 122 +++ src/projects/kostore/koStore.cc | 629 +++++++++++ src/projects/kostore/koStore.h | 384 +++++++ src/projects/kostore/koStoreBase.cc | 29 + src/projects/kostore/koStoreBase.h | 51 + src/projects/kostore/koStoreDevice.h | 88 ++ src/projects/kostore/koZipStore.cc | 237 +++++ src/projects/kostore/koZipStore.h | 61 ++ 123 files changed, 23707 insertions(+) create mode 100644 src/projects/Makefile.am create mode 100644 src/projects/base_k3badvanceddataimagesettings.ui create mode 100644 src/projects/base_k3baudiocdtextallfieldswidget.ui create mode 100644 src/projects/base_k3baudiocdtextwidget.ui create mode 100644 src/projects/base_k3baudiotrackwidget.ui create mode 100644 src/projects/base_k3bbootimageview.ui create mode 100644 src/projects/base_k3bdataimagesettings.ui create mode 100644 src/projects/base_k3bdatavolumedescwidget.ui create mode 100644 src/projects/base_k3bmovixoptionswidget.ui create mode 100644 src/projects/k3baudioburndialog.cpp create mode 100644 src/projects/k3baudioburndialog.h create mode 100644 src/projects/k3baudiocdtextwidget.cpp create mode 100644 src/projects/k3baudiocdtextwidget.h create mode 100644 src/projects/k3baudiodatasourceeditwidget.cpp create mode 100644 src/projects/k3baudiodatasourceeditwidget.h create mode 100644 src/projects/k3baudiodatasourceviewitem.cpp create mode 100644 src/projects/k3baudiodatasourceviewitem.h create mode 100644 src/projects/k3baudioeditorwidget.cpp create mode 100644 src/projects/k3baudioeditorwidget.h create mode 100644 src/projects/k3baudiotrackaddingdialog.cpp create mode 100644 src/projects/k3baudiotrackaddingdialog.h create mode 100644 src/projects/k3baudiotrackdialog.cpp create mode 100644 src/projects/k3baudiotrackdialog.h create mode 100644 src/projects/k3baudiotrackplayer.cpp create mode 100644 src/projects/k3baudiotrackplayer.h create mode 100644 src/projects/k3baudiotracksplitdialog.cpp create mode 100644 src/projects/k3baudiotracksplitdialog.h create mode 100644 src/projects/k3baudiotracktrmlookupdialog.cpp create mode 100644 src/projects/k3baudiotracktrmlookupdialog.h create mode 100644 src/projects/k3baudiotrackview.cpp create mode 100644 src/projects/k3baudiotrackview.h create mode 100644 src/projects/k3baudiotrackviewitem.cpp create mode 100644 src/projects/k3baudiotrackviewitem.h create mode 100644 src/projects/k3baudiotrackwidget.cpp create mode 100644 src/projects/k3baudiotrackwidget.h create mode 100644 src/projects/k3baudioview.cpp create mode 100644 src/projects/k3baudioview.h create mode 100644 src/projects/k3bbootimagedialog.cpp create mode 100644 src/projects/k3bbootimagedialog.h create mode 100644 src/projects/k3bbootimageview.cpp create mode 100644 src/projects/k3bbootimageview.h create mode 100644 src/projects/k3bdataadvancedimagesettingswidget.cpp create mode 100644 src/projects/k3bdataadvancedimagesettingswidget.h create mode 100644 src/projects/k3bdataburndialog.cpp create mode 100644 src/projects/k3bdataburndialog.h create mode 100644 src/projects/k3bdatadirtreeview.cpp create mode 100644 src/projects/k3bdatadirtreeview.h create mode 100644 src/projects/k3bdatafileview.cpp create mode 100644 src/projects/k3bdatafileview.h create mode 100644 src/projects/k3bdataimagesettingswidget.cpp create mode 100644 src/projects/k3bdataimagesettingswidget.h create mode 100644 src/projects/k3bdatamultisessioncombobox.cpp create mode 100644 src/projects/k3bdatamultisessioncombobox.h create mode 100644 src/projects/k3bdatapropertiesdialog.cpp create mode 100644 src/projects/k3bdatapropertiesdialog.h create mode 100644 src/projects/k3bdatasessionimportdialog.cpp create mode 100644 src/projects/k3bdatasessionimportdialog.h create mode 100644 src/projects/k3bdataurladdingdialog.cpp create mode 100644 src/projects/k3bdataurladdingdialog.h create mode 100644 src/projects/k3bdataview.cpp create mode 100644 src/projects/k3bdataview.h create mode 100644 src/projects/k3bdataviewitem.cpp create mode 100644 src/projects/k3bdataviewitem.h create mode 100644 src/projects/k3bdatavolumedescwidget.cpp create mode 100644 src/projects/k3bdatavolumedescwidget.h create mode 100644 src/projects/k3bdvdburndialog.cpp create mode 100644 src/projects/k3bdvdburndialog.h create mode 100644 src/projects/k3bdvdview.cpp create mode 100644 src/projects/k3bdvdview.h create mode 100644 src/projects/k3bencodingconverter.cpp create mode 100644 src/projects/k3bencodingconverter.h create mode 100644 src/projects/k3bfillstatusdisplay.cpp create mode 100644 src/projects/k3bfillstatusdisplay.h create mode 100644 src/projects/k3bmixedburndialog.cpp create mode 100644 src/projects/k3bmixedburndialog.h create mode 100644 src/projects/k3bmixeddirtreeview.cpp create mode 100644 src/projects/k3bmixeddirtreeview.h create mode 100644 src/projects/k3bmixedview.cpp create mode 100644 src/projects/k3bmixedview.h create mode 100644 src/projects/k3bmovixburndialog.cpp create mode 100644 src/projects/k3bmovixburndialog.h create mode 100644 src/projects/k3bmovixdvdburndialog.cpp create mode 100644 src/projects/k3bmovixdvdburndialog.h create mode 100644 src/projects/k3bmovixdvdview.cpp create mode 100644 src/projects/k3bmovixdvdview.h create mode 100644 src/projects/k3bmovixlistview.cpp create mode 100644 src/projects/k3bmovixlistview.h create mode 100644 src/projects/k3bmovixoptionswidget.cpp create mode 100644 src/projects/k3bmovixoptionswidget.h create mode 100644 src/projects/k3bmovixview.cpp create mode 100644 src/projects/k3bmovixview.h create mode 100644 src/projects/k3bmusicbrainzjob.cpp create mode 100644 src/projects/k3bmusicbrainzjob.h create mode 100644 src/projects/k3bprojectburndialog.cpp create mode 100644 src/projects/k3bprojectburndialog.h create mode 100644 src/projects/k3bprojectplugindialog.cpp create mode 100644 src/projects/k3bprojectplugindialog.h create mode 100644 src/projects/k3bvcdburndialog.cpp create mode 100644 src/projects/k3bvcdburndialog.h create mode 100644 src/projects/k3bvcdlistview.cpp create mode 100644 src/projects/k3bvcdlistview.h create mode 100644 src/projects/k3bvcdlistviewitem.cpp create mode 100644 src/projects/k3bvcdlistviewitem.h create mode 100644 src/projects/k3bvcdtrackdialog.cpp create mode 100644 src/projects/k3bvcdtrackdialog.h create mode 100644 src/projects/k3bvcdview.cpp create mode 100644 src/projects/k3bvcdview.h create mode 100644 src/projects/k3bvideodvdburndialog.cpp create mode 100644 src/projects/k3bvideodvdburndialog.h create mode 100644 src/projects/k3bvideodvdview.cpp create mode 100644 src/projects/k3bvideodvdview.h create mode 100644 src/projects/k3bview.cpp create mode 100644 src/projects/k3bview.h create mode 100644 src/projects/kostore/Makefile.am create mode 100644 src/projects/kostore/README.k3b create mode 100644 src/projects/kostore/SPEC create mode 100644 src/projects/kostore/koStore.cc create mode 100644 src/projects/kostore/koStore.h create mode 100644 src/projects/kostore/koStoreBase.cc create mode 100644 src/projects/kostore/koStoreBase.h create mode 100644 src/projects/kostore/koStoreDevice.h create mode 100644 src/projects/kostore/koZipStore.cc create mode 100644 src/projects/kostore/koZipStore.h (limited to 'src/projects') 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 @@ + +base_K3bAdvancedDataImageSettings +Sebastian Trueg + + + base_K3bDataCustomFilesystemsWidget + + + Custom Data Filesystems + + + + unnamed + + + 0 + + + 6 + + + + groupIsoSettings + + + File System Settings + + + + unnamed + + + + + ISO9660 Filesystem + + + false + + + false + + + + m_viewIsoSettings + + + true + + + + + + + groupBox3 + + + File Systems + + + + unnamed + + + + m_checkRockRidge + + + &Generate Rock Ridge extensions + + + true + + + Add Rock Ridge extensions to the file system + + + <p>If this option is checked, K3b will generate the System Use Sharing Protocol records (SUSP) specified by the Rock Ridge Interchange Protocol (IEEE-P1282). +<p>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. +<p>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. +<p><b>It is highly recommended to use Rock Ridge extensions on every data CD or DVD.</b> + + + + + m_checkJoliet + + + Generate &Joliet extensions + + + Add Joliet extensions to the file system + + + <p>If this option is checked, K3b will add additional Joliet extensions to the ISO-9660 file system. +<p>Joliet is not an accepted independent international standard like ISO-9660 or Rock Ridge. It is mainly used on Windows systems. +<p>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. +<p>Joliet uses UTF-16 coding. +<p><b>Caution:</b> With the exception of Linux and FreeBSD, there is no POSIX-like OS that supports Joliet. So <b>never create Joliet-only CDs or DVDs</b> for that reason. + + + + + m_checkUdf + + + Generate &UDF structures + + + Add UDF structures to the file system + + + <p>If this option is checked K3b will create UDF filesystem structures in addition to the ISO9660 filesystem. +<p>The UDF (<em><b>U</b>niversal <b>D</b>isk <b>F</b>ormat</em>) is mainly used for DVDs. + + + + + + + groupBox5 + + + Other Settings + + + + unnamed + + + + layout1 + + + + unnamed + + + + m_checkForceInputCharset + + + F&orce input charset: + + + + + m_comboInputCharset + + + false + + + true + + + + + + + m_checkPreservePermissions + + + Preserve file permissions (bac&kup) + + + <p>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). +<p>This is mainly useful for backups.<p><b>Caution:</b> 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. + + + + + + + + + m_checkForceInputCharset + toggled(bool) + m_comboInputCharset + setEnabled(bool) + + + + m_checkRockRidge + m_checkJoliet + + + + klistview.h + kcombobox.h + klineedit.h + + 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 @@ + +base_K3bAudioCdTextAllFieldsWidget +Sebastian Trueg + + + base_K3bAudioCdTextAllFieldsWidget + + + + unnamed + + + 0 + + + + textLabel8 + + + Messa&ge: + + + m_editMessage + + + + + layout2 + + + + unnamed + + + + m_editSongwriter + + + + + m_buttonCopySongwriter + + + ... + + + Copy to all tracks + + + + + + + textLabel6 + + + &UPC EAN: + + + m_editUpc_ean + + + + + layout1 + + + + unnamed + + + + m_editComposer + + + + + m_buttonCopyComposer + + + ... + + + Copy to all tracks + + + + + + + textLabel4 + + + So&ngwriter: + + + m_editSongwriter + + + + + textLabel5 + + + &Composer: + + + m_editComposer + + + + + textLabel7 + + + &Disk id: + + + m_editDisc_id + + + + + layout3 + + + + unnamed + + + + m_editArranger + + + + + m_buttonCopyArranger + + + ... + + + Copy to all tracks + + + + + + + textLabel3 + + + &Arranger: + + + m_editArranger + + + + + m_editUpc_ean + + + + + m_editDisc_id + + + + + m_editMessage + + + + + textLabel2 + + + &Performer: + + + m_editPerformer + + + + + layout5 + + + + unnamed + + + + m_editTitle + + + + + m_buttonCopyTitle + + + ... + + + Copy to all tracks + + + + + + + textLabel1 + + + &Title: + + + m_editTitle + + + + + line4 + + + HLine + + + Sunken + + + Horizontal + + + + + layout4 + + + + unnamed + + + + m_editPerformer + + + + + m_buttonCopyPerformer + + + ... + + + Copy to all tracks + + + + + + + + + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + + 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 @@ + +base_K3bAudioCdTextWidget +Widget to edit the global CD-Text in a K3b audio project. +Sebastian Trueg + + + K3bAudioCDTextWidget + + + K3bAudioCDTextWidget + + + + unnamed + + + + m_groupCdText + + + Write CD-Text + + + true + + + false + + + + + + <p><b>CD-Text</b> +<p>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. +<p>CD-Text is an extension to the audio CD standard introduced by Sony. +<p>CD-Text will only be usable on CD players that support this extension (mostly car CD players) and software like K3b, of course. +<p>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). + + + + unnamed + + + + frame3 + + + NoFrame + + + Raised + + + + unnamed + + + 0 + + + + textLabel2 + + + Perf&ormer: + + + m_editPerformer + + + + + layout4 + + + + unnamed + + + + m_editPerformer + + + + + m_buttonCopyPerformer + + + ... + + + Copy to all tracks + + + + + + + layout5 + + + + unnamed + + + + m_editTitle + + + + + m_buttonCopyTitle + + + ... + + + Copy to all tracks + + + + + + + textLabel1 + + + &Title: + + + m_editTitle + + + + + + + layout15 + + + + unnamed + + + + spacer3 + + + Horizontal + + + Expanding + + + + 0 + 0 + + + + + + m_buttonMoreFields + + + More Fiel&ds... + + + + + + + spacer1 + + + Vertical + + + Expanding + + + + 21 + 0 + + + + + + + + + + m_buttonCopyTitle + clicked() + K3bAudioCDTextWidget + slotCopyTitle() + + + m_buttonCopyPerformer + clicked() + K3bAudioCDTextWidget + slotCopyPerformer() + + + + m_editTitle + m_editPerformer + + + slotCopyTitle() + slotCopyPerformer() + slotCopyArranger() + slotCopyComposer() + slotCopySongwriter() + + + + klineedit.h + klineedit.h + + 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 @@ + +base_K3bAudioTrackWidget +Sebastian Trueg + + + K3bAudioTrackWidget + + + K3bAudioTrackWidget + + + + unnamed + + + 0 + + + + m_mainTab + + + + tab + + + C&D-Text + + + + unnamed + + + + layout9 + + + + unnamed + + + + m_editSongwriter + + + + + textLabel4 + + + So&ngwriter: + + + m_editSongwriter + + + + + m_editArranger + + + + + m_editComposer + + + + + m_editMessage + + + + + line2 + + + HLine + + + Sunken + + + Horizontal + + + + + textLabel3 + + + &Arranger: + + + m_editArranger + + + + + textLabel5 + + + &Composer: + + + m_editComposer + + + + + textLabel8 + + + &Message: + + + m_editMessage + + + + + m_editTitle + + + + + textLabel2 + + + &Performer: + + + m_editPerformer + + + + + textLabel6 + + + &ISRC: + + + m_editIsrc + + + + + textLabel1 + + + &Title: + + + m_editTitle + + + + + m_editIsrc + + + + + m_editPerformer + + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 350 + 50 + + + + + + + + tab + + + &Options + + + + unnamed + + + + m_checkPreemphasis + + + Preemph&asis + + + <p>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. + + + + + m_checkCopyPermitted + + + &Copy permitted + + + + + layout6 + + + + unnamed + + + + m_labelPostGap + + + Post-Gap: + + + + + m_editPostGap + + + Set the length of the track's post-gap + + + <p>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. +<p>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. +<p><i>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. +<p><b>Changing the post-gap does not change the length of the track!</b> +<p><b>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.</b> + + + + + spacer7 + + + Horizontal + + + Expanding + + + + 161 + 20 + + + + + + + + spacer3 + + + Vertical + + + Expanding + + + + 41 + 80 + + + + + + + + + + + K3bMsfEdit +
k3bmsfedit.h
+ + 100 + -1 + + 0 + + 7 + 5 + 0 + 0 + + image0 +
+
+ + + 789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f + + + + m_editTitle + m_editPerformer + m_editArranger + m_editComposer + m_editSongwriter + m_editIsrc + m_editMessage + m_checkPreemphasis + m_checkCopyPermitted + + + + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + k3bmsfedit.h + +
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 @@ + +base_K3bBootImageView +Sebastian Trueg + + + base_K3bBootImageView + + + + unnamed + + + 0 + + + + layout17 + + + + unnamed + + + + label + + + + 5 + 5 + 1 + 0 + + + + Boot images: + + + + + m_buttonNew + + + &New... + + + Add new boot image + + + + + m_buttonDelete + + + &Delete + + + Remove selected boot image + + + + + + + + Emulation Type + + + false + + + false + + + + + Size + + + true + + + true + + + + + Local Path + + + false + + + false + + + + m_viewImages + + + true + + + true + + + + + m_groupImageType + + + Emulation Type + + + + unnamed + + + + m_radioFloppy + + + Flopp&y + + + Emulate a 1440/2880 kb floppy + + + + + m_radioHarddisk + + + Harddisk + + + Emulate a harddisk + + + + + m_radioNoEmulation + + + None + + + No emulation at all + + + + + + + m_groupOptions + + + + 5 + 5 + 0 + 0 + + + + Settings + + + + unnamed + + + + m_checkNoBoot + + + No boot image + + + Do not boot from the emulated floppy/harddisk + + + + + m_checkInfoTable + + + Boot-info-table + + + + + layout10 + + + + unnamed + + + + m_editLoadSegment + + + false + + + 0 + + + + + m_editLoadSize + + + false + + + 0 + + + + + textLabel2_2 + + + false + + + Boot load segment: + + + + + textLabel3 + + + false + + + Boot load size: + + + + + + + + + layout16 + + + + unnamed + + + + m_buttonToggleOptions + + + Show Advanced Op&tions + + + + + spacer16 + + + Horizontal + + + Expanding + + + + 261 + 21 + + + + + + + + layout18 + + + + unnamed + + + + textLabel2 + + + Boot catalog: + + + + + m_editBootCataloge + + + boot/boot.catalog + + + true + + + + + + + + + m_radioFloppy + toggled(bool) + base_K3bBootImageView + slotOptionsChanged() + + + m_radioHarddisk + toggled(bool) + base_K3bBootImageView + slotOptionsChanged() + + + m_checkNoBoot + toggled(bool) + base_K3bBootImageView + slotOptionsChanged() + + + m_checkInfoTable + toggled(bool) + base_K3bBootImageView + slotOptionsChanged() + + + m_editLoadSegment + textChanged(const QString&) + base_K3bBootImageView + slotOptionsChanged() + + + m_editLoadSize + textChanged(const QString&) + base_K3bBootImageView + slotOptionsChanged() + + + m_radioNoEmulation + toggled(bool) + textLabel2_2 + setEnabled(bool) + + + m_radioNoEmulation + toggled(bool) + textLabel3 + setEnabled(bool) + + + m_radioNoEmulation + toggled(bool) + m_editLoadSegment + setEnabled(bool) + + + m_radioNoEmulation + toggled(bool) + m_editLoadSize + setEnabled(bool) + + + m_radioNoEmulation + toggled(bool) + m_checkNoBoot + setDisabled(bool) + + + m_radioNoEmulation + toggled(bool) + base_K3bBootImageView + slotOptionsChanged() + + + + slotOptionsChanged() + + + + klistview.h + + 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 @@ + +base_K3bDataImageSettings +Sebastian Trueg + + + base_K3bDataImageSetings + + + Data Image Settings + + + + unnamed + + + 0 + + + + m_groupVolumeName + + + Volume Name + + + + unnamed + + + + m_editVolumeName + + + 32 + + + + + m_buttonMoreVolDescFields + + + &More fields... + + + + + + + m_groupFileSystem + + + File System + + + + unnamed + + + 11 + + + 6 + + + + m_comboFilesystems + + + + 1 + 0 + 1 + 0 + + + + File system presets + + + + + m_buttonCustomFilesystems + + + &Custom... + + + + + + + layout4 + + + + unnamed + + + + m_groupSymlinks + + + Symbolic Links + + + + unnamed + + + + + No Change + + + + + Discard broken symlinks + + + + + Discard all symlinks + + + + + Follow symlinks + + + + m_comboSymlinkHandling + + + + 1 + 0 + 1 + 0 + + + + Symbolic link handling in the project + + + <p>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. + +<p><b>No Change</b><br> +Symlinks are used as they have been added to the project. + +<p><b>Discard broken symlinks</b><br> +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'. + +<p><b>Discard all symlinks</b><br> +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. + +<p><b>Follow symlinks</b><br> +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.<br> +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. + +<p><b>Caution:</b> Symbolic links require Rock Ridge extensions. + + + + + + + m_groupWhitespace + + + White space handling + + + + unnamed + + + + + No Change + + + + + Strip + + + + + Extended Strip + + + + + Replace + + + + m_comboSpaceHandling + + + + 1 + 0 + 1 + 0 + + + + Handling of spaces in filenames + + + <p><b>No Change</b><br> +If this option is checked, K3b will leave all spaces in filenames as they are. +<p><b>Strip</b><br> +If this option is checked, K3b will remove all spaces from all filenames.<br> +Example: 'my good file.ext' becomes 'mygoodfile.ext' +<p><b>Extended Strip</b><br> +If this option is checked K3b will remove all spaces in all filenames and capitalize all letters following a space.<br> +Example: 'my good file.ext' becomes 'myGoodFile.ext' +<p><b>Replace</b><br> +If this option is checked, K3b will replace all spaces in all filenames with the specified characters.<br> +Example: 'my good file.ext' becomes 'my_good_file.ext' + + + + + m_editReplace + + + false + + + + 0 + 0 + 0 + 0 + + + + _ + + + The string to replace spaces with + + + + + + + + + spacer1 + + + Vertical + + + Expanding + + + + 21 + 0 + + + + + + + m_editReplace + + + 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 @@ + +base_K3bDataVolumeDescWidget +Sebastian Trueg + + + base_K3bDataVolumeDescWidget + + + Volume Descriptor + + + + unnamed + + + 0 + + + 6 + + + + m_editVolumeName + + + 32 + + + + + m_editVolumeSetName + + + 128 + + + + + TextLabel2 + + + V&olume set name: + + + m_editVolumeSetName + + + + + TextLabel1 + + + &Volume name: + + + m_editVolumeName + + + + + m_editPublisher + + + 128 + + + + + m_editPreparer + + + 128 + + + + + TextLabel4 + + + P&reparer: + + + m_editPreparer + + + + + TextLabel3 + + + P&ublisher: + + + m_editPublisher + + + + + textLabel1 + + + Volu&me set size: + + + m_spinVolumeSetSize + + + + + layout1 + + + + unnamed + + + + m_spinVolumeSetSize + + + + + + 1 + + + 1 + + + + + textLabel2 + + + Volume set &number: + + + AlignVCenter|AlignRight + + + m_spinVolumeSetNumber + + + + + m_spinVolumeSetNumber + + + + + + 2 + + + 1 + + + 1 + + + + + + + TextLabel5 + + + S&ystem: + + + m_editSystem + + + + + m_editSystem + + + 32 + + + + + TextLabel6 + + + &Application: + + + m_editApplication + + + + + Spacer1 + + + Vertical + + + Expanding + + + + 20 + 0 + + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + m_editApplication + + + 128 + + + + + layout4 + + + + unnamed + + + + m_editBiblio + + + 37 + + + + + m_buttonFindBiblio + + + ... + + + Select a bibliographic file from the project + + + + + + + layout2 + + + + unnamed + + + + m_editAbstract + + + 37 + + + + + m_buttonFindAbstract + + + ... + + + Select an abstract file from the project + + + + + + + layout3 + + + + unnamed + + + + m_editCopyright + + + 37 + + + + + m_buttonFindCopyright + + + ... + + + Select a copyright file from the project + + + + + + + textLabel1_2 + + + Abstract file: + + + + + textLabel2_2 + + + Copyright file: + + + + + textLabel3 + + + Bibliographic file: + + + + + line1_2 + + + HLine + + + Sunken + + + Horizontal + + + + + + m_editVolumeName + m_editVolumeSetName + m_spinVolumeSetSize + m_spinVolumeSetNumber + m_editPublisher + m_editPreparer + m_editSystem + m_editApplication + + + 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 @@ + +base_K3bMovixOptionsWidget +Sebastian trueg + + + Form1 + + + + unnamed + + + + groupBox2 + + + GroupBoxPanel + + + Sunken + + + Playback Settings + + + + unnamed + + + + textLabel2 + + + MPlayer subtitle fontset: + + + + + m_comboSubtitleFontset + + + Select the font to be used to render subtitles + + + + + textLabel7 + + + Unwanted MPlayer options: + + + + + + + + layout1 + + + + unnamed + + + + m_checkRandomPlay + + + Pla&y files randomly + + + The files are played in random order + + + <p>If this option is checked the order in which the files are played is determined randomly every time it is played. + + + + + m_checkNoDma + + + &Do not use DMA + + + Do not use DMA for media access + + + <p>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.</p> + + + + + + + m_editUnwantedMplayerOptions + + + MPlayer options you want to be sure MPlayer will not use + + + <p>Here one can specify MPlayer options that should never be used. +<p>They have to be separated by spaces: +<pre>opt1 opt2 opt3</pre> + + + + + m_editAdditionalMplayerOptions + + + Additional MPlayer options + + + <p>MPlayer options that should be used in any case. +<p>They have to be separated by spaces: +<pre>opt1 opt2 opt3</pre> + + + + + textLabel6 + + + Additional MPlayer options: + + + + + textLabel3 + + + Loop playlist: + + + + + m_spinLoop + + + time(s) + + + infinity + + + 1 + + + How many times should the playlist be looped + + + + + m_labelAudioBackground + + + Audio Player Background: + + + + + m_comboAudioBackground + + + Background video to show during audio playback + + + <p><b>Audio Player Background</b> +<p>During audio playback normally the screen would be black. However, if a background movie has been selected, eMovix will display it during playback. +<p>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 <i>/usr/share/emovix</i> or <i>/usr/local/share/emovix</i>) under <em>backgrounds</em>. So to add a background one has to copy the file to that folder. + + + + + + + groupBox3 + + + Startup Behavior + + + + unnamed + + + + m_labelKeyboardLayout + + + Keyboard Layout: + + + + + textLabel1 + + + eMovix boot messages language: + + + + + m_comboBootMessageLanguage + + + Select the language of the eMovix help screens + + + + + textLabel5 + + + Default boot label: + + + + + m_comboDefaultBootLabel + + + Select the default Linux kernel configuration + + + <p><b>eMovix Boot Labels</b> +<p>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. +<p>The <b>default</b>, <b>movix</b>, or <b>MoviX</b> labels start a general Vesa video driver. +<p>The <b>TV</b> 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. +<p>The <b>FB</b> labels refer to configurations that start a Frame Buffer driver in different screen resolutions. +<p>The <b>AA</b> 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. +<p>The <b>hd</b> label makes eMovix boot from the local harddisk instead of the medium. This can be used to prevent accidental starting of an eMovix medium. +<p>The <b>floppy</b> label makes eMovix boot from the local floppy drive instead of the medium. + + + + + m_comboKeyboardLayout + + + Select the layout of the keyboard + + + <p>The keyboard layout selected here will be used for the eMovix commands like controlling the media player. + + + + + + + groupBox1 + + + + 5 + 5 + 0 + 1 + + + + Behavior After Playing + + + + unnamed + + + + m_checkEject + + + E&ject disk + + + Eject the disk after playing has finished + + + <p>If this option is checked the disk will be ejected after MPlayer has finished. + + + + + m_checkShutdown + + + Sh&utdown + + + Shutdown after playing has finished + + + <p>If this option is checked the PC will be shut down after MPlayer has finished playing. + + + + + m_checkReboot + + + Re&boot + + + Reboot after playing has finished + + + <p>If this option is checked the PC will be rebooted after MPlayer has finished playing. + + + + + + + + + m_checkShutdown + toggled(bool) + m_checkReboot + setDisabled(bool) + + + m_checkReboot + toggled(bool) + m_checkShutdown + setDisabled(bool) + + + + + kcombobox.h + kcombobox.h + kcombobox.h + kcombobox.h + kcombobox.h + + 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include "k3baudiodoc.h" +#include +#include +#include +#include "k3baudiocdtextwidget.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +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("

If this option is checked K3b will hide the first track." + "

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." + "

You will need to seek back from the beginning of the CD to listen to " + "the first track. Try it, it is quite amusing." + "

This feature is only available in DAO mode when writing with cdrdao.") ); +} + +K3bAudioBurnDialog::~K3bAudioBurnDialog(){ +} + + +void K3bAudioBurnDialog::slotStartClicked() +{ + static_cast(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(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("

External program normalize-audio is not installed." + "

K3b uses normalize-audio (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("

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("

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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + +#include +#include +#include + +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + + +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( 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( 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include + + + +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 +{ +public: + RangeList() + : QPtrList() { + } + + RangeList( const RangeList& l ) + : QPtrList( l ) { + } + + int compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 ) { + if( *static_cast(item1) > *static_cast(item2) ) + return 1; + else if( *static_cast(item1) < *static_cast(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 K3bAudioEditorWidget::allRanges() const +{ + QValueList l; + d->ranges.sort(); + for( QPtrListIterator 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 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 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 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 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 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 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 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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include + + +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 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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +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("

%1:
%2") + .arg( i18n("Insufficient permissions to read the following files") ) + .arg( dlg.m_unreadableFiles.join( "
" ) ); + if( !dlg.m_notFoundFiles.isEmpty() ) + message += QString("

%1:
%2") + .arg( i18n("Unable to find the following files") ) + .arg( dlg.m_notFoundFiles.join( "
" ) ); + if( !dlg.m_nonLocalFiles.isEmpty() ) + message += QString("

%1:
%2") + .arg( i18n("No non-local files supported") ) + .arg( dlg.m_unreadableFiles.join( "
" ) ); + if( !dlg.m_unsupportedFiles.isEmpty() ) + message += QString("

%1:
%2
%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( "
" ) ); + + 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "k3baudiotrackdialog.h" +#include "k3baudioeditorwidget.h" +#include "k3baudiotrackwidget.h" +#include "k3baudiotrack.h" +#include +#include +#include +#include +#include +#include + + +// 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& 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + +#include + +class K3bAudioTrack; +class K3bAudioTrackWidget; + +/** + *@author Sebastian Trueg + */ + +class K3bAudioTrackDialog : public KDialogBase +{ + Q_OBJECT + + public: + K3bAudioTrackDialog( QPtrList&, QWidget *parent=0, const char *name=0); + ~K3bAudioTrackDialog(); + + protected slots: + void slotOk(); + void slotApply(); + + void updateTrackLengthDisplay(); + + private: + QPtrList 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include + +#include +#include + +#include +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include +#include +#include +#include + +#include +#include +#include + + +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( e ); + splitAt( me->pos() ); + } + else if( e->type() == QEvent::ContextMenu ) { + QContextMenuEvent* ce = static_cast( 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 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::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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#ifdef HAVE_MUSICBRAINZ + +#include "k3baudiotracktrmlookupdialog.h" +#include "k3bmusicbrainzjob.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +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& 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +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& 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 list = selectedItems(); + + if( list.isEmpty() ) + return 0; + + KURL::List urls; + + for( QPtrListIterator 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( item ) ) { + if( K3bAudioFile* file = dynamic_cast( sourceItem->source() ) ) + urls.append( KURL::fromPathOrURL(file->filename()) ); + } + else { + K3bAudioTrackViewItem* trackItem = static_cast( item ); + K3bAudioDataSource* source = trackItem->track()->firstSource(); + while( source ) { + if( K3bAudioFile* file = dynamic_cast( 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( after ) ) { + m_dropTrackAfter = tv->track(); + } + else if( K3bAudioDataSourceViewItem* sv = dynamic_cast( after ) ) { + m_dropSourceAfter = sv->source(); + } + } + + if( K3bAudioTrackViewItem* tv = dynamic_cast( 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 tracks; + QPtrList 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 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 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 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 trackNumbers; + + K3bAudioCdTrackDrag::decode( e, toc, trackNumbers, cddb, &dev ); + + // for now we just create one source + for( QValueList::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::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( 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(this); + that->findDrop( pos, parent, after ); + if( parent ) + return static_cast( parent ); + else if( K3bAudioTrackViewItem* tv = dynamic_cast(after) ) + return tv; + else if( K3bAudioDataSourceViewItem* sv = dynamic_cast(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(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& tracks, + QPtrList& sources ) +{ + tracks.clear(); + sources.clear(); + + QPtrList items = selectedItems(); + for( QPtrListIterator it( items ); it.current(); ++it ) { + if( K3bAudioTrackViewItem* tv = dynamic_cast( *it ) ) + tracks.append( tv->track() ); + else { + K3bAudioDataSourceViewItem* sv = static_cast( *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 tracks; + QPtrList 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 srcIt( sources ); + while( srcIt.current() ) { + if( tracks.containsRef( srcIt.current()->track() ) ) + sources.removeRef( *srcIt ); + else + ++srcIt; + } + + // + // Now delete all the tracks + // + for( QPtrListIterator it( tracks ); it.current(); ++it ) + delete *it; + + // + // Now delete all the sources + // + for( QPtrListIterator 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(item) ) { + tv->track()->addSource( zero ); + } + else if( K3bAudioDataSourceViewItem* sv = dynamic_cast(item) ) { + zero->moveAfter( sv->source() ); + } + } + } +} + + +void K3bAudioTrackView::slotMergeTracks() +{ + QPtrList tracks; + QPtrList 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(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( 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(item) ) { + K3bAudioTrackSplitDialog::splitTrack( tv->track(), this ); + } +} + + +void K3bAudioTrackView::slotEditSource() +{ + QListViewItem* item = selectedItems().first(); + + K3bAudioDataSource* source = 0; + if( K3bAudioDataSourceViewItem* sv = dynamic_cast(item) ) + source = sv->source(); + else if( K3bAudioTrackViewItem* tv = dynamic_cast(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 tracks; + QPtrList 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(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(m_doc->view())->actionCollection()->action( "project_burn" )->plug( m_popupMenu ); + + m_popupMenu->popup( pos ); +} + + +void K3bAudioTrackView::slotProperties() +{ + QPtrList tracks; + QPtrList sources; + getSelectedItems( tracks, sources ); + + // TODO: add tracks from sources to tracks + + if( !tracks.isEmpty() ) { + K3bAudioTrackDialog d( tracks, this ); + d.exec(); + } + else { + static_cast(m_doc->view())->slotProperties(); + } +} + + +void K3bAudioTrackView::slotPlayTrack() +{ + QPtrList tracks; + QPtrList 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 tracks; + QPtrList 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include +#include +#include + +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& tracks, + QPtrList& 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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + +#include + + +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( 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + + +K3bAudioTrackWidget::K3bAudioTrackWidget( const QPtrList& 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + + +class K3bAudioTrack; + + +/** + * This class is used internally by K3bAudioTrackDialog. + */ +class K3bAudioTrackWidget : public base_K3bAudioTrackWidget +{ + Q_OBJECT + + public: + K3bAudioTrackWidget( const QPtrList& tracks, + QWidget* parent = 0, const char* name = 0 ); + ~K3bAudioTrackWidget(); + + public slots: + void save(); + void load(); + + QPtrList 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include "k3baudioview.h" +#include "k3baudiotrackview.h" +#include "k3baudioburndialog.h" +#include "k3baudiotrackplayer.h" +#include "k3baudioburndialog.h" +#include "k3baudiotrackaddingdialog.h" +#include + +#include +#include +#include +#include + +// this is not here becasue of base_*.ui troubles +#include "../rip/k3baudioprojectconvertingdialog.h" + +#include +#include +#include +#include +#include + +// QT-includes +#include +#include + +// KDE-includes +#include +#include +#include +#include + + + +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(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( "" + "" + "" + "

&Project" + " " +#ifdef HAVE_MUSICBRAINZ + " " +#endif + " " + "" + "", 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include "k3baudiotrackview.h" + +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + + +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("

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. " + "

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:" + "

dd if=/dev/floppy of=/tmp/floppy.img
" + "or by using one of the many boot floppy generators that can be found on " + "the internet."), + 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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +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( "

Set the ISO-9660 conformance level.\n" + "

    \n" + "
  • Level 1: Files may only consist of one section and filenames are restricted " + "to 8.3 characters.
  • \n" + "
  • Level 2: Files may only consist of one section.
  • \n" + "
  • Level 3: No restrictions.
  • \n" + "
\n" + "

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(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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +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(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( 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( 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 selectedViewItems = m_fileView->selectedItems(); + QValueList selectedDataItems; + QPtrListIterator it( selectedViewItems ); + for( ; it.current(); ++it ) { + K3bDataViewItem* dataViewItem = dynamic_cast( 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( selectedItem() ) ) { + QValueList 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( 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( item ); + QMapIterator 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 it( dirItem->children() ); + for( ; it.current(); ++it ) { + if( it.current()->isDir() ) + slotDataItemRemoved( it.current() ); + } + + delete viewItem; + } + } +} + + +void K3bDataDirTreeView::setCurrentDir( K3bDirItem* dirItem ) +{ + QMapIterator 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(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(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( currentItem() ) ) + m_doc->removeItem( dirViewItem->dirItem() ); + } +} + + +void K3bDataDirTreeView::slotProperties() +{ + K3bDataViewItem* viewItem = dynamic_cast( 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( item ); + + QMapIterator 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(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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include + +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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include "k3bdataurladdingdialog.h" +#include +#include "k3bdatapropertiesdialog.h" +#include "k3bdatadirtreeview.h" +#include "k3bdataviewitem.h" +#include + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +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(item), this ); + else if( item->isFile() ) + vi = new K3bDataFileViewItem( static_cast(item), this ); + else if( item->isSpecialFile() ) + vi = new K3bSpecialDataViewItem( static_cast(item), this ); + else if( item->isFromOldSession() ) + vi = new K3bSessionImportViewItem( static_cast(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(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 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( it.current() ); + if( dataViewItem && dataViewItem->dataItem()->parent() != currentDir() ) + delete dataViewItem; + } +} + + +QDragObject* K3bDataFileView::dragObject() +{ + QPtrList selectedViewItems = selectedItems(); + KURL::List urls; + for( QPtrListIterator it( selectedViewItems ); it.current(); ++it ) { + K3bDataViewItem* dataViewItem = dynamic_cast( 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( 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( 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 selectedViewItems = selectedItems(); + QValueList selectedDataItems; + QPtrListIterator it( selectedViewItems ); + for( ; it.current(); ++it ) { + K3bDataViewItem* dataViewItem = dynamic_cast( 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( m_treeView->selectedItem() ) ) { + QValueList 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( 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(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 items = selectedItems(); + QPtrListIterator it( items ); + for(; it.current(); ++it ) { + if( K3bDataViewItem* d = dynamic_cast( 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( 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( selectedItems().first() ) ) { + K3bDataItem* item = viewItem->dataItem(); + if( item->isFile() ) { + K3bDataFileViewItem* fvi = static_cast( 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( 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + +#include + + +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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +// 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("

File System Presets" + "

K3b provides the following file system Presets which allow for a quick selection " + "of the most frequently used settings.") + + "

" + i18n(s_fsPresetNames[0]) + "
" + + 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.") + + "

" + i18n(s_fsPresetNames[1]) + "
" + + 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.") + + "

" + i18n(s_fsPresetNames[2]) + "
" + + 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.") + + "

" + i18n(s_fsPresetNames[3]) + "
" + + 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("

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." + "

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("

Be aware that without the Joliet extensions Windows " + "systems will not be able to display long filenames. You " + "will only see the ISO9660 filenames." + "

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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include +#include + + +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("

Multisession Mode" + "

Auto
" + "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)." + "

No Multisession
" + "Create a single-session CD or DVD and close the disk." + "

Start Multisession
" + "Start a multisession CD or DVD, not closing the disk to " + "allow further sessions to be apppended." + "

Continue Multisession
" + "Continue an appendable data CD (as for example created in " + "Start Multisession mode) and add another session " + "without closing the disk to " + "allow further sessions to be apppended." + "

Finish Multisession
" + "Continue an appendable data CD (as for example created in " + "Start Multisession mode), add another session, " + "and close the disk." + "

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.") ); +} + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + +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(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(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("

If this option is checked, the file or directory " + "(and its entire contents) will be hidden on the " + "ISO9660 and RockRidge filesystem.

" + "

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.

") ); + QWhatsThis::add( m_checkHideOnJoliet, i18n("

If this option is checked, the file or directory " + "(and its entire contents) will be hidden on the " + "Joliet filesystem.

" + "

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.

") ); + QWhatsThis::add( m_editSortWeight, i18n("

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)." + "

This option is useful in order to optimize the data layout " + "on a CD/DVD." + "

Caution: 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + + +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("

K3b found session containing Joliet information for long filenames " + "but no Rock Ridge extensions." + "

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( k3bappcore->k3bMainWindow()->slotNewDvdDoc() ); + else + m_doc = static_cast( 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include +#include + +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include "k3bdataurladdingdialog.h" +#include "k3bencodingconverter.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +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("

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.
" + "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("

%1:
%2") + .arg( i18n("Insufficient permissions to read the following files") ) + .arg( m_unreadableFiles.join( "
" ) ); + if( !m_notFoundFiles.isEmpty() ) + message += QString("

%1:
%2") + .arg( i18n("Unable to find the following files") ) + .arg( m_notFoundFiles.join( "
" ) ); + if( !m_nonLocalFiles.isEmpty() ) + message += QString("

%1:
%2") + .arg( i18n("No non-local files supported") ) + .arg( m_unreadableFiles.join( "
" ) ); + if( !m_tooBigFiles.isEmpty() ) + message += QString("

%1:
%2") + .arg( i18n("It is not possible to add files bigger than %1").arg(KIO::convertSize(0xFFFFFFFF)) ) + .arg( m_tooBigFiles.join( "
" ) ); + if( !m_mkisofsLimitationRenamedFiles.isEmpty() ) + message += QString("

%1:
%2") + .arg( i18n("Some filenames had to be modified due to limitations in mkisofs") ) + .arg( m_mkisofsLimitationRenamedFiles.join( "
" ) ); + if( !m_invalidFilenameEncodingFiles.isEmpty() ) + message += QString("

%1:
%2") + .arg( i18n("The following filenames have an invalid encoding. You may fix this " + "with the convmv tool") ) + .arg( m_invalidFilenameEncodingFiles.join( "
" ) ); + + return message; +} + + +int K3bDataUrlAddingDialog::moveItems( const QValueList& items, + K3bDirItem* dir, + QWidget* parent ) +{ + return copyMoveItems( items, dir, parent, false ); +} + + +int K3bDataUrlAddingDialog::copyItems( const QValueList& items, + K3bDirItem* dir, + QWidget* parent ) +{ + return copyMoveItems( items, dir, parent, true ); +} + + +int K3bDataUrlAddingDialog::copyMoveItems( const QValueList& 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::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( *it )->numFiles(); + dlg.m_totalFiles += static_cast( *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(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("

File %1 already exists in " + "project folder %2.") + .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("

'%1' is a symbolic link to folder '%2'." + "

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." + "

If you do not intend to enable the option follow symbolic links you may safely " + "ignore this warning and choose to add the link to the project.") + .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& cl = dynamic_cast( item )->children(); + for( QPtrListIterator it( cl ); *it; ++it ) + m_items.append( qMakePair( *it, dynamic_cast( 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("

File %1 already exists in " + "project folder %2.") + .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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include + +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& items, K3bDirItem* dir, + QWidget* parent = 0 ); + + static int copyItems( const QValueList& items, K3bDirItem* dir, + QWidget* parent = 0 ); + + static int copyMoveItems( const QValueList& 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 > m_urlQueue; + + QValueList< QPair > m_items; + + QValueList 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +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( "" + "" + "" + "

&Project" + " " + " " + " " + " " + "" + "", 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include "k3bencodingconverter.h" + +#include +#include + +#include + +#ifdef HAVE_ICONV_H +#include +#include +#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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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("

Why does K3b offer 4.4 GB and 8.0 GB instead of 4.7 and 8.5 like " + "it says on the media?" + "

A single layer DVD media has a capacity of approximately " + "4.4 GB which equals 4.4*10243 bytes. Media producers just " + "calculate with 1000 instead of 1024 for advertising reasons.
" + "This results in 4.4*10243/10003 = 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("

Please specify the size of the media. Use suffixes gb,mb, " + "and min for gigabytes, megabytes, and minutes" + " 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 devs; + if( d->showDvdSizes ) + devs = k3bcore->deviceManager()->dvdWriter(); + else + devs = k3bcore->deviceManager()->cdWriter(); + + for( QPtrListIterator 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +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("Blue book CD" + "
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." + "
This mode is based on the Blue book " + "standard (also known as Extended Audio CD, " + "CD-Extra, or CD Plus) " + "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." + "
If the CD is intended to be used in a hifi audio CD player " + "this is the recommended mode." + "
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("Caution: The last two modes should only be used for CDs that are unlikely to " + "be played on a hifi audio CD player." + "
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(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("

External program normalize-audio is not installed." + "

K3b uses normalize-audio (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("

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("

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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include + +#include + +#include +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +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(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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +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( 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +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( 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include +#include +#include +#include + +#include +#include +#include +#include + + +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(this)->mimeComment()) + " "; + else + return const_cast(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(this)->mimeComment()); + else + return const_cast(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 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 sel = selectedItems(); + QPtrListIterator 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 list = selectedItems(); + + if( list.isEmpty() ) + return 0; + + QPtrListIterator 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include + +#include + + +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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +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::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 m_langMap; + QMap 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +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( m_listView->selectedItems().first() ) ) { + dataItem = viewItem->fileItem(); + } + + if( dataItem ) { + K3bDataPropertiesDialog d( dataItem, this ); + d.exec(); + } + else + slotProperties(); +} + + +void K3bMovixView::slotRemoveItems() +{ + QPtrList list = m_listView->selectedItems(); + QPtrListIterator it(list); + + if( list.isEmpty() ) + kdDebug() << "nothing to remove" << endl; + + for( ; it.current(); ++it ) { + K3bMovixListViewItem* vi = static_cast(*it); + if( vi->isMovixFileItem() ) + m_doc->removeItem( vi->fileItem() ); + else + m_doc->removeSubTitleItem( ((K3bMovixSubTitleViewItem*)*it)->fileItem() ); + } +} + + +void K3bMovixView::slotRemoveSubTitleItems() +{ + QPtrList list = m_listView->selectedItems(); + QPtrListIterator it(list); + + if( list.isEmpty() ) + kdDebug() << "nothing to remove" << endl; + + for( ; it.current(); ++it ) { + K3bMovixListViewItem* vi = static_cast(*it); + m_doc->removeSubTitleItem( vi->fileItem() ); + } +} + + +void K3bMovixView::slotAddSubTitleFile() +{ + QListViewItem* item = m_listView->selectedItems().first(); + if( K3bMovixListViewItem* vi = dynamic_cast(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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#ifdef HAVE_MUSICBRAINZ + +#include "k3bmusicbrainzjob.h" +#include "k3btrm.h" +#include "k3bmusicbrainz.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + + +// 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(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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#endif + +#ifdef HAVE_MUSICBRAINZ + +#include + + +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& 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 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + + +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: + *

    + *
  • Writing mode
  • + *
  • Simulate
  • + *
  • on the fly
  • + *
  • remove images
  • + *
  • only create images
  • + *
+ */ + virtual void loadK3bDefaults(); + + /** + * The default implementation loads the following settings from the KConfig. + * May be used in subclasses. + *
    + *
  • Writing mode
  • + *
  • Simulate
  • + *
  • on the fly
  • + *
  • remove images
  • + *
  • only create images
  • + *
  • writer
  • + *
  • writing speed
  • + *
+ */ + virtual void loadUserDefaults( KConfigBase* ); + + /** + * The default implementation saves the following settings to the KConfig. + * May be used in subclasses. + *
    + *
  • Writing mode
  • + *
  • Simulate
  • + *
  • on the fly
  • + *
  • remove images
  • + *
  • only create images
  • + *
  • writer
  • + *
  • writing speed
  • + *
+ */ + virtual void saveUserDefaults( KConfigBase* ); + + /** + * The default implementation saves the following settings to the doc and may be called + * in subclasses: + *
    + *
  • Writing mode
  • + *
  • Simulate
  • + *
  • on the fly
  • + *
  • remove images
  • + *
  • only create images
  • + *
  • writer
  • + *
  • writing speed
  • + *
+ */ + virtual void saveSettings(); + + /** + * The default implementation reads the following settings from the doc and may be called + * in subclasses: + *
    + *
  • Writing mode
  • + *
  • Simulate
  • + *
  • on the fly
  • + *
  • remove images
  • + *
  • only create images
  • + *
  • writer
  • + *
  • writing speed
  • + *
+ */ + 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "k3bvcdburndialog.h" +#include "k3bvcddoc.h" +#include "k3bvcdoptions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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( "

This is the most basic Video CD specification dating back to 1993, which has the following characteristics:" + "

  • One mode2 mixed form ISO-9660 track containing file pointers to the information areas.
  • " + "
  • Up to 98 multiplex-ed MPEG-1 audio/video streams or CD-DA audio tracks.
  • " + "
  • Up to 500 MPEG sequence entry points used as chapter divisions.
" + "

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.
" + "The specification allows for the following two resolutions:" + "

  • 352 x 240 @ 29.97 Hz (NTSC SIF).
  • " + "
  • 352 x 240 @ 23.976 Hz (FILM SIF).
" + "

The CBR MPEG-1, layer II audio stream is fixed at 224 kbps with 1 stereo or 2 mono channels." + "

It is recommended to keep the video bit-rate under 1151929.1 bps." ) ); + + QWhatsThis::add + ( m_radioVcd20, i18n( "

About two years after the Video CD 1.1 specification came out, an improved Video CD 2.0 standard was published in 1995." + "

This one added the following items to the features already available in the Video CD 1.1 specification:" + "

  • Support for MPEG segment play items (\"SPI\"), consisting of still pictures, motion pictures and/or audio (only) streams was added.
  • " + "
  • Note Segment Items::.
  • " + "
  • Support for interactive playback control (\"PBC\") was added.
  • " + "
  • Support for playing related access by providing a scan point index file was added. (\"/EXT/SCANDATA.DAT\")
  • " + "
  • Support for closed captions.
  • " + "
  • Support for mixing NTSC and PAL content.
" + "

By adding PAL support to the Video CD 1.1 specification, the following resolutions became available:" + "

  • 352 x 240 @ 29.97 Hz (NTSC SIF).
  • " + "
  • 352 x 240 @ 23.976 Hz (FILM SIF).
  • " + "
  • 352 x 288 @ 25 Hz (PAL SIF).
" + "

For segment play items the following audio encodings became available:" + "

  • Joint stereo, stereo or dual channel audio streams at 128, 192, 224 or 384 kbit/sec bit-rate.
  • " + "
  • Mono audio streams at 64, 96 or 192 kbit/sec bit-rate.
" + "

Also the possibility to have audio only streams and still pictures was provided." + "

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." ) ); + + QWhatsThis::add + ( m_radioSvcd10, i18n( "

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." + "

In the midst of 2000 a full subset of this Super Video CD specification was published as IEC-62107." + "

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." + "

The following new features--building upon the Video CD 2.0 specification--are:" + "

  • Use of MPEG-2 encoding instead of MPEG-1 for the video stream.
  • " + "
  • Allowed VBR encoding of MPEG-1 audio stream.
  • " + "
  • Higher resolutions (see below) for video stream resolution.
  • " + "
  • Up to 4 overlay graphics and text (\"OGT\") sub-channels for user switchable subtitle displaying in addition to the already existing closed caption facility.
  • " + "
  • Command lists for controlling the SVCD virtual machine.
" + "

For the Super Video CD, only the following two resolutions are supported for motion video and (low resolution) still pictures:" + "

  • 480 x 480 @ 29.97 Hz (NTSC 2/3 D-2).
  • " + "
  • 480 x 576 @ 25 Hz (PAL 2/3 D-2).
" ) ); + + QWhatsThis::add + ( m_radioHqVcd10, i18n( "

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." + "

It differs from the Super Video CD 1.0 format in the following items:" + "

  • The system profile tag field in /SVCD/INFO.SVD is set to 1 instead of 0.
  • " + "
  • The system identification field value in /SVCD/INFO.SVD is set to HQ-VCD instead of SUPERVCD.
  • " + "
  • /EXT/SCANDATA.DAT is mandatory instead of being optional.
  • " + "
  • /SVCD/SEARCH.DAT is optional instead of being mandatory.
" ) ); + + QWhatsThis::add + ( m_checkAutoDetect, i18n( "

If Autodetect is:

" + "
  • ON then K3b will set the correct VideoCD type.
  • " + "
  • OFF then the correct VideoCD type needs to be set by the user.
" + "

If you are not sure about the correct VideoCD type, it is best to turn Autodetect ON.

" + "

If you want to force the VideoCD type, you must turn Autodetect OFF. This is useful for some standalone DVD players without SVCD support.

" ) ); + + QWhatsThis::add + ( m_checkNonCompliant, i18n( "
  • Rename \"/MPEG2\" folder on SVCDs to (non-compliant) \"/MPEGAV\".
  • " + "
  • Enables the use of the (deprecated) signature \"ENTRYSVD\" instead of \"ENTRYVCD\" for the file \"/SVCD/ENTRY.SVD\".
" ) ); + QWhatsThis::add + ( m_checkVCD30interpretation, i18n( "
  • Enables the use of the (deprecated) Chinese \"/SVCD/TRACKS.SVD\" format which differs from the format defined in the IEC-62107 specification.
" + "

The differences are most exposed on SVCDs containing more than one video track." ) ); + + QWhatsThis::add + ( m_check2336, i18n( "

though most devices will have problems with such an out-of-specification media." + "

You may want use this option for images longer than 80 minutes" ) ); + + QWhatsThis::add + ( m_checkCdiSupport, i18n( "

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." + "

This program is designed to:" + "

  • provide full play back control as defined in the PSD of the standard" + "
  • be extremely simple to use and easy-to-learn for the end-user
" + "

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( "

Configuration parameters only available for VideoCD 2.0" + "

The engine works perfectly well when used as-is." + "

You have the option to configure the VCD application." + "

You can adapt the color and/or the shape of the cursor and lots more." ) ); + + + QWhatsThis::add + ( m_checkPbc, i18n( "

Playback control, PBC, is available for Video CD 2.0 and Super Video CD 1.0 disc formats." + "

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( "

Here you can specify that the folder SEGMENT should always be present." + "

Some DVD players need the folder to give a faultless rendition." ) ); + + QWhatsThis::add + ( m_checkRelaxedAps, i18n( "

An Access Point Sector, APS, is an MPEG video sector on the VCD/SVCD which is suitable to be jumped to directly." + "

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." + "

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." + "

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." + "

Warning: 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( "

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." + "

It can be used by playing devices for implementing fast forward & fast reverse scanning." + "

The already existing scan information data can be updated by enabling the update scan offsets option." ) ); + + QWhatsThis::add + ( m_labelRestriction, i18n( "

Viewing Restriction may be interpreted by the playing device." + "

The allowed range goes from 0 to 3." + "

  • 0 = unrestricted, free to view for all
  • " + "
  • 3 = restricted, content not suitable for ages under 18
" + "

Actually, the exact meaning is not defined and is player dependant." + "

Most players ignore that value." ) ); + + QWhatsThis::add + ( m_checkGaps, i18n( "

This option allows customization of Gaps and Margins." ) ); + QWhatsThis::add + ( m_labelPreGapLeadout, i18n( "

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." + "

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." + "

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." + "

Allowed value content: [0..300]. Default: 150." ) ); + + QWhatsThis::add + ( m_labelPreGapTrack, i18n( "

Used to set the track pre-gap for all tracks in sectors globally." + "

The specification requires the pre-gaps to be at least 150 sectors long." + "

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." + "

For Video CD 1.0/1.1/2.0 this margin should be at least 15 sectors long." + "

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( "

Margins are used to compensate for inaccurate sector-addressing issues on CD-ROM media. Interestingly, they have been abandoned for Super Video CDs." + "

For Video CD 1.0/1.1/2.0 this margin should be at least 15 sectors long." + "

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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 + +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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// K3b Includes +#include "k3bvcdlistview.h" +#include "k3bvcdlistviewitem.h" +#include "k3bvcdtrack.h" +#include "k3bvcdtrackdialog.h" +#include "k3bvcddoc.h" +#include + +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 list = selectedItems(); + + if ( list.isEmpty() ) + return 0; + + QPtrListIterator 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 sel = selectedItems(); + QPtrListIterator 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 selected = selectedTracks(); + if ( !selected.isEmpty() && selected.count() == 1 ) { + QPtrList tracks = *m_doc->tracks(); + K3bVcdTrackDialog d( m_doc, tracks, selected, this ); + if ( d.exec() ) { + repaint(); + } + } else { + m_view->slotProperties(); + } +} + +QPtrList K3bVcdListView::selectedTracks() +{ + QPtrList selectedTracks; + QPtrList selectedVI( selectedItems() ); + for ( QListViewItem * item = selectedVI.first(); item != 0; item = selectedVI.next() ) { + K3bVcdListViewItem * vcdItem = dynamic_cast( item ); + if ( vcdItem ) { + selectedTracks.append( vcdItem->vcdTrack() ); + } + } + + return selectedTracks; +} + + +void K3bVcdListView::slotRemoveTracks() +{ + QPtrList 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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 + +#include + +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 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 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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 +#include + + +// K3b Includes +#include "k3bvcdlistviewitem.h" +#include "k3bvcdtrack.h" +#include + +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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 + +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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Kde Includes +#include +#include +#include +#include +#include +#include + +// K3b Includes +#include "k3bvcdtrackdialog.h" +#include "k3bvcdtrack.h" +#include +#include +#include +#include + + +K3bVcdTrackDialog::K3bVcdTrackDialog( K3bVcdDoc* _doc, QPtrList& tracks, QPtrList& 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::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 ." ) ); + 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( "

Target to be jumped to on time-out of ." + "

If omitted (and is not set to an infinite time) one of the targets is selected at random." ) ); + QWhatsThis::add + ( m_check_reactivity, i18n( "

When reactivity is set to delayed, it is recommended that the length of the referenced 'play track' is not more than 5 seconds." + "

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( "

Playback control, PBC, is available for Video CD 2.0 and Super Video CD 1.0 disc formats." + "

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( "

If numeric keys enabled, you can overwrite the default settings." ) ); + QWhatsThis::add + ( m_spin_times, i18n( "

Times to repeat the playback of 'play track'." + "

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." + "

After the specified number of repetitions have completed, the time begins to count down, unless set to an infinite wait time." + "

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 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 definedkeysmap = selectedTrack->DefinedNumKey(); + + while ( it.current() ) { + int itemId = it.current() ->text( 0 ).toInt(); + + QMap::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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 +#include +#include + +#include +#include + +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& tracks, QPtrList& 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 m_tracks; + QPtrList m_selectedTracks; + QMap 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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 +#include + + +// KDE-includes +#include +#include +#include +#include + +// K3b Includes +#include "k3bvcdview.h" +#include "k3bvcddoc.h" +#include "k3bvcdlistview.h" +#include "k3bvcdburndialog.h" +#include +#include +#include + + +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 +* +* This file is part of the K3b project. +* Copyright (C) 1998-2007 Sebastian Trueg +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free 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 +#include + +// K3b Includes +#include + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include + +#include +#include +#include + +#include + + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 + +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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// application specific includes +#include "k3bview.h" +#include "k3bdoc.h" +#include "k3bfillstatusdisplay.h" +#include "k3bprojectburndialog.h" +#include "k3bprojectplugindialog.h" +#include +#include +#include +#include + + +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( "" + "" + "" + "

&Project" + " " + " " + " " + "" + "", true ); +} + +K3bView::~K3bView() +{ +} + + +void K3bView::setMainWidget( QWidget* w ) +{ + static_cast(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 pl = k3bcore->pluginManager()->plugins( "ProjectPlugin" ); + for( QPtrListIterator it( pl ); *it; ++it ) { + K3bProjectPlugin* pp = dynamic_cast( *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(button), pp ); + } + } +} + + +void K3bView::slotPluginButtonClicked() +{ + QObject* o = const_cast(sender()); + if( K3bProjectPlugin* p = m_plugins[static_cast(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 + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free 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 +#endif + +// include files for Qt +#include +#include + +#include +#include + +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 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 +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 and David +(edited by Chris Lee 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 + Copyright (C) 2000-2002 David Faure , Werner Trobin + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; 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 +#include +#include + +#include "koStore.h" +//#include "koTarStore.h" +#include "koZipStore.h" +//#include "koDirectoryStore.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//#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 + + 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(-1); + } + if ( m_mode != Read ) + { + kdWarning(s_area) << "KoStore: Can not get size from store that is opened for writing" << endl; + return static_cast(-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(-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 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; 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 +#include +#include +#include +//#include +#include + +#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 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 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; 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 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; 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 + +#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 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; 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 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; 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 + +#include +#include +#include +#include +#include +#if ! KDE_IS_VERSION( 3, 4, 1 ) +#include +#include +#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(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( 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( 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 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; 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 -- cgit v1.2.3