summaryrefslogtreecommitdiffstats
path: root/adept
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-09 10:18:22 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-09 10:18:22 +0000
commita4e1f41de249a24f3a3607b3ed5d5f02c094e8b5 (patch)
tree7e484840aaf31fc0d4780295b342592f3dd87a72 /adept
downloadadept-a4e1f41de249a24f3a3607b3ed5d5f02c094e8b5.tar.gz
adept-a4e1f41de249a24f3a3607b3ed5d5f02c094e8b5.zip
Added adept (KDE3 version abandoned by original author)
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/adept@1072021 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'adept')
-rw-r--r--adept/COPYING29
-rw-r--r--adept/Makefile.am1
-rw-r--r--adept/NEWS2
-rw-r--r--adept/TODO33
-rw-r--r--adept/adept/Makefile.am35
-rw-r--r--adept/adept/acqprogress.cpp295
-rw-r--r--adept/adept/acqprogress.h127
-rw-r--r--adept/adept/acqprogresswidget.cpp53
-rw-r--r--adept/adept/acqprogresswidget.h30
-rw-r--r--adept/adept/acqprogresswidgetui.ui79
-rw-r--r--adept/adept/actor.h43
-rw-r--r--adept/adept/application.cpp350
-rw-r--r--adept/adept/application.h102
-rw-r--r--adept/adept/changelog.cpp145
-rw-r--r--adept/adept/changelog.h45
-rw-r--r--adept/adept/commitprogress.cpp117
-rw-r--r--adept/adept/commitprogress.h41
-rw-r--r--adept/adept/commitprogressui.ui197
-rw-r--r--adept/adept/desktopentryui.ui116
-rw-r--r--adept/adept/desktoplist.cpp194
-rw-r--r--adept/adept/desktoplist.h117
-rw-r--r--adept/adept/dpkgpm-gui.cpp258
-rw-r--r--adept/adept/dpkgpm-gui.h68
-rw-r--r--adept/adept/dpkgpm.cpp462
-rw-r--r--adept/adept/dpkgpm.h49
-rw-r--r--adept/adept/easytagfilter.cpp81
-rw-r--r--adept/adept/easytagfilter.h93
-rw-r--r--adept/adept/easytagfilterui.ui201
-rw-r--r--adept/adept/extendablelist.cpp339
-rw-r--r--adept/adept/extendablelist.h166
-rw-r--r--adept/adept/filterlist.cpp232
-rw-r--r--adept/adept/filterlist.h149
-rw-r--r--adept/adept/filtersidebar.cpp72
-rw-r--r--adept/adept/filtersidebar.h26
-rw-r--r--adept/adept/filtersidebarui.ui119
-rw-r--r--adept/adept/filterwidget.cpp36
-rw-r--r--adept/adept/filterwidget.h39
-rw-r--r--adept/adept/groupeddesktopselector.cpp137
-rw-r--r--adept/adept/groupeddesktopselector.h39
-rw-r--r--adept/adept/installerview.cpp112
-rw-r--r--adept/adept/installerview.h33
-rw-r--r--adept/adept/installerviewui.ui203
-rw-r--r--adept/adept/lister.cpp818
-rw-r--r--adept/adept/lister.h261
-rw-r--r--adept/adept/listerextenderui.ui309
-rw-r--r--adept/adept/listerpredicate.h14
-rw-r--r--adept/adept/packagedetails.cpp273
-rw-r--r--adept/adept/packagedetails.h58
-rw-r--r--adept/adept/packagedetailsui.ui506
-rw-r--r--adept/adept/packageinfo.cpp181
-rw-r--r--adept/adept/packageinfo.h49
-rw-r--r--adept/adept/packageinfoui.ui180
-rw-r--r--adept/adept/progress.cpp58
-rw-r--r--adept/adept/progress.h30
-rw-r--r--adept/adept/quickfilter.cpp79
-rw-r--r--adept/adept/quickfilter.h119
-rw-r--r--adept/adept/quickfilterui.ui130
-rw-r--r--adept/adept/sourceseditor.cpp165
-rw-r--r--adept/adept/sourceseditor.h63
-rw-r--r--adept/adept/sourceseditorui.ui173
-rw-r--r--adept/adept/statefilter.cpp60
-rw-r--r--adept/adept/statefilter.h144
-rw-r--r--adept/adept/statefilterui.ui166
-rw-r--r--adept/adept/tagchooser.cpp147
-rw-r--r--adept/adept/tagchooser.h83
-rw-r--r--adept/adept/tagfilter.cpp67
-rw-r--r--adept/adept/tagfilter.h110
-rw-r--r--adept/adept/tagfilterui.ui95
-rw-r--r--adept/adept/taglist.cpp138
-rw-r--r--adept/adept/taglist.h72
-rw-r--r--adept/adept/threadutils.cpp44
-rw-r--r--adept/adept/utils.h71
-rw-r--r--adept/adept/view.cpp153
-rw-r--r--adept/adept/view.h66
-rw-r--r--adept/batch/Makefile.am20
-rw-r--r--adept/batch/adept_batchui.rc16
-rw-r--r--adept/batch/adept_updater.desktop70
-rw-r--r--adept/batch/app.cpp142
-rw-r--r--adept/batch/app.h54
-rw-r--r--adept/batch/main.cpp48
-rw-r--r--adept/configure.in.in5
-rwxr-xr-xadept/deb-build21
-rw-r--r--adept/icons/Makefile.am1
-rw-r--r--adept/icons/cr128-action-adept_notifier_warning.pngbin0 -> 15265 bytes
-rw-r--r--adept/icons/cr16-action-adept_commit.pngbin0 -> 883 bytes
-rw-r--r--adept/icons/cr16-action-adept_distupgrade.pngbin0 -> 987 bytes
-rw-r--r--adept/icons/cr16-action-adept_install.pngbin0 -> 1088 bytes
-rw-r--r--adept/icons/cr16-action-adept_keep.pngbin0 -> 912 bytes
-rw-r--r--adept/icons/cr16-action-adept_main_indicator.pngbin0 -> 808 bytes
-rw-r--r--adept/icons/cr16-action-adept_notifier_ok.pngbin0 -> 1160 bytes
-rw-r--r--adept/icons/cr16-action-adept_notifier_warning.pngbin0 -> 905 bytes
-rw-r--r--adept/icons/cr16-action-adept_preview.pngbin0 -> 1042 bytes
-rw-r--r--adept/icons/cr16-action-adept_purge.pngbin0 -> 536 bytes
-rw-r--r--adept/icons/cr16-action-adept_reinstall.pngbin0 -> 1013 bytes
-rw-r--r--adept/icons/cr16-action-adept_remove.pngbin0 -> 625 bytes
-rw-r--r--adept/icons/cr16-action-adept_sourceseditor.pngbin0 -> 1054 bytes
-rw-r--r--adept/icons/cr16-action-adept_update.pngbin0 -> 1135 bytes
-rw-r--r--adept/icons/cr16-action-adept_upgrade.pngbin0 -> 906 bytes
-rw-r--r--adept/icons/cr16-action-extender_closed.pngbin0 -> 781 bytes
-rw-r--r--adept/icons/cr16-action-extender_opened.pngbin0 -> 808 bytes
-rw-r--r--adept/icons/cr22-action-adept_commit.pngbin0 -> 1192 bytes
-rw-r--r--adept/icons/cr22-action-adept_distupgrade.pngbin0 -> 1255 bytes
-rw-r--r--adept/icons/cr22-action-adept_install.pngbin0 -> 1415 bytes
-rw-r--r--adept/icons/cr22-action-adept_keep.pngbin0 -> 1229 bytes
-rw-r--r--adept/icons/cr22-action-adept_notifier_ok.pngbin0 -> 1589 bytes
-rw-r--r--adept/icons/cr22-action-adept_notifier_warning.pngbin0 -> 1367 bytes
-rw-r--r--adept/icons/cr22-action-adept_preview.pngbin0 -> 1433 bytes
-rw-r--r--adept/icons/cr22-action-adept_purge.pngbin0 -> 646 bytes
-rw-r--r--adept/icons/cr22-action-adept_reinstall.pngbin0 -> 1482 bytes
-rw-r--r--adept/icons/cr22-action-adept_remove.pngbin0 -> 743 bytes
-rw-r--r--adept/icons/cr22-action-adept_sourceseditor.pngbin0 -> 1578 bytes
-rw-r--r--adept/icons/cr22-action-adept_update.pngbin0 -> 1684 bytes
-rw-r--r--adept/icons/cr22-action-adept_upgrade.pngbin0 -> 1222 bytes
-rw-r--r--adept/icons/cr22-action-extender_closed.pngbin0 -> 1003 bytes
-rw-r--r--adept/icons/cr22-action-extender_opened.pngbin0 -> 1029 bytes
-rw-r--r--adept/icons/cr32-action-adept_commit.pngbin0 -> 1732 bytes
-rw-r--r--adept/icons/cr32-action-adept_distupgrade.pngbin0 -> 2037 bytes
-rw-r--r--adept/icons/cr32-action-adept_install.pngbin0 -> 1790 bytes
-rw-r--r--adept/icons/cr32-action-adept_keep.pngbin0 -> 1821 bytes
-rw-r--r--adept/icons/cr32-action-adept_notifier_ok.pngbin0 -> 2473 bytes
-rw-r--r--adept/icons/cr32-action-adept_notifier_warning.pngbin0 -> 2288 bytes
-rw-r--r--adept/icons/cr32-action-adept_preview.pngbin0 -> 2474 bytes
-rw-r--r--adept/icons/cr32-action-adept_purge.pngbin0 -> 784 bytes
-rw-r--r--adept/icons/cr32-action-adept_reinstall.pngbin0 -> 2200 bytes
-rw-r--r--adept/icons/cr32-action-adept_remove.pngbin0 -> 935 bytes
-rw-r--r--adept/icons/cr32-action-adept_sourceseditor.pngbin0 -> 2404 bytes
-rw-r--r--adept/icons/cr32-action-adept_update.pngbin0 -> 2536 bytes
-rw-r--r--adept/icons/cr32-action-adept_upgrade.pngbin0 -> 1849 bytes
-rw-r--r--adept/icons/cr32-action-extender_closed.pngbin0 -> 1591 bytes
-rw-r--r--adept/icons/cr32-action-extender_opened.pngbin0 -> 1628 bytes
-rw-r--r--adept/icons/cr48-action-adept_commit.pngbin0 -> 2855 bytes
-rw-r--r--adept/icons/cr48-action-adept_distupgrade.pngbin0 -> 2963 bytes
-rw-r--r--adept/icons/cr48-action-adept_install.pngbin0 -> 2352 bytes
-rw-r--r--adept/icons/cr48-action-adept_keep.pngbin0 -> 2687 bytes
-rw-r--r--adept/icons/cr48-action-adept_notifier_ok.pngbin0 -> 4152 bytes
-rw-r--r--adept/icons/cr48-action-adept_notifier_warning.pngbin0 -> 3965 bytes
-rw-r--r--adept/icons/cr48-action-adept_preview.pngbin0 -> 4442 bytes
-rw-r--r--adept/icons/cr48-action-adept_purge.pngbin0 -> 1094 bytes
-rw-r--r--adept/icons/cr48-action-adept_reinstall.pngbin0 -> 3598 bytes
-rw-r--r--adept/icons/cr48-action-adept_remove.pngbin0 -> 1164 bytes
-rw-r--r--adept/icons/cr48-action-adept_sourceseditor.pngbin0 -> 3645 bytes
-rw-r--r--adept/icons/cr48-action-adept_update.pngbin0 -> 4229 bytes
-rw-r--r--adept/icons/cr48-action-adept_upgrade.pngbin0 -> 2802 bytes
-rw-r--r--adept/icons/cr48-action-extender_closed.pngbin0 -> 2535 bytes
-rw-r--r--adept/icons/cr48-action-extender_opened.pngbin0 -> 2459 bytes
-rw-r--r--adept/icons/cr64-action-adept_notifier_warning.pngbin0 -> 5963 bytes
-rw-r--r--adept/icons/crsc-action-adept_notifier_warning.svgzbin0 -> 5636 bytes
-rw-r--r--adept/installer/Makefile.am22
-rw-r--r--adept/installer/adept_installer.desktop45
-rw-r--r--adept/installer/adept_installerui.rc20
-rw-r--r--adept/installer/app.cpp416
-rw-r--r--adept/installer/app.h128
-rw-r--r--adept/installer/hi128-app-adept_installer.pngbin0 -> 14185 bytes
-rw-r--r--adept/installer/hi16-app-adept_installer.pngbin0 -> 844 bytes
-rw-r--r--adept/installer/hi22-app-adept_installer.pngbin0 -> 1258 bytes
-rw-r--r--adept/installer/hi32-app-adept_installer.pngbin0 -> 2120 bytes
-rw-r--r--adept/installer/hi48-app-adept_installer.pngbin0 -> 3713 bytes
-rw-r--r--adept/installer/hi64-app-adept_installer.pngbin0 -> 5460 bytes
-rw-r--r--adept/installer/hisc-app-adept_installer.svgzbin0 -> 10539 bytes
-rw-r--r--adept/installer/main.cpp51
-rw-r--r--adept/kubuntu_upgrader/Makefile.am11
-rw-r--r--adept/kubuntu_upgrader/errordialog.cpp48
-rw-r--r--adept/kubuntu_upgrader/errordialog.h51
-rw-r--r--adept/kubuntu_upgrader/errordialogbase.ui67
-rw-r--r--adept/kubuntu_upgrader/upgradewizard.cpp545
-rw-r--r--adept/kubuntu_upgrader/upgradewizard.h96
-rw-r--r--adept/kubuntu_upgrader/upgradewizardbase.ui143
-rw-r--r--adept/libadept/Makefile.am33
-rw-r--r--adept/libadept/acqprogress.cpp295
-rw-r--r--adept/libadept/acqprogress.h127
-rw-r--r--adept/libadept/acqprogresswidget.cpp53
-rw-r--r--adept/libadept/acqprogresswidget.h30
-rw-r--r--adept/libadept/acqprogresswidgetui.ui79
-rw-r--r--adept/libadept/actor.h43
-rw-r--r--adept/libadept/application.cpp197
-rw-r--r--adept/libadept/application.h75
-rw-r--r--adept/libadept/commitprogress.cpp115
-rw-r--r--adept/libadept/commitprogress.h41
-rw-r--r--adept/libadept/commitprogressui.ui197
-rw-r--r--adept/libadept/desktopentryui.ui116
-rw-r--r--adept/libadept/desktoplist.cpp194
-rw-r--r--adept/libadept/desktoplist.h117
-rw-r--r--adept/libadept/dpkgpm-gui.cpp258
-rw-r--r--adept/libadept/dpkgpm-gui.h68
-rw-r--r--adept/libadept/dpkgpm.cpp451
-rw-r--r--adept/libadept/dpkgpm.h49
-rw-r--r--adept/libadept/easytagfilter.cpp82
-rw-r--r--adept/libadept/easytagfilter.h93
-rw-r--r--adept/libadept/easytagfilterui.ui201
-rw-r--r--adept/libadept/extendablelist.cpp332
-rw-r--r--adept/libadept/extendablelist.h165
-rw-r--r--adept/libadept/filterlist.cpp231
-rw-r--r--adept/libadept/filterlist.h149
-rw-r--r--adept/libadept/filtersidebar.cpp71
-rw-r--r--adept/libadept/filtersidebar.h26
-rw-r--r--adept/libadept/filtersidebarui.ui119
-rw-r--r--adept/libadept/filterwidget.cpp36
-rw-r--r--adept/libadept/filterwidget.h39
-rw-r--r--adept/libadept/groupeddesktopselector.cpp137
-rw-r--r--adept/libadept/groupeddesktopselector.h39
-rw-r--r--adept/libadept/installerview.cpp88
-rw-r--r--adept/libadept/installerview.h33
-rw-r--r--adept/libadept/installerviewui.ui194
-rw-r--r--adept/libadept/lister.cpp707
-rw-r--r--adept/libadept/lister.h220
-rw-r--r--adept/libadept/listerextenderui.ui310
-rw-r--r--adept/libadept/listerpredicate.h14
-rw-r--r--adept/libadept/packagedetails.cpp253
-rw-r--r--adept/libadept/packagedetails.h55
-rw-r--r--adept/libadept/packagedetailsui.ui464
-rw-r--r--adept/libadept/packageinfo.cpp181
-rw-r--r--adept/libadept/packageinfo.h49
-rw-r--r--adept/libadept/packageinfoui.ui180
-rw-r--r--adept/libadept/progress.cpp58
-rw-r--r--adept/libadept/progress.h30
-rw-r--r--adept/libadept/quickfilter.cpp79
-rw-r--r--adept/libadept/quickfilter.h119
-rw-r--r--adept/libadept/quickfilterui.ui130
-rw-r--r--adept/libadept/sourceseditor.cpp165
-rw-r--r--adept/libadept/sourceseditor.h63
-rw-r--r--adept/libadept/sourceseditorui.ui173
-rw-r--r--adept/libadept/statefilter.cpp60
-rw-r--r--adept/libadept/statefilter.h144
-rw-r--r--adept/libadept/statefilterui.ui166
-rw-r--r--adept/libadept/tagchooser.cpp144
-rw-r--r--adept/libadept/tagchooser.h82
-rw-r--r--adept/libadept/tagfilter.cpp67
-rw-r--r--adept/libadept/tagfilter.h113
-rw-r--r--adept/libadept/tagfilterui.ui95
-rw-r--r--adept/libadept/taglist.cpp134
-rw-r--r--adept/libadept/taglist.h75
-rw-r--r--adept/libadept/threadutils.cpp44
-rw-r--r--adept/libadept/utils.h71
-rw-r--r--adept/libadept/view.cpp153
-rw-r--r--adept/libadept/view.h66
-rw-r--r--adept/manager/Makefile.am20
-rw-r--r--adept/manager/adept_manager.desktop43
-rw-r--r--adept/manager/adept_managerui.rc38
-rw-r--r--adept/manager/app.cpp450
-rw-r--r--adept/manager/app.h162
-rw-r--r--adept/manager/hi128-app-adept_manager.pngbin0 -> 26416 bytes
-rw-r--r--adept/manager/hi16-app-adept_manager.pngbin0 -> 1482 bytes
-rw-r--r--adept/manager/hi22-app-adept_manager.pngbin0 -> 2346 bytes
-rw-r--r--adept/manager/hi32-app-adept_manager.pngbin0 -> 3909 bytes
-rw-r--r--adept/manager/hi48-app-adept_manager.pngbin0 -> 6820 bytes
-rw-r--r--adept/manager/hi64-app-adept_manager.pngbin0 -> 10284 bytes
-rw-r--r--adept/manager/hisc-app-adept_manager.svgzbin0 -> 3643 bytes
-rw-r--r--adept/manager/main.cpp71
-rw-r--r--adept/notifier/15adept-periodic-update3
-rw-r--r--adept/notifier/Makefile.am26
-rw-r--r--adept/notifier/adept_notifier.desktop63
-rw-r--r--adept/notifier/adept_notifier_auto.desktop23
-rw-r--r--adept/notifier/app.cpp342
-rw-r--r--adept/notifier/app.h93
-rw-r--r--adept/tests/libcapture/celem-test.cpp34
-rw-r--r--adept/tests/libcapture/grouper-test.cpp44
-rw-r--r--adept/tests/libcapture/pkgcache-test.cpp71
-rw-r--r--adept/tests/libcapture/stl_util-test.cpp56
-rw-r--r--adept/tests/libcapture/tree-test.cpp86
-rw-r--r--adept/tests/tut-main.cpp61
-rw-r--r--adept/tests/tut.h872
-rw-r--r--adept/tests/tut_reporter.h182
-rw-r--r--adept/updater/Makefile.am21
-rw-r--r--adept/updater/adept_updater.desktop69
-rw-r--r--adept/updater/adept_updaterui.rc16
-rw-r--r--adept/updater/app.cpp275
-rw-r--r--adept/updater/app.h105
-rw-r--r--adept/updater/hi128-app-adept_updater.pngbin0 -> 27523 bytes
-rw-r--r--adept/updater/hi16-app-adept_updater.pngbin0 -> 1509 bytes
-rw-r--r--adept/updater/hi22-app-adept_updater.pngbin0 -> 2357 bytes
-rw-r--r--adept/updater/hi32-app-adept_updater.pngbin0 -> 4053 bytes
-rw-r--r--adept/updater/hi48-app-adept_updater.pngbin0 -> 7011 bytes
-rw-r--r--adept/updater/hi64-app-adept_updater.pngbin0 -> 10508 bytes
-rw-r--r--adept/updater/hisc-app-adept_updater.svgzbin0 -> 4601 bytes
-rw-r--r--adept/updater/main.cpp56
275 files changed, 24486 insertions, 0 deletions
diff --git a/adept/COPYING b/adept/COPYING
new file mode 100644
index 0000000..5ce2405
--- /dev/null
+++ b/adept/COPYING
@@ -0,0 +1,29 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of [original copyright holder] nor the names of
+ its contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/adept/Makefile.am b/adept/Makefile.am
new file mode 100644
index 0000000..d0531ef
--- /dev/null
+++ b/adept/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = kubuntu_upgrader adept installer manager updater notifier icons batch
diff --git a/adept/NEWS b/adept/NEWS
new file mode 100644
index 0000000..a3dc72a
--- /dev/null
+++ b/adept/NEWS
@@ -0,0 +1,2 @@
+good bye kapture, hello ept
+ept - kde apt frontend based on libapt-front
diff --git a/adept/TODO b/adept/TODO
new file mode 100644
index 0000000..504a439
--- /dev/null
+++ b/adept/TODO
@@ -0,0 +1,33 @@
+the 1.88 milestone:
+* the most "intrusive" changes to ui should be done at this point: the detailed
+ package view and package browsing interface, improvements to the filtering ui
+- make the filter area resize itself to fit the contained filters [done]
+- clean up individual filters (their extended state that is) [done]
+- implement a sidebar for listing available filtering options
+- implement "buckets" for wanted and unwanted tags (these are basically a
+ want/unwant anded tag filters)
+- implement drag&drop from sidebar to buckets and to filter list
+- implement shuffling of items in the filter list by d&d (needs fixes in
+ extendablelist)
+- implement detailed package view
+- implement package browsing (needs thinking)
+
+* basic pinning support in the libraries should be done (the ui will possibly
+ have to wait till beta)
+
+* the ui should be fully i18n'd
+- libapt-front needs to be i18n'd
+- strings in libept and apps need to be wrapped in i18n
+
+* skeleton of the update notifier should be done
+
+* purge and reinstall options in the UI
+- need respective options in libapt-front
+- add actions to context menu
+- think about semantics...
+
+* support for individual deb handling in the libraries (possibly without
+ ui)
+
+* at least basic support for konsole hiding (eventually without "waiting
+ for input" detection)
diff --git a/adept/adept/Makefile.am b/adept/adept/Makefile.am
new file mode 100644
index 0000000..ffec465
--- /dev/null
+++ b/adept/adept/Makefile.am
@@ -0,0 +1,35 @@
+noinst_LTLIBRARIES = libadept.la
+libadept_la_SOURCES = changelog.cpp\
+ acqprogresswidgetui.ui acqprogress.cpp \
+ tagchooser.cpp filtersidebarui.ui filtersidebar.cpp \
+ application.cpp \
+ tagfilterui.ui tagfilter.cpp taglist.cpp \
+ packageinfoui.ui packageinfo.cpp \
+ commitprogressui.ui commitprogress.cpp \
+ progress.cpp \
+ sourceseditorui.ui sourceseditor.cpp \
+ acqprogresswidget.cpp dpkgpm.cpp \
+ dpkgpm-gui.cpp \
+ extendablelist.cpp \
+ desktopentryui.ui desktoplist.cpp \
+ groupeddesktopselector.cpp \
+ packagedetailsui.ui packagedetails.cpp view.cpp \
+ listerextenderui.ui lister.cpp filterlist.cpp \
+ filterwidget.cpp \
+ quickfilterui.ui quickfilter.cpp \
+ statefilterui.ui statefilter.cpp \
+ easytagfilterui.ui easytagfilter.cpp \
+ actor.h threadutils.cpp \
+ installerviewui.ui installerview.cpp
+libadept_la_LDFLAGS = -L/usr/lib/debug $(all_libraries)
+libadept_la_LIBADD = -lapt-front $(LIBTAGCOLL2_LIBS)
+
+acqprogress.cpp: acqprogress.moc
+
+INCLUDES = -I$(srcdir)/.. -I.. $(all_includes) $(LIBEPT_CFLAGS) $(LIBTAGCOLL2_CFLAGS) $(LIBAPT_FRONT_CFLAGS) $(LIBWIBBLE_CFLAGS)
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII -DDEFAULT_KONSOLE_HIDDEN=true
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/libept.pot
diff --git a/adept/adept/acqprogress.cpp b/adept/adept/acqprogress.cpp
new file mode 100644
index 0000000..4b0643f
--- /dev/null
+++ b/adept/adept/acqprogress.cpp
@@ -0,0 +1,295 @@
+// -*- C++ -*-
+
+#include <qprogressbar.h>
+#include <klistview.h>
+#include <kapplication.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "acqprogress.h"
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/acquire-worker.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/configuration.h>
+
+#include <adept/utils.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <iostream>
+
+#define _(a...) (a) // XXX
+
+using namespace std;
+
+namespace adept {
+
+AcqStatus::Item::Item (KListView *parent, pkgAcquire::ItemDesc &item, bool hit)
+: KListViewItem( parent )
+{
+ m_pbcol = 0;
+ m_prog = new ItemProgress( 0, 0 );
+ m_prog->setStatus( "waiting" );
+ m_prog->setTotalSteps( 100 );
+ m_item = item;
+ m_id = m_item.Owner->ID;
+ /* if (item.Owner->FileSize > 0)
+ setText( 1, SizeToStr( item.Owner->FileSize ).c_str() + QString( "B" ) ); */
+ setText( 1, u8( item.Description ) );
+ // cerr << "create: id = " << item . Owner -> ID << ", myId = " << m_item . Owner -> ID << endl;
+ if (hit) {
+ m_prog->setStatus( "hit" );
+ } else
+ m_prog->setStatus( "waiting" );
+ // QString (SizeToStr (Itm.Owner -> FileSize) . c_str ()) + QString ("B"),
+ // /* QString (Itm . Owner -> ID) + */ QString (Itm.Description . c_str ()));
+}
+
+AcqStatus::Item::~Item ()
+{
+ delete m_prog;
+}
+
+int AcqStatus::Item::compare (QListViewItem *i, int /*col*/, bool /*ascend*/) const
+{
+ int id1 = m_id;
+ int id2 = ((Item *) i) -> m_id;
+ return (id2 >= id1) - (id2 <= id1);
+}
+
+void AcqStatus::Item::pulse (pkgAcquire::Worker *w)
+{
+ if (w) {
+ if (w->TotalSize)
+ setStatus( "progress", long( double(
+ w -> CurrentSize * 100.0)
+ / double( w->TotalSize ) ) );
+ else
+ setStatus( "downloading", 0 );
+ }
+}
+
+void AcqStatus::Item::setStatus( const std::string &s, int i )
+{
+ m_prog->setStatus( s, i );
+}
+
+void AcqStatus::Item::paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+
+ if ( column == m_pbcol ) {
+ const QRect bar = QRect( 0, 0, width, height() );
+ m_prog->resize( width, height() );
+ QPixmap pm = QPixmap::grabWidget( m_prog );
+ // p->fillRect( bar, listView()->paletteBackgroundColor() );
+ p->drawPixmap( bar.x(), bar.y(), pm );
+ } else {
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ _cg.setColor( QColorGroup::Text, c );
+ KListViewItem::paintCell( &_p, _cg, column, width, alignment );
+ p->drawPixmap( 0, 0, pm );
+ }
+}
+
+AcqStatus::Item *AcqStatus::findItem (pkgAcquire::ItemDesc &Itm)
+{
+ if ( Itm.Owner->ID < m_idOffset )
+ return 0;
+ if ( Itm.Owner->ID - m_idOffset >= m_items.size() )
+ return 0;
+ return m_items[ Itm.Owner->ID - m_idOffset ];
+}
+
+AcqStatus::AcqStatus(QWidget *parent, const char *name)
+ : KListView (parent, name), m_idOffset( 0 ), m_continue( true )
+{
+ // m_lastItem = 0;
+ addColumn( i18n( "Progress" ) );
+ addColumn( i18n( "Description" ) );
+ setSorting (1);
+ setColumnWidth (0, 220);
+ setColumnWidth (1, 300);
+ setResizeMode (LastColumn);
+ ID = 0;
+}
+
+void AcqStatus::Done (pkgAcquire::ItemDesc &Itm)
+{
+ Item *i = findItem (Itm);
+ if (i) {
+ i->setStatus( "done" );
+ }
+ emit statusChanged( StWaiting );
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+}
+
+void AcqStatus::clear()
+{
+ KListView::clear();
+ m_idOffset += m_items.size();
+ m_items.clear(); // got deleted by klistview already
+}
+
+void AcqStatus::Start()
+{
+ clear();
+ pkgAcquireStatus::Start();
+ kdDebug() << "AcqStatus::Start ()" << endl;
+ _config -> Set ("APT::Fetcher::Select-Timeout-Usec", 100000);
+ emit statusChanged( StWaiting );
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+}
+
+void AcqStatus::IMSHit(pkgAcquire::ItemDesc &Itm)
+{
+ Itm.Owner->ID = ID++;
+ Item *i = new Item( this, Itm, true );
+ // ensureItemVisible( i );
+ i->setStatus( "hit" );
+ m_items.push_back( i );
+
+ kdDebug() << "imshit called on ID = " << ID - 1 << " i = " << (void *)i << endl;
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+};
+
+void AcqStatus::Fetch(pkgAcquire::ItemDesc &Itm)
+ // an item started to download
+{
+ Update = true;
+ if (Itm.Owner->Complete == true) // XXX?
+ return;
+
+ Itm.Owner->ID = ID++;
+
+ Item *i = new Item( this, Itm );
+ // ensureItemVisible( i );
+ m_items.push_back( i );
+
+ kdDebug() << "fetch called on ID = " << ID - 1 << " i = " << (void *)i << endl;
+ emit statusChanged( StDownloading );
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+};
+
+void AcqStatus::Fail(pkgAcquire::ItemDesc &Itm)
+ // item failed to download
+{
+ kdDebug() << "fail, status = " << Itm.Owner->Status
+ << " ID = " << Itm.Owner->ID << endl;
+ // Ignore certain kinds of transient failures (bad code)
+ if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) {
+ kdDebug() << "fail with StatIdle, ignoring" << endl;
+ return;
+ }
+
+ Item *i = findItem (Itm);
+ kdDebug() << "fail, i = " << i << endl;
+ if (! i)
+ return;
+ if (Itm.Owner->Status == pkgAcquire::Item::StatDone) {
+ i->setStatus( "ignored" );
+ } else {
+ i->setStatus( "error" );
+ }
+
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+};
+
+void AcqStatus::Stop()
+{
+ pkgAcquireStatus::Stop();
+ emit statusChanged( StDone );
+ triggerUpdate ();
+ KApplication::kApplication()->processEvents();
+}
+
+bool AcqStatus::Pulse(pkgAcquire *Owner)
+{
+ pkgAcquireStatus::Pulse(Owner);
+
+ for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
+ I = Owner->WorkerStep(I)) {
+ if (I -> CurrentItem) {
+ Item *i = findItem (* (I -> CurrentItem));
+ if (i)
+ i -> pulse (I);
+ }
+ }
+
+ triggerUpdate ();
+ // repaint ();
+
+ if (TotalBytes > 0)
+ emit totalProgress(
+ long( double(
+ (CurrentBytes +
+ CurrentItems)*100.0)/double(TotalBytes+TotalItems) ) );
+ else
+ emit totalProgress (-1);
+ KApplication::kApplication () -> processEvents ();
+
+ if ( m_continue )
+ return true;
+
+ m_continue = true;
+ return false;
+}
+
+bool AcqStatus::MediaChange(string Media,string Drive)
+{
+ int res = KMessageBox::warningContinueCancel(
+ this, i18n( "Please insert the disc "
+ "labeled '%1' in the drive "
+ "'%2' and press enter" ).arg(
+ u8( Media ) ).arg( u8( Drive ) ),
+ i18n( "Media Change" ) );
+ if ( res == KMessageBox::Cancel )
+ cancel();
+ return true;
+}
+
+void AcqStatus::cancel()
+{
+ m_continue = false;
+}
+
+AcqStatusDialog::AcqStatusDialog (QWidget *parent, const char *name, bool modal)
+ : KDialogBase( parent, name, modal,
+ u8( "progress dialog (FIXME: waiting for headers, done)" ),
+ Ok|Cancel, Cancel, true )
+{
+ m_status = new AcqStatus (this, "");
+ setMainWidget( m_status.data() );
+ enableButton (Ok, false);
+ connect (m_status.data(), SIGNAL (statusChanged (AcqStatus::Status)),
+ this, SLOT (statusChange (AcqStatus::Status)));
+}
+
+void AcqStatusDialog::statusChange (AcqStatus::Status st)
+{
+ if (st == AcqStatus::StDownloading || st == AcqStatus::StWaiting) {
+ enableButton (Ok, false);
+ // XXX: cancel should be true; but needs implementation first
+ enableButton (Cancel, false);
+ } else if (st == AcqStatus::StDone) {
+ enableButton (Ok, true);
+ enableButton (Cancel, false);
+ }
+}
+
+}
+
+#include "acqprogress.moc"
diff --git a/adept/adept/acqprogress.h b/adept/adept/acqprogress.h
new file mode 100644
index 0000000..9510825
--- /dev/null
+++ b/adept/adept/acqprogress.h
@@ -0,0 +1,127 @@
+/** -*- C++ -*-
+ @file adept/acqprogress.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#ifndef ACQPROGRESS_H
+#define ACQPROGRESS_H
+
+#include <klocale.h>
+#include <kdialogbase.h>
+#include <klistview.h>
+#include <kprogress.h>
+
+#include <vector>
+#include <apt-pkg/acquire.h>
+#include <apt-front/progresscallback.h>
+
+class AcqStatus;
+class QLabel;
+class QProgressBar;
+class QSpacer;
+class QGridLayout;
+
+namespace adept {
+
+class AcqStatus : public KListView, public aptFront::ProgressCallback
+{
+ Q_OBJECT
+protected:
+ class ItemProgress: public KProgress {
+ public:
+ ItemProgress( QWidget *parent, const char *name = 0 )
+ : KProgress( parent, name ), m_spin( 0 ) {}
+ void setStatus( const std::string &s,
+ int prog = 0 ) {
+ m_status = s;
+ if (m_status == "hit"
+ || m_status == "ignored"
+ || m_status == "done")
+ prog = 100;
+ if (m_status == "waiting") {
+ prog = 0;
+ }
+ if (m_status == "progress" && prog != 100)
+ setFormat( i18n( "downloading (%p%)" ) );
+ else if (prog == 100) // who cares about hit/ignore anyway?
+ setFormat( i18n( "done (%p%)" ) );
+ else
+ setFormat( m_status );
+ setProgress( prog );
+ }
+ protected:
+ std::string m_status;
+ int m_spin;
+ };
+ class Item : public KListViewItem {
+ protected:
+ ItemProgress *m_prog;
+ int m_pbcol;
+ unsigned long m_id;
+ pkgAcquire::ItemDesc m_item;
+
+ public:
+ Item (KListView *parent, pkgAcquire::ItemDesc &item,
+ bool hit = false);
+ virtual ~Item ();
+
+ virtual void paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment);
+
+ void setProgress (int);
+ virtual int compare (QListViewItem *i, int col, bool ascend) const;
+ virtual void pulse (pkgAcquire::Worker *);
+ void setStatus( const std::string &, int = 0 );
+
+ void setup() {
+ KListViewItem::setup();
+ setHeight( height() + 6 );
+ }
+ };
+ unsigned long ID;
+ unsigned long m_idOffset;
+ std::vector <Item *> m_items;
+ bool m_continue;
+
+public:
+
+ enum Status { StWaiting, StDownloading, StDone };
+
+ AcqStatus (QWidget *parent, const char *name);
+ Item *findItem (pkgAcquire::ItemDesc &Itm);
+
+ virtual bool MediaChange (string Media,string Drive);
+ virtual void IMSHit (pkgAcquire::ItemDesc &Itm);
+ virtual void Fetch (pkgAcquire::ItemDesc &Itm);
+ virtual void Done (pkgAcquire::ItemDesc &Itm);
+ virtual void Fail (pkgAcquire::ItemDesc &Itm);
+ virtual void Start ();
+ virtual void Stop ();
+ void addLine (QWidget *l, QWidget *s, QWidget *prog);
+ void clear();
+
+ bool Pulse (pkgAcquire *Owner);
+
+public slots:
+ void cancel();
+
+signals:
+ void statusChanged (AcqStatus::Status st);
+ void totalProgress (int percent);
+
+ //AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet);
+};
+
+class AcqStatusDialog : public KDialogBase
+{
+ Q_OBJECT
+protected:
+ aptFront::SharedPtr<AcqStatus> m_status;
+public:
+ aptFront::SharedPtr<aptFront::ProgressCallback> callback() { return m_status.data(); };
+ AcqStatusDialog (QWidget *parent, const char *name, bool modal);
+public slots:
+ void statusChange (AcqStatus::Status st);
+};
+}
+#endif
diff --git a/adept/adept/acqprogresswidget.cpp b/adept/adept/acqprogresswidget.cpp
new file mode 100644
index 0000000..dd02f03
--- /dev/null
+++ b/adept/adept/acqprogresswidget.cpp
@@ -0,0 +1,53 @@
+#include <kprogress.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include "acqprogresswidget.h"
+#include "acqprogress.h"
+
+using namespace adept;
+
+AcqProgressWidget::AcqProgressWidget( QWidget *parent, const char *name )
+ : AcqProgressWidgetUi( parent, name )
+{
+ m_statusRef = m_status;
+ m_progress->setTotalSteps( 100 );
+ m_progress->setProgress( 0 );
+ connect(m_status, SIGNAL( totalProgress( int ) ),
+ this, SLOT( setProgress( int ) ) );
+ connect(m_status, SIGNAL( statusChanged( AcqStatus::Status ) ),
+ this, SLOT( statusChange( AcqStatus::Status ) ) );
+ connect( m_cancel, SIGNAL( clicked() ),
+ m_status, SLOT( cancel() ) );
+}
+
+void AcqProgressWidget::statusChange( AcqStatus::Status s )
+{
+ QString t;
+ switch (s) {
+ case AcqStatus::StWaiting:
+ t = i18n( "Waiting for headers (%p%)" );
+ break;
+ case AcqStatus::StDownloading:
+ t = i18n( "Downloading (%p%)" );
+ break;
+ case AcqStatus::StDone:
+ t = i18n( "Done (%p%)" );
+ m_progress->setProgress( 100 );
+ break;
+ }
+ m_progress->setFormat( t );
+}
+
+void AcqProgressWidget::setProgress( int p )
+{
+ if (p < 0) {
+ m_progress->setTotalSteps( 0 );
+ m_progress->setProgress( m_progress->progress() + 1 );
+ } else {
+ m_progress->setTotalSteps( 100 );
+ m_progress->setProgress( p );
+ }
+}
+
+#include "acqprogresswidget.moc"
diff --git a/adept/adept/acqprogresswidget.h b/adept/adept/acqprogresswidget.h
new file mode 100644
index 0000000..54359c7
--- /dev/null
+++ b/adept/adept/acqprogresswidget.h
@@ -0,0 +1,30 @@
+/** -*- C++ -*-
+ @file adept/acqprogresswidget.h
+ @author Peter Rockai <me@mornfall.net>
+ @todo Close button!
+*/
+
+#ifndef PROGRESSWIDGET_H
+# define PROGRESSWIDGET_H
+
+#include <adept/acqprogresswidgetui.h>
+#include <adept/acqprogress.h>
+
+namespace adept {
+
+class AcqProgressWidget : public AcqProgressWidgetUi {
+ Q_OBJECT
+public:
+ AcqProgressWidget (QWidget *parent = 0, const char *name = 0);
+ aptFront::SharedPtr<aptFront::ProgressCallback> callback() { return m_statusRef.data(); };
+public slots:
+ void statusChange( AcqStatus::Status );
+ void setProgress( int );
+protected:
+ aptFront::SharedPtr<AcqStatus> m_statusRef;
+};
+
+}
+
+#endif /* ifndef PROGRESSWIDGET_H */
+
diff --git a/adept/adept/acqprogresswidgetui.ui b/adept/adept/acqprogresswidgetui.ui
new file mode 100644
index 0000000..26baa21
--- /dev/null
+++ b/adept/adept/acqprogresswidgetui.ui
@@ -0,0 +1,79 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::AcqProgressWidgetUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>adept::AcqProgressWidgetUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>705</width>
+ <height>289</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Download Progress</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::AcqStatus" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_status</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>150</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="KProgress" row="1" column="0">
+ <property name="name">
+ <cstring>m_progress</cstring>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>m_cancel</cstring>
+ </property>
+ <property name="text">
+ <string>Cancel Download</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::AcqStatus</class>
+ <header location="global">acqprogress.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/acqprogress.h</includehint>
+ <includehint>kprogress.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/actor.h b/adept/adept/actor.h
new file mode 100644
index 0000000..115b202
--- /dev/null
+++ b/adept/adept/actor.h
@@ -0,0 +1,43 @@
+/** -*- C++ -*-
+ @file adept/actor.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qobject.h>
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/actor.h>
+
+#ifndef EPT_ACTOR_H
+#define EPT_ACTOR_H
+
+namespace adept {
+
+using namespace aptFront;
+
+class EntityActor : public QObject
+{
+ Q_OBJECT
+public:
+ EntityActor( actor::Bound< cache::entity::Entity > a )
+ : m_actor( a ), m_dead( false )
+ {}
+ actor::Bound< cache::entity::Entity > actor() const {
+ return m_actor;
+ }
+public slots:
+ void act() { m_actor(); }
+ void destructiveAct() {
+ // in case we don't get deleted soon enough
+ if ( m_dead ) return;
+ m_dead = true;
+ act();
+ deleteLater();
+ }
+protected:
+ actor::Bound< cache::entity::Entity > m_actor;
+ bool m_dead;
+};
+
+}
+
+#endif
diff --git a/adept/adept/application.cpp b/adept/adept/application.cpp
new file mode 100644
index 0000000..5f2eb2a
--- /dev/null
+++ b/adept/adept/application.cpp
@@ -0,0 +1,350 @@
+/** -*- C++ -*-
+ @file adept/application.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qprocess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kstatusbar.h>
+#include <kdebug.h>
+
+#include <apt-front/init.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/component/state.h>
+
+#include <adept/commitprogress.h>
+#include <adept/application.h>
+#include <adept/packageinfo.h>
+#include <adept/progress.h>
+#include <adept/utils.h>
+
+namespace adept {
+using namespace cache;
+
+#ifdef KUBUNTU
+#include <qstringlist.h>
+#define DPKG_FIXER_ARGS QStringList::split(QString(" "), QString("dpkg --configure -a"), false)
+
+DpkgFixer::DpkgFixer(struct Application* parent)
+ : m_parent(parent)
+{
+ m_fixer = 0;
+ m_waiter = 0;
+ m_output = "";
+ m_done = false;
+}
+
+DpkgFixer::~DpkgFixer()
+{
+ if (m_fixer != 0) {
+ delete m_fixer;
+ }
+ if (m_waiter != 0) {
+ delete m_waiter;
+ }
+
+ std::cout << "Got output " << m_output.latin1() << std::endl;
+}
+
+void DpkgFixer::fixDpkgLock()
+{
+ kdDebug() << "Asking user if they would like to fix dpkg lock..." << endl;
+ int decision = KMessageBox::warningYesNoCancel(m_parent->mainWindow(),
+ i18n("Another process is using the packaging system database "
+ "(probably some other Adept application or apt-get or "
+ "aptitude).\nWould you like to attempt to resolve this problem? "
+ "No will enter read-only mode and Cancel to quit and resolve "
+ "this issue yourself."),
+ i18n( "Database Locked" ) );
+ switch (decision) {
+ case KMessageBox::Yes:
+ kdDebug() << "User opted to fix the dpkg database. Trying to run the process..." << endl;
+ cache::Global::get().close();
+ // Call the dpkg fixer.
+ m_fixer = new QProcess(dynamic_cast<QObject*>(this));
+ m_fixer->setArguments(DPKG_FIXER_ARGS);
+
+ // Handle when the process exits
+ connect(dynamic_cast<QObject*>(m_fixer), SIGNAL( processExited() ),
+ dynamic_cast<QObject*>(this), SLOT( retryOpen() ));
+
+ // Handle when the process has stdout output
+ connect(dynamic_cast<QObject*>(m_fixer), SIGNAL( readyReadStdout() ),
+ dynamic_cast<QObject*>(this), SLOT( handleStdout() ));
+
+ // Handle when the process has stderr output
+ connect(dynamic_cast<QObject*>(m_fixer), SIGNAL( readyReadStderr() ),
+ dynamic_cast<QObject*>(this), SLOT( handleStderr() ));
+
+ // Fire off the waiter...
+ m_waiter = new KProgressDialog(m_parent->mainWindow(), "waiter",
+ i18n("Unlocking; Please Wait..."), i18n("Unlocking dpkg database; Please wait..."));
+ m_waiter->setAllowCancel(false);
+ m_waiter->show();
+
+ m_fixer->start();
+ kdDebug() << "dpkg fixer fired off." << endl;
+
+ break;
+
+ case KMessageBox::Cancel:
+ kdDebug() << "User opted to cancel and repair manually." << endl;
+ exit(1);
+ break;
+
+ default:
+ kdDebug() << "User opted to continue in read-only mode." << endl;
+ m_parent->updateStatusbar();
+ m_parent->cacheOpenedNowFinishInit();
+ break;
+ }
+
+ return;
+}
+
+void DpkgFixer::retryOpen()
+{
+ kdDebug() << "Retrying the open..." << endl;
+ m_waiter->setLabel(i18n("Reopening the dpkg database..."));
+ m_waiter->progressBar()->setValue(50);
+ try {
+ if (!m_fixer->normalExit()) {
+ kdDebug() << "The fixer command did not exit normally. Throwing exception." << endl;
+ throw 0;
+ }
+
+ kdDebug() << "The fixer command exited normally, trying to reopen the database." << endl;
+ cache::Global::get().open( m_parent->openFlags() );
+ } catch (...) {
+ KMessageBox::information(m_parent->mainWindow(),
+ i18n( "Failed to unlock the database. "
+ "Please try to resolve this issue. "
+ "`sudo dpkg --configure -a` may help." ),
+ i18n( "Unlock Failed." ) );
+ exit( 1 );
+ }
+
+ m_waiter->progressBar()->setValue(100);
+ m_waiter->close();
+ m_parent->updateStatusbar();
+ m_parent->cacheOpenedNowFinishInit();
+}
+
+void DpkgFixer::outputUpdated()
+{
+}
+
+void DpkgFixer::handleStdout()
+{
+// m_output += m_fixer->readStdout();
+// outputUpdated();
+}
+
+void DpkgFixer::handleStderr()
+{
+// m_output += m_fixer->readStderr();
+// outputUpdated();
+}
+#endif // KUBUNTU
+
+Application::Application()
+ : m_acceptReadOnly( false ), m_main( 0 ), m_history( 0 ), m_statusBar( 0 )
+{
+#ifdef KUBUNTU
+ m_dpkgfixer = 0;
+#endif // KUBUNTU
+}
+
+Application::~Application()
+{
+#ifdef KUBUNTU
+ if (m_dpkgfixer != 0) {
+ delete m_dpkgfixer;
+ }
+#endif // KUBUNTU
+}
+
+void Application::openCache( unsigned flags )
+{
+ m_flags = flags;
+ bool ro = m_acceptReadOnly;
+ bool root = ::getuid() == 0 || ::geteuid() == 0;
+
+ try {
+ cache::Global::get().open( m_flags );
+ } catch (...) {
+ try {
+ cache::Global::get().open( m_flags | Cache::OpenReadOnly );
+ if ( ro && root ) {
+#ifndef KUBUNTU
+ kdDebug() << "ro && root -- Database locked." << endl;
+ KMessageBox::information(
+ m_main, i18n(
+ "You will not be able to change your system settings "
+ "in any way (install, remove or upgrade software), "
+ "because another process is using the packaging system database "
+ "(probably some other Adept application or apt-get or "
+ "aptitude). Please close the other application before "
+ "using this one." ),
+ i18n( "Read Only mode: Database Locked" ) );
+#else
+ kdDebug() << "Firing off the Kubuntu dpkg database lock fixer..." << endl;
+ m_dpkgfixer = new DpkgFixer(this);
+ m_dpkgfixer->fixDpkgLock();
+ return;
+#endif // KUBUNTU
+ } else if ( !root && ro ) {
+ kdDebug() << "!root && ro -- Need root privileges." << endl;
+ KMessageBox::information(
+ m_main, i18n(
+ "You will not be able to change your system settings "
+ "in any way (install, remove or upgrade software), "
+ "because this application needs special administrator "
+ "(root) privileges. Please run it as root or "
+ "through kdesu or sudo programs to be able to perform "
+ "these actions" ),
+ i18n( "Read Only mode: Need root privileges" ) );
+ } else if ( root && !ro ) {
+#ifndef KUBUNTU
+ kdDebug() << "root && !ro -- Database locked." << endl;
+ KMessageBox::information(m_main,
+ i18n("Another process is using the packaging system database "
+ "(probably some other Adept application or apt-get or "
+ "aptitude). Please close the other application before "
+ "using this one." ),
+ i18n( "Read Only mode: Database Locked" ) );
+#else
+ kdDebug() << "Firing off the Kubuntu dpkg database lock fixer..." << endl;
+ m_dpkgfixer = new DpkgFixer(this);
+ m_dpkgfixer->fixDpkgLock();
+ return;
+#endif // KUBUNTU
+ } else if ( !root && !ro ) {
+ kdDebug() << "!root && !ro -- Needs root privileges." << endl;
+ KMessageBox::information(
+ m_main, i18n( "This application needs special administrator "
+ "(root) privileges. Please run it as root or "
+ "through kdesu or sudo programs" ),
+ i18n( "Need root privileges" ) );
+ }
+ if ( !ro ) {
+ kdDebug() << "cannot continue, exiting" << endl;
+ exit( 1 );
+ }
+ } catch (...) {
+ KMessageBox::sorry(
+ m_main, i18n(
+ "The APT Database could not be opened!"
+ " This may be caused by incorrect APT configuration"
+ " or some similar problem. Try running apt-setup and"
+ " apt-get update in terminal and see if it helps"
+ " to resolve the problem." ), i18n( "Could not open cache" ));
+ exit( 1 );
+ }
+ }
+
+ updateStatusbar();
+ cacheOpenedNowFinishInit();
+}
+
+void Application::initHistory() {
+ cache::Global::get().addComponent(
+ m_history = new History() );
+}
+
+void Application::initKDEDebconf()
+{
+ // xxx unhardcode the package name somehow?
+ if (cache::Global::get().packages()
+ .packageByName( "libqt-perl" ).isInstalled())
+ putenv( "DEBIAN_FRONTEND=kde" );
+}
+
+void Application::initialize()
+{
+ CommitProgress::initSystem();
+ aptFront::init();
+ openCache();
+}
+
+void Application::cacheOpenedNowFinishInit() {
+ initKDEDebconf();
+ initHistory();
+ observeComponent< component::State >();
+
+ initFinished();
+}
+
+void Application::checkpoint() {
+ if ( !history() ) return;
+ setHistoryEnabled( false );
+ history()->checkpoint();
+ setHistoryEnabled( true );
+}
+
+void Application::undo() {
+ if ( !history() ) return;
+ setHistoryEnabled( false );
+ history()->undo();
+ setHistoryEnabled( true );
+}
+
+void Application::redo() {
+ if ( !history() ) return;
+ setHistoryEnabled( false );
+ history()->redo();
+ setHistoryEnabled( true );
+}
+
+QString Application::changeString() {
+ component::State &s = cache().state();
+ return i18n( " Install %1, upgrade %2, remove %3 " )
+ .arg( s.newInstallCount() ).arg( s.upgradeCount() )
+ .arg( s.removeCount() );
+}
+
+QString Application::statusString() {
+ component::State &s = cache().state();
+ return i18n( " %1 installed, %2 upgradable, %3 available " )
+ .arg( s.installedCount() ).arg( s.upgradableCount() )
+ .arg( s.availableCount() );
+}
+
+QString Application::sizesString() {
+ QString dl = cache().state().downloadSizeString();
+ QString inst = cache().state().installSizeString();
+ return i18n( " download: %1, installation: %2 " ).arg( dl ).arg( inst );
+}
+
+void Application::setStatusBar( KStatusBar *s ) {
+ m_statusBar = s;
+ if ( s ) {
+ s->message( i18n( "Initializing..." ) );
+ s->insertItem( u8( "" ), 0 );
+ s->insertItem( u8( "" ), 1 );
+ s->insertItem( u8( "" ), 2 );
+ adjustFontSize( s, -1 );
+
+ adept::Progress *pr = new adept::Progress();
+ pr->setStatusBar( s );
+ cache::Global::get().setProgress( pr );
+ }
+}
+
+void Application::notifyPostChange( component::Base * )
+{
+ updateStatusbar();
+}
+
+void Application::updateStatusbar()
+{
+ if ( m_statusBar ) {
+ m_statusBar->changeItem( changeString(), 0 );
+ m_statusBar->changeItem( statusString(), 1 );
+ m_statusBar->changeItem( sizesString(), 2 );
+ }
+}
+
+}
diff --git a/adept/adept/application.h b/adept/adept/application.h
new file mode 100644
index 0000000..0416b70
--- /dev/null
+++ b/adept/adept/application.h
@@ -0,0 +1,102 @@
+/** -*- C++ -*-
+ @file adept/application.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <vector>
+
+#include <qobject.h>
+#include <qprocess.h>
+#include <kprogress.h>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+
+#ifndef EPT_APPLICATION_H
+#define EPT_APPLICATION_H
+
+#define KUBUNTU
+
+class KStatusBar;
+
+namespace adept {
+using namespace aptFront;
+using cache::Cache;
+
+class Lister;
+
+#ifdef KUBUNTU
+class DpkgFixer : public QObject {
+ Q_OBJECT;
+public:
+ DpkgFixer(struct Application* app);
+ ~DpkgFixer();
+
+ bool done() { return m_done; };
+public slots:
+ void fixDpkgLock();
+
+
+protected slots:
+ void retryOpen();
+ void outputUpdated();
+ void handleStdout();
+ void handleStderr();
+
+protected:
+ QProcess* m_fixer;
+ Application* m_parent;
+ QString m_output;
+ KProgressDialog* m_waiter;
+ bool m_done;
+};
+#endif // KUBUNTU
+
+struct Application : cache::Observer {
+ Application();
+ ~Application();
+ void setAcceptReadOnly( bool ro ) { m_acceptReadOnly = ro; }
+ bool writeable() { return cache::Global::get().writeable(); }
+ Cache &cache() { return cache::Global::get(); }
+ void openCache( unsigned flags = Cache::OpenDefault | Cache::OpenDebtags );
+ void initialize();
+ void cacheOpenedNowFinishInit();
+ void initKDEDebconf();
+ void initHistory();
+ void setMainWidget( QWidget *w ) { m_main = w; }
+ void setStatusBar( KStatusBar *s );
+ void updateStatusbar();
+ virtual void initFinished() { return; };
+ virtual void checkpoint();
+ virtual void undo();
+ virtual void redo();
+
+ int test_this_shit;
+
+ virtual void notifyPostChange( cache::component::Base * );
+
+ QString changeString();
+ QString statusString();
+ QString sizesString();
+ QWidget* mainWindow() { return m_main; };
+ unsigned openFlags() { return m_flags; };
+
+protected:
+ virtual void setHistoryEnabled( bool ) {}
+ typedef cache::component::History< cache::component::State > History;
+ virtual History *history() { return m_history; }
+ bool m_acceptReadOnly;
+ unsigned m_flags;
+ QWidget *m_main;
+ KStatusBar *m_statusBar;
+ History *m_history;
+
+#ifdef KUBUNTU
+ DpkgFixer* m_dpkgfixer;
+#endif // KUBUNTU
+};
+
+}
+
+#endif
diff --git a/adept/adept/changelog.cpp b/adept/adept/changelog.cpp
new file mode 100644
index 0000000..5dd47ed
--- /dev/null
+++ b/adept/adept/changelog.cpp
@@ -0,0 +1,145 @@
+/* -*- C++ -*- */
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qhttp.h>
+#include <qbuffer.h>
+
+#include <kdebug.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+
+#include <adept/lister.h>
+
+#include "changelog.h"
+
+using namespace adept;
+
+#ifdef KUBUNTU
+ItemChangelog::ItemChangelog() {
+ connect(this, SIGNAL( changelogNeeded() ),
+ this, SLOT( requestChangelog() ));
+ m_http = 0;
+ m_content_catcher = 0;
+}
+
+ItemChangelog::~ItemChangelog() {
+ if (m_http != 0) {
+ delete m_http;
+ }
+ if (m_content_catcher != 0) {
+ delete m_content_catcher;
+ }
+}
+
+/*
+ * So this method is *very* specific to the ubuntu package
+ * changelog repository. If you want to modify this to meet the needs
+ * of another distro, you may want to implement your own method here.
+ */
+QString ItemChangelog::changelogUrl() {
+ // The list of known sections...
+ QStringList knownSections(QString("main"));
+ knownSections += QString("multiverse");
+ knownSections += QString("restricted");
+ knownSections += QString("universe");
+
+ // The parts of the package that form the URL...
+ QStringList pkgParts( QString(BASE_CHANGELOG_URL) );
+ QStringList sectionParts;
+ QString section;
+ QString urlBase;
+ QString pkgName;
+ bool found = false;
+
+ try {
+ if (&m_pkg == 0x0) {
+ throw 0;
+ }
+ std::string theSection(m_pkg.section(std::string("/")));
+ if (!theSection.length()) {
+ throw 0;
+ }
+ //// Get the section
+ section = QString( theSection );
+ /* now convert the section into something
+ usable for the changelog URL. */
+ sectionParts = QStringList::split(QString("/"), section);
+
+ /* If we have more than one piece, that means we've got a
+ non-main repo. Let's make sure it's one we can use. */
+ if (sectionParts.size() > 1) {
+ // Walk through known sections
+ for (QStringList::Iterator it = knownSections.begin();
+ it != knownSections.end(); ++it) {
+ // If we found it, let's say we found it.
+ if (sectionParts[0] == *it) {
+ pkgParts += sectionParts[0];
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return QString::null; // didn't find the repo!
+ }
+ } else {
+ pkgParts += QString("main");
+ }
+
+ //// Get the package name and prefix
+ pkgName += QString( m_pkg.source() );
+ pkgParts += QString(pkgName[0]);
+ pkgParts += pkgName;
+
+ //// Get the version string.
+ QString version = QString( m_pkg.candidateVersion().versionString() );
+ int epoch = version.find(':');
+ if (epoch > -1) {
+ version = version.mid(epoch + 1);
+ }
+ pkgName += "_" + version;
+ pkgParts += pkgName;
+ pkgParts += QString("changelog");
+
+ return pkgParts.join(QString("/"));
+ } catch (...) {
+ kdDebug() << "GOT ME AN EXCEPTION!!!! THIS IS NOT GOOD!!!!";
+ }
+
+ return QString::null;
+}
+
+void ItemChangelog::requestChangelog() {
+// emit changelogReady(changelogUrl());
+
+// return;
+
+ /* Removing temporarilly */
+ m_http = new QHttp(QString(BASE_CHANGELOG_HOST),
+ BASE_CHANGELOG_PORT,
+ this, "changelog_loader");
+ connect(dynamic_cast<QObject*>(m_http), SIGNAL( requestFinished(int,bool) ),
+ dynamic_cast<QObject*>(this), SLOT( contentReady(int,bool) ));
+ m_content_catcher = new QBuffer();
+ QString theUrl( changelogUrl() );
+
+ if ( theUrl == QString::null ) {
+ emit changelogReady(QString("No change log found."));
+ } else {
+ m_http->get( changelogUrl(), dynamic_cast<QIODevice*>(m_content_catcher) );
+ }
+}
+
+void ItemChangelog::contentReady( int id, bool error ) {
+ QString msg("Unable to fetch the Developer Changelog.");
+
+ if (!error) {
+ msg = QString( m_content_catcher->buffer() );
+ } else {
+ msg += ": " + m_http->errorString();
+ }
+
+ emit changelogReady( msg );
+}
+
+#endif /*KUBUNTU*/
diff --git a/adept/adept/changelog.h b/adept/adept/changelog.h
new file mode 100644
index 0000000..8db861b
--- /dev/null
+++ b/adept/adept/changelog.h
@@ -0,0 +1,45 @@
+/* -*- C++ -*- */
+#ifndef CHANGELOG_H
+#define CHANGELOG_H
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qhttp.h>
+#include <qbuffer.h>
+
+#include <adept/lister.h>
+
+#ifdef KUBUNTU
+#define BASE_CHANGELOG_HOST "changelogs.ubuntu.com"
+#define BASE_CHANGELOG_PORT 80
+#define BASE_CHANGELOG_URL "/changelogs/pool"
+
+namespace adept {
+
+ class ItemChangelog : public QObject {
+ Q_OBJECT
+ public:
+ ItemChangelog();
+ ~ItemChangelog();
+
+ // Give me the changelog's URL
+ QString changelogUrl();
+ void setParent(entity::Package parent) { m_pkg = parent; }
+ signals:
+ void changelogNeeded();
+ void changelogReady(QString content);
+
+ protected slots:
+ // Give me the changelog's text
+ void requestChangelog();
+ void contentReady(int id, bool error);
+
+ protected:
+ entity::Package m_pkg;
+ QHttp* m_http;
+ QBuffer* m_content_catcher;
+ };
+}
+
+#endif /* KUBUNTU */
+#endif /*CHANGELOG_H*/
diff --git a/adept/adept/commitprogress.cpp b/adept/adept/commitprogress.cpp
new file mode 100644
index 0000000..9322e27
--- /dev/null
+++ b/adept/adept/commitprogress.cpp
@@ -0,0 +1,117 @@
+#include <cassert>
+
+#include <qwidgetstack.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <kprogress.h>
+#include <qlayout.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <ktrader.h>
+#include <klibloader.h>
+
+#include <apt-front/init.h>
+#include <adept/commitprogress.h>
+#include <adept/utils.h>
+
+using namespace adept;
+using namespace aptFront;
+
+PkgSystem *CommitProgress::s_system = 0;
+
+void CommitProgress::initSystem() {
+ CommitProgress::s_system = new PkgSystem();
+}
+
+CommitProgress::CommitProgress( QWidget *p, const char *n )
+ : CommitProgressUi( p, n )
+{
+ assert( s_system );
+ m_konsoleFrame->installEventFilter( this );
+ loadKonsole();
+ connect( s_system, SIGNAL( statusChanged( int, QString ) ),
+ this, SLOT( updateProgress( int, QString ) ) );
+ connect( m_details, SIGNAL( clicked() ),
+ this, SLOT( toggleDetails() ) );
+ m_progress->setTotalSteps( 100 );
+}
+
+bool CommitProgress::eventFilter( QObject *o, QEvent *e ) {
+ // o == m_konsoleFrame
+ if ( e->type() == QEvent::Resize ) {
+ QResizeEvent *re = dynamic_cast< QResizeEvent * >( e );
+ if ( !re ) return false;
+ m_konsole->widget()->setGeometry( 0, 0, re->size().width(), re->size().height() );
+ m_occlude->setGeometry( 0, 0, re->size().width(), re->size().height() );
+ }
+ return false;
+};
+
+void CommitProgress::toggleDetails()
+{
+ if ( !m_occlude->isVisible() ) {
+ // if ( m_stack->visibleWidget() == m_konsole->widget() ) { // hide
+ // m_stack->raiseWidget( m_emptyPage );
+ m_occlude->show();
+ m_occlude->setFocus();
+ m_bottomSpace->changeSize( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding );
+ m_details->setText( i18n( "Show Details" ) );
+ } else { // show
+ m_occlude->hide();
+ m_konsole->widget()->setFocus();
+ // m_stack->raiseWidget( m_konsole->widget() );
+ m_bottomSpace->changeSize( 10, 10, QSizePolicy::Fixed, QSizePolicy::Fixed );
+ m_details->setText( i18n( "Hide Details" ) );
+ }
+}
+
+void CommitProgress::updateProgress( int p, QString msg )
+{
+ m_operation->setText( msg );
+ m_progress->setProgress( p );
+}
+
+void CommitProgress::loadKonsole()
+{
+ if ( s_system->terminal() )
+ kdDebug() << "WARNING: Hijacking PkgSystem terminal" << endl;
+
+ KLibFactory* factory = KLibLoader::self()->factory( "libsanekonsolepart" );
+ if (!factory)
+ factory = KLibLoader::self()->factory( "libkonsolepart" );
+
+ assert( factory );
+
+ delete m_occlude;
+ m_konsole = static_cast<KParts::Part*>(
+ factory->create( m_konsoleFrame, "konsolepart", "QObject",
+ u8( "KParts::ReadOnlyPart" ) ) );
+ // m_konsole->widget()->setGeometry( QRect( 0, 0, 40, 40 ) );
+
+ m_occlude = new QFrame( m_konsoleFrame, "m_occlude" );
+ // m_occlude->setGeometry( QRect( 0, 0, 10, 10 ) );
+ m_occlude->setFrameShape( QFrame::NoFrame );
+
+ assert( terminal() );
+
+ terminal()->setAutoDestroy( false );
+ terminal()->setAutoStartShell( false );
+ // m_stack->addWidget( m_konsole->widget() );
+
+ QStrList l; l.append( "echo" ); l.append( "-n" );
+ terminal()->startProgram( u8( "/bin/echo" ), l );
+
+ s_system->setTerminal( m_konsole );
+
+ // m_stack->raiseWidget( m_konsole->widget() );
+ // m_konsole->widget()->show();
+ // m_stack->raiseWidget( m_emptyPage );
+ m_operation->setText( i18n( "Idle" ) );
+ QTimer::singleShot( 0, this, SLOT( toggleDetails() ) );
+ if ( DEFAULT_KONSOLE_HIDDEN )
+ QTimer::singleShot( 0, this, SLOT( toggleDetails() ) );
+ QTimer::singleShot( 0, this, SLOT( hide() ) );
+}
+
diff --git a/adept/adept/commitprogress.h b/adept/adept/commitprogress.h
new file mode 100644
index 0000000..ed557d7
--- /dev/null
+++ b/adept/adept/commitprogress.h
@@ -0,0 +1,41 @@
+/* -*- C++ -*- file adept/commitprogress.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <kde_terminal_interface.h>
+#include <adept/dpkgpm-gui.h>
+#include <adept/commitprogressui.h>
+#include <kparts/part.h>
+
+#ifndef EPT_COMMITPROGRESS_H
+#define EPT_COMMITPROGRESS_H
+
+namespace adept {
+
+class CommitProgress : public CommitProgressUi
+{
+ Q_OBJECT
+public:
+ CommitProgress( QWidget *p = 0, const char *n = 0 );
+
+ ExtTerminalInterface *terminal() {
+ return static_cast<ExtTerminalInterface*>(
+ m_konsole->qt_cast( "ExtTerminalInterface" ) );
+ }
+
+ // needs to be called before aptFront::init() :'((
+ static void initSystem();
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+public slots:
+ void updateProgress( int p, QString msg );
+ void toggleDetails();
+protected:
+ void loadKonsole();
+ KParts::Part *m_konsole;
+ static adept::PkgSystem *s_system; // bla...
+};
+
+}
+
+
+#endif
diff --git a/adept/adept/commitprogressui.ui b/adept/adept/commitprogressui.ui
new file mode 100644
index 0000000..5ccecbf
--- /dev/null
+++ b/adept/adept/commitprogressui.ui
@@ -0,0 +1,197 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::CommitProgressUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CommitProgressUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>542</width>
+ <height>303</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>1</number>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>m_konsoleFrame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>m_occlude</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>40</x>
+ <y>10</y>
+ <width>460</width>
+ <height>60</height>
+ </rect>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ </widget>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>m_details</cstring>
+ </property>
+ <property name="text">
+ <string>(details)</string>
+ </property>
+ </widget>
+ <widget class="KProgress" row="1" column="0">
+ <property name="name">
+ <cstring>m_progress</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_operation</cstring>
+ </property>
+ <property name="text">
+ <string>Preparing...</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>m_bottomSpace</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>80</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>32</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kprogress.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/desktopentryui.ui b/adept/adept/desktopentryui.ui
new file mode 100644
index 0000000..a40c766
--- /dev/null
+++ b/adept/adept/desktopentryui.ui
@@ -0,0 +1,116 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::DesktopEntryUi</class>
+<widget class="adept::ItemExtender">
+ <property name="name">
+ <cstring>DesktopEntryUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>509</width>
+ <height>52</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>6</number>
+ </property>
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <widget class="QLabel" row="0" column="1" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>m_icon</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>m_check</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="3">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="text">
+ <string>(name)</string>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="3">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="text">
+ <string>(description)</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer row="0" column="2" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>6</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/extendablelist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/adept/desktoplist.cpp b/adept/adept/desktoplist.cpp
new file mode 100644
index 0000000..de64f11
--- /dev/null
+++ b/adept/adept/desktoplist.cpp
@@ -0,0 +1,194 @@
+/** -*- C++ -*-
+ @file adept/desktoplist.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qimage.h>
+#include <qlabel.h>
+#include <qcursor.h>
+#include <qcheckbox.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <adept/desktoplist.h>
+#include <adept/utils.h>
+
+namespace adept {
+
+DesktopEntry::DesktopEntry( QWidget *p, const char *n )
+ : DesktopEntryUi( p, n )
+{
+ adjustFontSize( m_description, -1 );
+}
+
+void DesktopEntry::resize( int w, int h )
+{
+ // kdDebug() << "DesktopEntry::resize( " << w << ", " << h << " )" << endl;
+ int margin = layout()->margin() + layout()->spacing() * 2
+ + 6 /* spacer */ + m_icon->width() + m_check->width();
+ if ( m_check->isVisible() ) margin += m_check->width() + layout()->spacing();
+ int hFW1 = m_name->heightForWidth( w - margin );
+ int hFW2 = m_description->heightForWidth( w - margin );
+ /* kdDebug() << "margin = " << margin << ", hFW1 = " << hFW1 << ", hFW2 = "
+ << hFW2 << endl; */
+ int height = 2 * layout()->margin() + layout()->spacing() + hFW1 + hFW2;
+ if ( height < 32 + 2*layout()->margin() /* icon size + margin */ )
+ height = 32 + 2*layout()->margin();
+ // m_description->resize( w - margin, m_description->heightForWidth( w - margin ) );
+ QWidget::resize( w, height );
+}
+
+void DesktopEntry::setItem( ExtendableItem *i ) {
+ m_polished = false;
+ ItemExtender::setItem( i );
+ m_name->setText( u8( "<b>" ) + u8( entity().name() ) + u8( "</b>" ) );
+ m_description->setText( u8( entity().description() ) );
+ if ( !item()->list()->displayCheckboxes() ) {
+ m_check->hide();
+ }
+ if ( !package().valid() || !package().hasVersion() ) {
+ setEnabled( false );
+ } else {
+ connect( m_check, SIGNAL( toggled( bool ) ),
+ this, SLOT( toggled() ) );
+ notifyPostChange();
+ }
+}
+
+void DesktopEntry::mousePressEvent( QMouseEvent *e ) {
+ kdDebug() << "DesktopEntry::mousePressEvent" << endl;
+ e->ignore();
+}
+
+void DesktopEntry::mouseReleaseEvent( QMouseEvent *e ) {
+ kdDebug() << "DesktopEntry::mouseReleaseEvent" << endl;
+ e->ignore();
+}
+
+void DesktopEntry::showEvent( QShowEvent *e ) {
+ DesktopEntryUi::showEvent( e );
+ // DesktopEntryUi::polish();
+ if ( m_polished ) return;
+ item()->list()->polishing();
+ kdDebug() << "polish for " << entity().name() << endl;
+ QImage icon( KGlobal::iconLoader()->iconPath( entity().icon(), -32, true ) );
+ if ( icon.isNull() ) {
+ icon = QImage( KGlobal::dirs()->findResource( "desktopicon", entity().icon() ) );
+ }
+ m_icon->setPixmap( icon.isNull() ? item()->list()->emptyIcon() :
+ QPixmap( icon.smoothScale( 32, 32, QImage::ScaleMin ) ) );
+ item()->list()->polished();
+ m_polished = true;
+}
+
+void DesktopEntry::toggled() {
+ /* if ( package().isInstalled() ) {
+ if ( package().markedRemove() )
+ package().markKeep();
+ else
+ package().markRemove();
+ } else if ( package().markedInstall() )
+ package().markKeep();
+ else
+ package().markInstall(); */
+
+ if ( package().isInstalled() ) {
+ if ( package().markedRemove() )
+ item()->list()->fireRequest( package(), component::State::AKeep );
+ else
+ item()->list()->fireRequest( package(), component::State::ARemove );
+ } else if ( package().markedInstall() )
+ item()->list()->fireRequest( package(), component::State::AKeep );
+ else
+ item()->list()->fireRequest( package(), component::State::AInstall );
+ notifyPostChange();
+}
+
+void DesktopList::polishing() {
+ if ( m_polishing == 0 )
+ QApplication::setOverrideCursor( QCursor( Qt::BusyCursor ) );
+ m_polishing++;
+ if ( m_polishing % 10 == 0 )
+ kapp->processEvents();
+}
+
+void DesktopList::polished() {
+ if ( m_polishing == childCount() )
+ QApplication::restoreOverrideCursor();
+}
+
+void DesktopList::notifyPostChange( component::Base * ) {
+ utils::Range< ExtendableItem * > r = extenders();
+ for ( ; r != r.end(); ++r ) {
+ dynamic_cast< DesktopEntry * >( (*r)->extender() )->notifyPostChange();
+ }
+}
+
+void DesktopEntry::notifyPostChange() {
+ if ( !package().valid() || !package().hasVersion() )
+ return;
+
+ m_check->blockSignals( true );
+ m_check->setChecked( ( package().isInstalled()
+ || entity().package().markedInstall() )
+ && !entity().package().markedRemove() );
+ m_check->blockSignals( false );
+}
+
+DesktopList::DesktopList( QWidget *parent, const char *name )
+ : ExtendableList( parent, name ), m_polishing( 0 ), m_displayCheckboxes( true )
+{
+ observeComponent< component::State >();
+ addColumn( i18n( "Application" ) );
+ setResizeMode( LastColumn );
+ setToggleColumn( -1 ); // no toggling, thanks
+ setExtenderHighlight( true );
+ m_emptyIcon = QPixmap(
+ QImage(
+ KGlobal::iconLoader()->iconPath( u8( "exec" ), -32, false )
+ ).smoothScale( 32, 32, QImage::ScaleMin ) );
+ connect( this, SIGNAL( clicked( QListViewItem *, const QPoint &, int ) ),
+ this, SLOT( processClick( QListViewItem *, const QPoint &, int ) ) );
+}
+
+void DesktopList::processClick( QListViewItem *it, const QPoint &, int ) {
+ kdDebug() << "DesktopList::processClick..." << endl;
+ DesktopItem *i = dynamic_cast< DesktopItem * >( it );
+ if ( !i ) return;
+ emit showDescription( i->entity() );
+}
+
+void DesktopList::insertRange( Range r ) {
+ m_range = r;
+ DesktopItem *last = 0;
+ int i = 0;
+ QApplication::setOverrideCursor( QCursor( Qt::BusyCursor ) );
+ for( ; r != r.end(); r.advance() ) {
+ if ( i % 20 == 0 )
+ kapp->processEvents();
+ if ( !r->package( entity::Package() ).valid() )
+ continue;
+ DesktopItem *i = last ? new DesktopItem( this, last ) : new DesktopItem( this );
+ last = i;
+ i->setEntity( *r );
+ ++ i;
+ }
+ QApplication::restoreOverrideCursor();
+}
+
+ItemExtender *DesktopItem::createExtender() {
+ return new DesktopEntry();
+}
+
+DesktopItem *DesktopEntry::item() const {
+ return dynamic_cast< DesktopItem * >( m_item );
+}
+
+entity::Desktop DesktopEntry::entity() const {
+ return item()->entity();
+}
+
+}
diff --git a/adept/adept/desktoplist.h b/adept/adept/desktoplist.h
new file mode 100644
index 0000000..207b9a7
--- /dev/null
+++ b/adept/adept/desktoplist.h
@@ -0,0 +1,117 @@
+/** -*- C++ -*-
+ @file adept/desktoplist.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qimage.h>
+#include <klocale.h>
+
+#include <apt-front/cache/entity/desktop.h>
+#include <adept/extendablelist.h>
+#include <adept/desktopentryui.h>
+
+#ifndef EPT_DESKTOPLIST_H
+#define EPT_DESKTOPLIST_H
+
+class QPopupMenu;
+
+namespace adept {
+using namespace aptFront;
+using namespace aptFront::cache;
+
+class DesktopItem;
+
+class DesktopList : public ExtendableList, public cache::Observer
+{
+ Q_OBJECT
+public:
+ typedef utils::Range< entity::Desktop > Range;
+ DesktopList( QWidget *parent = 0, const char *name = 0 );
+ void insertRange( Range );
+ QPixmap emptyIcon() { return m_emptyIcon; }
+ void polishing();
+ void polished();
+
+ void setTitle( QString s ) {
+ setColumnText( 0, i18n( "Application (" ) + s + i18n( ")" ) );
+ }
+
+ void setDisplayCheckboxes( bool d ) { m_displayCheckboxes = d; }
+ bool displayCheckboxes() { return m_displayCheckboxes; }
+ virtual void notifyPostChange( cache::component::Base * );
+ void fireRequest( entity::Package p, component::State::Action a ) {
+ emit request( p, a );
+ }
+protected slots:
+ void processClick( QListViewItem *, const QPoint &, int );
+signals:
+ void request( cache::entity::Package, cache::component::State::Action );
+ void showDescription( cache::entity::Desktop );
+protected:
+ Range m_range;
+ QPixmap m_emptyIcon;
+ int m_polishing;
+ bool m_displayCheckboxes;
+};
+
+class DesktopEntry : public DesktopEntryUi
+{
+ Q_OBJECT
+public:
+ DesktopEntry( QWidget * = 0, const char * = 0 );
+ DesktopItem *item() const;
+ entity::Desktop entity() const;
+ void setItem( ExtendableItem * );
+ entity::Package package() { return entity().package(); }
+ virtual void notifyPostChange();
+ virtual void resize( int, int );
+ // virtual void polish();
+public slots:
+ void toggled();
+protected:
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent *e );
+ virtual void showEvent( QShowEvent * );
+ bool m_polished;
+};
+
+class DesktopItem : public ExtendableItem
+{
+public:
+ ItemExtender *createExtender();
+ DesktopItem( DesktopList *l )
+ : ExtendableItem( l ), m_delayedDone( false )
+ {
+ }
+ DesktopItem( DesktopList *v, DesktopItem *i )
+ : ExtendableItem( v, i ), m_delayedDone( false )
+ {
+ }
+
+ void setup() {
+ ExtendableItem::setup();
+ if (m_delayedDone)
+ return;
+ m_delayedDone = true;
+ showExtender();
+ }
+
+ DesktopList *list() { return dynamic_cast< DesktopList * >( listView() ); }
+
+ QString text( int ) const { return QString( "you shouldn't see this" ); }
+ entity::Desktop entity() const { return m_entity; }
+ void setEntity( entity::Desktop e ) { m_entity = e; }
+
+ virtual bool less( const ExtendableItem *other ) const {
+ const DesktopItem *o = dynamic_cast< const DesktopItem * >( other );
+ return entity() < o->entity();
+ }
+
+protected:
+ entity::Desktop m_entity;
+ bool m_delayedDone:1;
+};
+
+}
+
+#endif
diff --git a/adept/adept/dpkgpm-gui.cpp b/adept/adept/dpkgpm-gui.cpp
new file mode 100644
index 0000000..828d18f
--- /dev/null
+++ b/adept/adept/dpkgpm-gui.cpp
@@ -0,0 +1,258 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm-gui.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <fcntl.h>
+#include <iostream>
+
+#include <qstrlist.h>
+#include <kapplication.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <kparts/part.h>
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/entity/package.h>
+
+#include <adept/dpkgpm-gui.h>
+#include <adept/utils.h>
+
+using namespace aptFront;
+using namespace cache;
+
+namespace adept {
+
+PkgSystem::PkgSystem()
+ : m_terminalPart( 0 )
+{
+ std::cerr << "kapture::PkgSystem::PkgSystem()" << std::endl;
+ Label = "adeptDPkgSystem";
+}
+
+void PkgSystem::setTerminal( KParts::Part *t )
+{
+ m_terminalPart = t;
+}
+
+pkgPackageManager *PkgSystem::CreatePM( pkgDepCache *c ) const
+{
+ std::cerr << "kapture::PkgSystem::CreatePM()" << std::endl;
+ adept::DPkgPM *pm = new adept::DPkgPM( c, m_terminalPart );
+ connect( pm, SIGNAL( statusChanged( int, QString ) ),
+ this, SIGNAL( statusChanged( int, QString ) ) );
+ return pm;
+}
+
+DPkgPM::DPkgPM( pkgDepCache *cache, KParts::Part *t )
+ : aptFront::DPkgPM (cache), m_terminalPart (t)
+{
+}
+
+bool DPkgPM::forkDpkg( char *const argv[] )
+{
+ bool ok = true;
+ std::cerr << "adept::DPkgPM::forkDpkg ()" << std::endl;
+ QStrList l;
+ for (int i = 0; argv[i]; i ++)
+ l.append( argv[i] );
+
+ m_processRunning = true;
+ connect( m_terminalPart, SIGNAL( processExited( KProcess * ) ),
+ this, SLOT( processExit( KProcess * ) ) );
+ connect( m_terminalPart, SIGNAL( processExited( const KProcess * ) ),
+ this, SLOT( processExitC( const KProcess * ) ) );
+ connect( m_terminalPart, SIGNAL( forkedChild() ),
+ this, SLOT( setupDpkgChild() ) );
+
+ terminal()->startProgram( u8( argv[0] ), l );
+
+ ::close( m_dpkgPipe[1] );
+ ::fcntl( m_dpkgPipe[0], F_SETFL, O_NONBLOCK );
+
+ while (m_processRunning) {
+ dpkgMonitor();
+ usleep( 50000 );
+ }
+
+ if (m_exitedProcess->normalExit()) {
+ if (m_exitedProcess->exitStatus() != 0) {
+ ok = _error->Error( "Child for %s exited with error %d",
+ argv [0], m_exitedProcess->exitStatus());
+ }
+ } else {
+ ok = _error->Error( "Child for %s was killed by signal %d",
+ argv [0], m_exitedProcess->exitSignal());
+ }
+
+ if (ok) // do we run scripts in case dpkg died???
+ ok = runScripts ("DPkg::Post-Invoke", false);
+
+ return ok;
+}
+
+ExtTerminalInterface *DPkgPM::terminal() {
+ return static_cast<ExtTerminalInterface *>(
+ m_terminalPart->qt_cast( "ExtTerminalInterface" ) );
+}
+
+bool DPkgPM::forkScript (const char *cmd, bool fP)
+{
+ std::cerr << "adept::DPkgPM::forkScript(\"" << cmd << "\")" << std::endl;
+ if (fP) {
+ if (pipe( m_scriptPipe ) != 0)
+ return _error->Errno(
+ "pipe","Failed to create IPC pipe to subprocess");
+ SetCloseExec (m_scriptPipe[0], true);
+ SetCloseExec (m_scriptPipe[1], true);
+ }
+ QStrList l;
+ l.append ("/bin/sh");
+ l.append ("-c");
+ l.append (cmd);
+ if (fP) {
+ connect( m_terminalPart, SIGNAL( forkedChild() ),
+ this, SLOT( setupScriptPipe() ) );
+ }
+
+ connect( m_terminalPart, SIGNAL( processExited( KProcess * ) ),
+ this, SLOT( processExit( KProcess * ) ) );
+ connect( m_terminalPart, SIGNAL( processExited( const KProcess * ) ),
+ this, SLOT( processExitC( const KProcess * ) ) );
+
+ m_processRunning = true;
+ terminal()->startProgram( u8( "/bin/sh" ), l);
+
+ if (fP) {
+ if (!feedPackages())
+ return _error->Error("Failed feeding packages to script");
+ }
+
+ while (m_processRunning) {
+ kapp->processEvents();
+ usleep(50000);
+ }
+
+ std::cerr << "END: adept::DPkgPM::forkScript(\""
+ << cmd << "\")" << std::endl;
+
+ if (m_exitedProcess->normalExit()) {
+ if (m_exitedProcess->exitStatus() != 0) {
+ return _error -> Error("Child for %s exited with error %d",
+ cmd, m_exitedProcess->exitStatus());
+ } else {
+ return true;
+ }
+ } else {
+ return _error->Error("Child for %s was killed by signal %d",
+ cmd, m_exitedProcess->exitSignal());
+ }
+}
+
+void DPkgPM::processExit(KProcess *p) {
+ processExitC( p );
+}
+
+void DPkgPM::processExitC(const KProcess *p)
+{
+ std::cerr << "a process exited!" << std::endl;
+ m_processRunning = false;
+ m_exitedProcess = p;
+}
+
+void DPkgPM::setupScriptPipe()
+{
+ // setupScript();
+ // std::cerr << "setupScriptPipe()" << std::endl;
+ dup2 (m_scriptPipe[0], STDIN_FILENO);
+}
+
+void DPkgPM::setupDpkgChild()
+{
+ // setupScript();
+ // std::cerr << "setupDpkgChild()" << std::endl;
+ setupChild();
+}
+
+bool DPkgPM::Go( int )
+{
+ std::cerr << "kapture::DPkgPM::Go ()" << std::endl;
+ statusChanged( 0, i18n( "Preparing..." ) );
+ bool ret = aptFront::DPkgPM::Go(-1);
+ QStrList l;
+ l.append("echo");
+ l.append("dpkg run finished!");
+ terminal()->startProgram( u8( "echo" ), l );
+ statusChanged( 100, i18n( "Done" ) );
+ return ret;
+}
+
+void DPkgPM::dpkgMonitor ()
+{
+ aptFront::DPkgPM::dpkgMonitor();
+ kapp->processEvents();
+}
+
+void DPkgPM::updateStatus( std::string pkg, std::string ev, std::string r )
+{
+ std::string op, msg;
+ aptFront::DPkgPM::updateStatus( pkg, ev, r );
+ entity::Package p = cache::Global::get().packages().packageByName( pkg );
+
+ if ( m_currentOp == OInstall ) {
+ if ( p.markedNewInstall() ) {
+ if ( ev == "half-installed" )
+ msg = u8( i18n( "Preparing installation of %1..." ) );
+ else if ( ev == "unpacked" )
+ msg = u8( i18n( "Unpacking %1..." ) );
+ } else if ( p.markedUpgrade() ) {
+ if ( ev == "half-installed" )
+ msg = u8( i18n( "Preparing upgrade of %1..." ) );
+ else if ( ev == "unpacked" || ev == "half-configured" )
+ msg = u8( i18n( "Replacing %1 with new version..." ) );
+ }
+ } else if ( m_currentOp == OConfigure ) {
+ if ( p.markedNewInstall() ) {
+ if ( ev == "unpacked" )
+ msg = u8( i18n( "Preparing to configure %1..." ) );
+ else if ( ev == "half-configured" )
+ msg = u8( i18n( "Configuring %1..." ) );
+ else if ( ev == "installed" )
+ msg = u8( i18n( "Installed %1" ) );
+ } else if ( p.markedUpgrade() ) {
+ if ( ev == "unpacked" )
+ msg = u8( i18n( "Preparing to configure new version of %1..." ) );
+ else if ( ev == "half-configured" )
+ msg = u8( i18n( "Configuring new version of %1..." ) );
+ else if ( ev == "installed" )
+ msg = u8( i18n( "Upgraded %1" ) );
+ }
+ } else if ( m_currentOp == ORemove ) {
+ if ( ev == "installed" )
+ msg = u8( i18n( "Preparing to remove %1..." ) );
+ else if ( ev == "half-configured" || ev == "half-installed" )
+ msg = u8( i18n( "Removing %1..." ) );
+ else if ( ev == "config-files" || ev == "not-installed" )
+ msg = u8( i18n( "Removed %1" ) );
+ } else if ( m_currentOp == OPurge ) {
+ if ( ev == "config-files" )
+ msg = u8( i18n( "Preparing to purge %1..." ) );
+ else if ( ev == "not-installed" )
+ msg = u8( i18n( "Purged %1" ) );
+ }
+
+ std::cerr << "updateStatus( " << pkg << ", " << ev << ", " << r << ")" << std::endl;
+ std::cerr << "updateStatus: msg = " << msg << std::endl;
+ std::cerr << "updateStatus: seen = " << m_seenOpCount
+ << ", total = " << m_totalOpCount << std::endl;
+ statusChanged( ( m_seenOpCount * 100 ) / m_totalOpCount,
+ u8( msg ).arg( pkg ) + ( ( r == "") ? "" : (" (" + r + ")") ) );
+}
+
+}
+
+#include "dpkgpm-gui.moc"
diff --git a/adept/adept/dpkgpm-gui.h b/adept/adept/dpkgpm-gui.h
new file mode 100644
index 0000000..435ee7f
--- /dev/null
+++ b/adept/adept/dpkgpm-gui.h
@@ -0,0 +1,68 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm-gui.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#ifndef EPT_DPKGPM_H
+# define EPT_DPKGPM_H
+
+#include <apt-pkg/debsystem.h>
+#include <adept/dpkgpm.h>
+#include <kde_terminal_interface.h>
+#include <kprocess.h>
+#include <kdialogbase.h>
+
+class KListBox;
+namespace KParts {
+class Part;
+}
+
+namespace adept {
+
+class PkgSystem : public QObject, public debSystem
+{
+ Q_OBJECT
+public:
+ PkgSystem ();
+ virtual pkgPackageManager *CreatePM( pkgDepCache *Cache ) const;
+ virtual void setTerminal( KParts::Part *t );
+ KParts::Part *terminal() { return m_terminalPart; }
+ virtual int Score( Configuration const &Cnf ) {
+ return debSystem::Score (Cnf) + 2; };
+protected:
+ KParts::Part *m_terminalPart;
+signals:
+ void statusChanged( int p, QString m );
+};
+
+class DPkgPM : public QObject, public aptFront::DPkgPM
+{
+ Q_OBJECT
+public:
+ DPkgPM (pkgDepCache *c, KParts::Part *t);
+ virtual bool forkDpkg (char *const argv[]);
+ virtual void dpkgMonitor (void);
+ virtual bool Go (int);
+ virtual bool forkScript (const char *, bool);
+ ExtTerminalInterface *terminal();
+ virtual void updateStatus( std::string pkg, std::string ev, std::string r );
+
+public slots:
+ void processExitC(const KProcess *p);
+ void processExit(KProcess *p);
+ void setupScriptPipe();
+ void setupDpkgChild();
+
+signals:
+ void statusChanged( int p, QString m );
+
+protected:
+ KParts::Part *m_terminalPart;
+ // DPkgProgress *m_prog;
+ bool m_processRunning:1;
+ const KProcess *m_exitedProcess;
+};
+
+}
+
+#endif
diff --git a/adept/adept/dpkgpm.cpp b/adept/adept/dpkgpm.cpp
new file mode 100644
index 0000000..f4b4f0d
--- /dev/null
+++ b/adept/adept/dpkgpm.cpp
@@ -0,0 +1,462 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include "dpkgpm.h"
+#include <signal.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/entity/package.h>
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+using namespace aptFront;
+using namespace cache;
+
+/* === PkgSystem === */
+DPkgPM::DPkgPM (pkgDepCache *C)
+ : pkgDPkgPM (C), m_seenOpCount( 0 ), m_totalOpCount( 0 )
+{
+}
+
+bool DPkgPM::Go( int )
+{
+ cerr << "DPkgPM::Go()" << endl;
+ computeTotals();
+ if (runScripts ("DPkg::Pre-Invoke", false) == false)
+ return false;
+ if (runScripts ("DPkg::Pre-Install-Pkgs", true) == false)
+ return false;
+
+ for (vector<Item>::iterator I = List.begin(); I != List.end();) {
+ char *const *argv;
+ if (! setupArgs (&argv, I))
+ return false;
+
+ cerr << "running '";
+ for (unsigned int k = 0; argv [k]; k++)
+ cerr << argv[k] << ' ';
+ cerr << "'" << endl;
+ if (_config->FindB("Debug::pkgDPkgPM",false) == true)
+ {
+ for (unsigned int k = 0; argv [k]; k++)
+ cerr << argv[k] << ' ';
+ cerr << endl;
+ continue;
+ }
+
+ if (! forkDpkg (argv))
+ return false;
+ delete[] argv;
+ if (! runScripts ("DPkg::Post-Invoke", false))
+ return false;
+ }
+ return true;
+}
+
+void DPkgPM::computeTotals()
+{
+ m_totalOpCount = 0;
+ for (vector<Item>::iterator I = List.begin(); I != List.end();I++)
+ {
+ entity::Package p = cache::Global::get().packages().packageByName(
+ I->Pkg.Name() );
+ int x = 0;
+ switch ( I->Op ) {
+ case Item::Remove: x = 4; break;
+ case Item::Install: p.markedUpgrade() ? x = 3 : x = 2; break;
+ case Item::Purge: x = 2; break;
+ case Item::Configure: x = 3; break;
+ }
+ m_totalOpCount += x;
+ }
+}
+
+bool DPkgPM::forkDpkg (char *const argv[])
+{
+ cerr << "DPkgPM::forkDpkg ()" << endl;
+ cout << flush;
+ clog << flush;
+ cerr << flush;
+
+ /* Mask off sig int/quit. We do this because dpkg also does when
+ it forks scripts. What happens is that when you hit ctrl-c it sends
+ it to all processes in the group. Since dpkg ignores the signal
+ it doesn't die but we do! So we must also ignore it */
+ sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN);
+ sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
+
+ // Fork dpkg
+ pid_t Child = ExecFork();
+ if (Child == 0) {
+ if (! setupChild ()) {
+ cerr << "Error in dpkg post-fork setup!" << endl;
+ _exit (100);
+ }
+ execvp (argv [0], argv);
+ cerr << "Error executing dpkg!" << endl;
+ _exit (100);
+ }
+
+ close( m_dpkgPipe[1] );
+ fcntl( m_dpkgPipe[0], F_SETFL, O_NONBLOCK );
+
+ int Status = 0;
+ int ret = 0;
+ while ((ret = waitpid (Child, &Status, WNOHANG)) != Child) {
+ if (errno == EINTR || ret == 0) {
+ dpkgMonitor ();
+ usleep (200000); // 0.2 second hang
+ continue;
+ }
+ runScripts ("DPkg::Post-Invoke", false);
+
+ signal(SIGQUIT,old_SIGQUIT);
+ signal(SIGINT,old_SIGINT);
+ return _error -> Errno ("waitpid","Couldn't wait for subprocess");
+ }
+
+ signal(SIGQUIT,old_SIGQUIT);
+ signal(SIGINT,old_SIGINT);
+
+ // Check for an error code.
+ if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
+ {
+ runScripts ("DPkg::Post-Invoke", false);
+ if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
+ return _error->Error("Sub-process %s received a segmentation fault.", argv [0]);
+
+ if (WIFEXITED(Status) != 0)
+ return _error->Error("Sub-process %s returned an error code (%u)", argv[0], WEXITSTATUS(Status));
+
+ return _error->Error("Sub-process %s exited unexpectedly", argv[0]);
+ }
+
+ return true;
+}
+
+bool DPkgPM::setupArgs (char *const**a, std::vector<Item>::iterator &I)
+{
+ cerr << "DPkgPM::setupArgs ()" << endl;
+ unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",350);
+ unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",8192);
+
+ vector<Item>::iterator J = I;
+ for (; J != List.end() && J->Op == I->Op; J++);
+
+ // Generate the argument list
+ const char **Args = new const char *[MaxArgs + 50];
+ if (J - I > (signed)MaxArgs)
+ J = I + MaxArgs;
+
+ unsigned int n = 0;
+ unsigned long Size = 0;
+ string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
+ Args[n++] = Tmp.c_str();
+ Size += strlen(Args[n-1]);
+
+ // Stick in any custom dpkg options
+ Configuration::Item const *Opts = _config->Tree("DPkg::Options");
+ if (Opts != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ Args[n++] = Opts->Value.c_str();
+ Size += Opts->Value.length();
+ }
+ }
+
+ pipe( m_dpkgPipe );
+ stringstream fds;
+ fds << m_dpkgPipe[1];
+ std::cerr << "reading end of the pipe: " << m_dpkgPipe[0] << std::endl;
+
+ Args[n++] = "--status-fd";
+ Size += strlen(Args[n-1]);
+ // bah, we leak a string every time we run dpkg... silly eh
+ Args[n++] = ( new string( fds.str() ) )->c_str();
+ Size += strlen(Args[n-1]);
+
+ switch (I->Op)
+ {
+ case Item::Remove:
+ Args[n++] = "--force-depends";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--force-remove-essential";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--remove";
+ Size += strlen(Args[n-1]);
+ m_currentOp = ORemove;
+ break;
+
+ case Item::Purge:
+ Args[n++] = "--force-depends";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--force-remove-essential";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--purge";
+ Size += strlen(Args[n-1]);
+ m_currentOp = OPurge;
+ break;
+
+ case Item::Configure:
+ Args[n++] = "--configure";
+ Size += strlen(Args[n-1]);
+ m_currentOp = OConfigure;
+ break;
+
+ case Item::Install:
+ Args[n++] = "--unpack";
+ Size += strlen(Args[n-1]);
+ m_currentOp = OInstall;
+ break;
+ }
+
+ // Write in the file or package names
+ if (I->Op == Item::Install)
+ {
+ for (;I != J && Size < MaxArgBytes; I++)
+ {
+ if (I->File[0] != '/')
+ return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str());
+ Args[n++] = I->File.c_str();
+ Size += strlen(Args[n-1]);
+ }
+ }
+ else
+ {
+ for (;I != J && Size < MaxArgBytes; I++)
+ {
+ Args[n++] = I->Pkg.Name();
+ Size += strlen(Args[n-1]);
+ }
+ }
+ Args[n] = 0;
+ J = I;
+ *a = (char *const *)Args;
+ return true;
+}
+
+bool DPkgPM::setupChild ()
+{
+ // cerr << "DPkgPM::setupChild ()" << endl;
+ if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
+ return false;
+
+ if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO))
+ {
+ int Flags,dummy;
+ if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
+ return false;
+
+ // Discard everything in stdin before forking dpkg
+ if (fcntl(STDIN_FILENO,F_SETFL,Flags | O_NONBLOCK) < 0)
+ return false;
+
+ while (read(STDIN_FILENO,&dummy,1) == 1);
+
+ if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
+ return false;
+ }
+
+ /* No Job Control Stop Env is a magic dpkg var that prevents it
+ from using sigstop */
+ putenv("DPKG_NO_TSTP=yes");
+ close( m_dpkgPipe[0] );
+
+ return true;
+}
+
+void DPkgPM::dpkgMonitor ()
+{
+ char buf[1024];
+ int r = read( m_dpkgPipe[0], buf, 1023 );
+
+ if ( r > 0 ) {
+ buf[r] = 0;
+ std::string b( buf );
+
+ // parse status updates from dpkg
+ while ( true ) {
+ std::string::size_type colon, nl = b.find( '\n' );
+ m_statusBuffer.append( string( b, 0, nl ) );
+ if ( nl == std::string::npos )
+ break;
+
+ // cerr << "dpkg status completed line: " << m_statusBuffer << endl;
+ colon = m_statusBuffer.find( ": " );
+ string l( m_statusBuffer, 0, colon );
+ string r( m_statusBuffer, colon + 2, string::npos );
+
+ if ( l == "status" ) {
+ colon = r.find( ": " );
+ std::string p( r, 0, colon );
+ r = string( r, colon + 2, string::npos );
+
+ colon = r.find( ": " );
+ std::string e( r, 0, colon );
+ if ( colon == string::npos )
+ r = "";
+ else
+ r = string( r, colon + 2, string::npos );
+ updateStatus( p, e, r );
+ }
+
+ b = string( b, nl + 1, string::npos );
+ m_statusBuffer = string();
+ nl = b.find( '\n' );
+ }
+ }
+}
+
+void DPkgPM::updateStatus( std::string pkg, std::string ev, std::string r )
+{
+ //std::cerr << "DPkgPM::updateStatus " << pkg << " " << ev << " " << r
+ // << std::endl;
+ if (ev.find("error") != string::npos) {
+ char* list[5];
+ char *line = strdup(m_statusBuffer.c_str());
+ TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
+ WriteApportReport(list[1], list[3]);
+ free(line);
+ return;
+ }
+
+ OpAndStatus os = std::make_pair( m_currentOp, ev );
+ if ( m_seenOps[ std::make_pair( os, pkg ) ] == 0 ) {
+ m_seenOpCount++;
+ m_seenOps[ std::make_pair( os, pkg ) ] = 1;
+ }
+}
+
+bool DPkgPM::runScripts (const char *Cnf, bool sP)
+{
+ cerr << "DPkgPM::runScripts ('" << Cnf << "', " << sP << ")" << endl;
+ Configuration::Item const *Opts = _config->Tree(Cnf);
+ if (Opts == 0 || Opts->Child == 0)
+ return true;
+ Opts = Opts->Child;
+
+ unsigned int Count = 1;
+ for (; Opts != 0; Opts = Opts->Next, Count++)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+
+ // Determine the protocol version
+ string OptSec = Opts->Value;
+ string::size_type Pos;
+ if ((Pos = OptSec.find(' ')) == string::npos || Pos == 0)
+ Pos = OptSec.length();
+ OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos);
+
+ m_version = _config->FindI (OptSec + "::Version", 1);
+
+ // Purified Fork for running the script
+ // pid_t Process = ExecFork();
+ forkScript (Opts->Value.c_str(), sP);
+ }
+
+ return true;
+}
+
+bool DPkgPM::SendV1Pkgs (FILE *F)
+{
+ bool Die = false;
+ for (vector<Item>::iterator I = List.begin(); I != List.end(); ++I)
+ {
+ // Only deal with packages to be installed from .deb
+ if (I->Op != Item::Install)
+ continue;
+
+ // No errors here..
+ if (I->File[0] != '/')
+ continue;
+
+ /* Feed the filename of each package that is pending install
+ into the pipe. */
+ fprintf(F,"%s\n",I->File.c_str());
+ if (ferror(F) != 0)
+ {
+ Die = true;
+ break;
+ }
+ }
+ return ! Die;
+}
+
+bool DPkgPM::forkScript (const char *cmd, bool fP)
+{
+ cerr << "DPkgPM::forkScript ()" << endl;
+ if (fP) {
+ if (pipe( m_scriptPipe ) != 0)
+ return _error -> Errno("pipe", "Failed to create IPC pipe to subprocess");
+ SetCloseExec( m_scriptPipe[ 0 ], true );
+ SetCloseExec( m_scriptPipe[ 1 ], true );
+ }
+ pid_t Process = ExecFork ();
+ if (Process == 0)
+ {
+ setupScript (cmd, fP);
+
+ const char *Args[4];
+ Args[0] = "/bin/sh";
+ Args[1] = "-c";
+ Args[2] = cmd;
+ Args[3] = 0;
+ execv(Args[0],(char **)Args);
+ _exit(100);
+ }
+
+ if (fP) {
+ if (! feedPackages ())
+ return _error -> Error ("Failed feeding packages to script");
+ }
+
+ // Clean up the sub process
+ if (ExecWait (Process, cmd) == false)
+ return _error -> Error("Failure running script %s", cmd);
+}
+
+void DPkgPM::setupScript (const char * /*cmd*/, bool fP)
+{
+ cerr << "DPkgPM::setupScript ()" << endl;
+ if (fP) {
+ dup2 (m_scriptPipe [0], STDIN_FILENO);
+ SetCloseExec(STDOUT_FILENO, false);
+ SetCloseExec(STDIN_FILENO, false);
+ SetCloseExec(STDERR_FILENO, false);
+ }
+}
+
+bool DPkgPM::feedPackages ()
+{
+ close(m_scriptPipe[ 0 ]);
+
+ FILE *F = fdopen(m_scriptPipe[ 1 ], "w");
+ if (F == 0)
+ return _error->Errno("fdopen","Faild to open new FD");
+
+ // Feed it the filenames.
+ bool Die = false;
+ if (m_version <= 1)
+ Die = !SendV1Pkgs (F);
+ else
+ Die = !SendV2Pkgs(F);
+
+ fclose(F);
+ return ! Die;
+}
diff --git a/adept/adept/dpkgpm.h b/adept/adept/dpkgpm.h
new file mode 100644
index 0000000..b899693
--- /dev/null
+++ b/adept/adept/dpkgpm.h
@@ -0,0 +1,49 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-pkg/dpkgpm.h>
+#include <string>
+#include <vector>
+#include <map>
+
+#ifndef DPKGPM_H
+# define DPKGPM_H
+
+namespace aptFront {
+
+class DPkgPM : public pkgDPkgPM {
+protected:
+ enum Op { ORemove, OPurge, OConfigure, OInstall };
+ Op m_currentOp;
+ int m_dpkgPipe[2];
+ int m_scriptPipe[2];
+ unsigned m_version;
+ std::string m_statusBuffer;
+ typedef std::pair< Op, std::string > OpAndStatus;
+ typedef std::map< std::pair< OpAndStatus, std::string >, int > SeenOps;
+ SeenOps m_seenOps;
+ int m_totalOpCount;
+ int m_seenOpCount;
+public:
+ DPkgPM (pkgDepCache *C);
+ virtual bool Go ( int );
+ virtual void computeTotals();
+ virtual bool setupArgs (char *const **a, std::vector<Item>::iterator &I);
+ virtual bool forkDpkg (char *const argv[]);
+ virtual bool forkScript (const char *, bool);
+ virtual bool runScripts (const char *, bool);
+ virtual bool setupChild ();
+ virtual void setupScript (const char *, bool);
+ virtual void dpkgMonitor (void);
+ virtual bool SendV1Pkgs (FILE *);
+ virtual bool feedPackages (void);
+ virtual void updateStatus( std::string pkg, std::string ev, std::string r );
+};
+
+}
+
+
+#endif /* ifndef DPKGPM_H */
+
diff --git a/adept/adept/easytagfilter.cpp b/adept/adept/easytagfilter.cpp
new file mode 100644
index 0000000..3049d60
--- /dev/null
+++ b/adept/adept/easytagfilter.cpp
@@ -0,0 +1,81 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include "easytagfilter.h"
+
+using namespace aptFront;
+using namespace adept;
+
+static void fillCombo( QComboBox *c, const std::string f ) {
+ Cache &cache = cache::Global::get(); // FIXME?
+ std::set< ept::debtags::Tag > t;
+ t = cache.tags().tags( f );
+ for (std::set< ept::debtags::Tag >::iterator i = t.begin(); i != t.end(); ++ i) {
+ c->insertItem( i->name() );
+ }
+}
+
+EasyTagFilterWidget::EasyTagFilterWidget( QWidget *parent, const char *name )
+ : EasyTagFilterUi( parent, name )
+{
+ fillCombo( m_use, "use" );
+ fillCombo( m_interface, "interface" );
+ fillCombo( m_worksWith, "works-with" );
+ fillCombo( m_role, "role" );
+ connect( m_use, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_interface, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_worksWith, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_role, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_reset, SIGNAL( clicked() ),
+ this, SLOT( reset() ) );
+}
+
+static void setFacet( QComboBox *c, const std::string fac,
+ EasyTagFilter< entity::Package > &f )
+{
+ if (c->currentItem())
+ f.set( fac, c->currentText() );
+}
+
+EasyTagFilterWidget::Predicate EasyTagFilterWidget::predicate()
+{
+ EasyTagFilter< entity::Package > f;
+ setFacet( m_use, "use", f );
+ setFacet( m_interface, "interface", f );
+ setFacet( m_worksWith, "works-with", f );
+ setFacet( m_role, "role", f );
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void setCombo( QComboBox *c, const std::string &t ) {
+ c->blockSignals( true );
+ if (t == "")
+ c->setCurrentItem( 0 );
+ else
+ c->setCurrentText( t );
+ c->blockSignals( false );
+}
+
+void EasyTagFilterWidget::predicateChanged() {
+ typedef EasyTagFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ setCombo( m_use, f.get( "use" ) );
+ setCombo( m_interface, f.get( "interface" ) );
+ setCombo( m_role, f.get( "role" ) );
+ setCombo( m_worksWith, f.get( "works-with" ) );
+}
+
+void EasyTagFilterWidget::reset() {
+ setCombo( m_use, "" );
+ setCombo( m_interface, "" );
+ setCombo( m_role, "" );
+ setCombo( m_worksWith, "" );
+ emit widgetsChanged();
+}
diff --git a/adept/adept/easytagfilter.h b/adept/adept/easytagfilter.h
new file mode 100644
index 0000000..66977d5
--- /dev/null
+++ b/adept/adept/easytagfilter.h
@@ -0,0 +1,93 @@
+/** -*- C++ -*-
+ @file adept/quickfilter.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <kdebug.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+//#include <apt-front/cache/component/tags.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/easytagfilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+
+#ifndef EPT_EASYTAGFILTER_H
+#define EPT_EASYTAGFILTER_H
+
+namespace adept {
+
+template< typename T >
+struct EasyTagFilter : predicate::Implementation< T, EasyTagFilter< T > >,
+ InterfacingPredicate
+{
+ typedef std::map< std::string, std::string > Tags;
+
+ EasyTagFilter() {
+ setupPredicate();
+ }
+
+ void setupPredicate() {
+ Cache &cache = cache::Global::get(); // FIXME?
+ m_op = predicate::True< T >();
+ for (Tags::iterator i = m_tags.begin(); i != m_tags.end(); ++i ) {
+ m_op = m_op and predicate::Factory< T >::tag(
+ cache.tags().tagByName( i->first + "::" + i->second ) );
+ // kdDebug() << t.summary() << endl;
+ }
+ }
+
+ std::string summary() const {
+ std::string r( i18n( "EasyTag filter: " ).local8Bit() );
+ for (Tags::const_iterator j, i = m_tags.begin();
+ i != m_tags.end(); ++i ) {
+ j = i; ++j;
+ r += i->first + ": " + i->second;
+ if (j != m_tags.end())
+ r += ", ";
+ }
+ return r;
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const EasyTagFilter &o ) const {
+ return o.m_tags == m_tags;
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ void set( const std::string &f, const std::string &t ) {
+ m_tags[f] = t;
+ setupPredicate();
+ }
+
+ std::string get( const std::string &f ) {
+ return m_tags[ f ];
+ }
+
+protected:
+ Tags m_tags;
+ predicate::Predicate< T > m_op;
+};
+
+class EasyTagFilterWidget : public EasyTagFilterUi
+{
+ Q_OBJECT
+public:
+ EasyTagFilterWidget( QWidget *parent, const char *name = 0 );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+ void reset();
+};
+
+}
+
+#endif
diff --git a/adept/adept/easytagfilterui.ui b/adept/adept/easytagfilterui.ui
new file mode 100644
index 0000000..998bf2b
--- /dev/null
+++ b/adept/adept/easytagfilterui.ui
@@ -0,0 +1,201 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::EasyTagFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>EasyTagFilterUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>611</width>
+ <height>116</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>QuickFilterUi</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Easy Tag Filter&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Works With:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Role:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="3">
+ <item>
+ <property name="text">
+ <string>Anything</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_worksWith</cstring>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="4">
+ <property name="name">
+ <cstring>m_reset</cstring>
+ </property>
+ <property name="text">
+ <string>Reset Filter</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="3">
+ <item>
+ <property name="text">
+ <string>Any</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_interface</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Use:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Any</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_use</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Any</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_role</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Interface:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>130</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/adept/extendablelist.cpp b/adept/adept/extendablelist.cpp
new file mode 100644
index 0000000..c3abf1d
--- /dev/null
+++ b/adept/adept/extendablelist.cpp
@@ -0,0 +1,339 @@
+#include <kdebug.h>
+#include <qtimer.h>
+#include <qobjectlist.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <kiconeffect.h>
+#include <kiconloader.h>
+
+#include <adept/extendablelist.h>
+#include <adept/utils.h>
+
+using namespace adept;
+
+ExtendableList::ExtendableList( QWidget *p, const char *n )
+ : KListView( p, n ),
+ m_toggleColumn( 0 ), m_inDtor( false ),
+ m_extenderUpdateScheduled( false ),
+ m_needSort( false ),
+ m_extenderHighlight( false )
+{
+ // kdDebug() << "connecting processClick har har" << endl;
+ connect( this, SIGNAL( clicked( QListViewItem *,
+ const QPoint &, int ) ),
+ this, SLOT( processClick( QListViewItem *,
+ const QPoint &, int ) ) );
+ connect( this, SIGNAL( moved() ),
+ this, SLOT( delayedUpdateExtenders() ) );
+ connect( this, SIGNAL( collapsed( QListViewItem * ) ),
+ this, SLOT( delayedUpdateExtenders() ) );
+ connect( this, SIGNAL( expanded( QListViewItem * ) ),
+ this, SLOT( delayedUpdateExtenders() ) );
+ setTreeStepSize( 15 );
+
+ m_baseIcon = SmallIcon( u8( "extender_closed" ) );
+ m_extendedIcon = SmallIcon( u8( "extender_opened" ) );
+ QImage img;
+ img = m_baseIcon;
+ KIconEffect::toGray( img, 1.0 );
+ m_unextendableIcon = QPixmap( img );
+}
+
+void ExtendableList::keyPressEvent( QKeyEvent *e ) {
+ ExtendableItem *item = dynamic_cast< ExtendableItem* >( currentItem() );
+ if ( item ) {
+ if ( item->extendable() ) {
+ if ( item->extender() && e->key() == Qt::Key_Left ) {
+ return item->hideExtender();
+ } else if ( !item->extender() && e->key() == Qt::Key_Right ) {
+ return item->showExtender();
+ }
+ }
+ KListView::keyPressEvent( e );
+ if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
+ item->updateIcon();
+ } else return KListView::keyPressEvent( e );
+}
+
+void ExtendableList::openToplevel() {
+ QListViewItem *i;
+ for ( i = firstChild(); i != 0; i = i->nextSibling() ) {
+ i->setOpen( true );
+ }
+}
+
+int ExtendableList::extenderOffset( ExtendableItem *i )
+{
+ int c = 0, x = 0;
+
+ while( c < m_toggleColumn ) {
+ x += columnWidth( c );
+ c ++;
+ }
+
+ if ( m_toggleColumn >= 0 ) {
+ // *sigh*
+ if ( i->pixmap( m_toggleColumn ) )
+ x += i->pixmap( m_toggleColumn )->width();
+ if ( rootIsDecorated() )
+ x += treeStepSize();
+ if ( i->parent() )
+ x += treeStepSize();
+ }
+
+ return x + 2; // + 2 = icon margin, apparently... gnah
+}
+
+void ExtendableList::updateExtender( ExtendableItem *i )
+{
+ // setUpdatesEnabled( false );
+
+ // since updateGeometries is private, we use this dirty trick to
+ // get at it (since setContentsPos in QListView calls it
+ setContentsPos( contentsX(), contentsY() );
+
+ if ( !i->isVisible() || ( i->parent() && !i->parent()->isOpen() ) ) {
+ kdDebug() << "hiding invisible item's extender" << endl;
+ i->hideExtender();
+ return;
+ }
+
+ // QRect rect = itemRect( i );
+ addChild( i->extender(), extenderOffset( i ), itemPos( i ) );
+ // addChild( i->extender(), x, rect.y() );
+ i->extender()->show();
+ i->extender()->resize( visibleWidth() - extenderOffset( i ),
+ i->extender()->height() );
+ if ( i->height() != i->extender()->frameSize().height() ) {
+ i->setHeight( i->extender()->frameSize().height() );
+ delayedUpdateExtenders(); // re-update since we broke layout
+ }
+
+ i->extender()->setupColors();
+
+ // setUpdatesEnabled( true );
+ // addChild( i->extender(), x, itemPos( i ) );
+ // QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) );
+ // QTimer::singleShot( 0, i->extender(), SLOT( setupColors() ) );
+}
+
+void ExtendableList::delayedUpdateExtenders()
+{
+ if ( m_extenderUpdateScheduled )
+ return;
+ m_extenderUpdateScheduled = true;
+ // kdDebug() << "ExtendableList::delayedUpdateExtenders()" << endl;
+ QTimer::singleShot( 0, this, SLOT( updateExtenders() ) );
+}
+
+void ExtendableList::clear()
+{
+ kdDebug() << "ExtendableList::clear()" << endl;
+ KListView::clear();
+ kdDebug() << "end of ExtendableList::clear()" << endl;
+}
+
+void ExtendableList::show()
+{
+ KListView::show();
+ updateExtenders();
+}
+
+void ExtendableList::showEvent( QShowEvent *e )
+{
+ KListView::showEvent( e );
+ updateExtenders();
+}
+
+void ExtendableList::resizeEvent( QResizeEvent *e )
+{
+ KListView::resizeEvent( e );
+ updateExtenders();
+ // delayedUpdateExtenders();
+}
+
+void ExtendableList::updateExtenders()
+{
+ m_extenderUpdateScheduled = false;
+ setUpdatesEnabled( false );
+ // updateGeometries();
+ // since updateGeometries is private, we use this dirty trick to
+ // get at it (since setContentsPos in QListView calls it
+ setContentsPos( contentsX(), contentsY() );
+ extendersChanged();
+ kdDebug() << "ExtendableList::updateExtenders(); count = "
+ << m_extenders.size() << endl;
+ if ( m_needSort ) {
+ std::sort( m_extenders.begin(), m_extenders.end(), ExtendableItem::s_less );
+ m_needSort = false;
+ }
+
+ std::for_each( m_extenders.begin(), m_extenders.end(),
+ std::bind1st( std::mem_fun( &ExtendableList::updateExtender ),
+ this ) );
+
+ setUpdatesEnabled( true );
+ // triggerUpdate();
+ if ( !m_extenderUpdateScheduled )
+ QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) );
+ /* if ( m_extenders.empty() )
+ QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) ); */
+ // QTimer::singleShot( 0, this, SIGNAL( extendersChanged() ) );
+}
+
+void ExtendableList::addExtender( ExtendableItem *item )
+{
+ m_extenders.push_back( item );
+ m_needSort = true;
+ // std::sort( m_extenders.begin(), m_extenders.end(), ExtendableItem::s_less );
+ // updateExtender( item );
+ delayedUpdateExtenders();
+}
+
+void ExtendableList::removeExtender( ExtendableItem *i )
+{
+ kdDebug() << "ExtendableList::removeExtender( " << i << " )" << endl;
+ m_extenders.erase( std::remove( m_extenders.begin(),
+ m_extenders.end(), i ),
+ m_extenders.end() );
+ // the above retains ordering so no need to re-sort
+ if (!m_inDtor)
+ delayedUpdateExtenders();
+}
+
+void ExtendableList::processClick( QListViewItem *it,
+ const QPoint &pt, int c )
+{
+ // if (! it) return;
+ ExtendableItem *item = dynamic_cast< ExtendableItem* >( it );
+ if (!item) return;
+ kdDebug() << "ExtendableList::processClick (a real item)" << endl;
+
+ if (c == m_toggleColumn)
+ item->toggleExtender();
+ if ( item->extender() )
+ item->extender()->setupColors();
+ delayedUpdateExtenders();
+ /* if (item->extender()) {
+ if (c == m_toggleColumn)
+ item->toggleExtender();
+ } else
+ item->toggleExtender(); */
+}
+
+ExtendableList::~ExtendableList() {
+}
+
+ExtendableList *ExtendableItem::list()
+{
+ return dynamic_cast< ExtendableList * >( listView() );
+}
+
+bool ExtendableItem::s_less(
+ const ExtendableItem *a, const ExtendableItem *b )
+{
+ return a->less( b );
+}
+
+int ExtendableItem::compare( QListViewItem *i, int c, bool asc ) const
+{
+ ExtendableItem *o = dynamic_cast< ExtendableItem * >( i );
+ return int( o->less( this ) ) - int( less( o ) );
+}
+
+void ExtendableItem::updateIcon() {
+ QPixmap p;
+ if ( !extender() ) {
+ p = list()->baseIcon();
+ if ( !extendable() && !firstChild() ) {
+ p = list()->unextendableIcon();
+ } else if ( isOpen() ) {
+ p = list()->extendedIcon();
+ }
+ } else {
+ p = list()->extendedIcon();
+ }
+ setPixmap( list()->toggleColumn(), p );
+ setUpdatedIcon(p);
+
+ // umm hack
+ if ( dynamic_cast< ExtendableItem * >( parent() ) )
+ dynamic_cast< ExtendableItem * >( parent() )->updateIcon();
+}
+
+
+void ExtendableItem::toggleExtender()
+{
+ if (m_extender) {
+ setup();
+ if( list() ) // this could as well be 0... bah
+ list()->removeExtender( this );
+ delete m_extender;
+ m_extender = 0;
+ } else {
+ m_extender = createExtender();
+ if (m_extender) {
+ m_extender->setItem( this );
+ list()->addExtender( this );
+ }
+ if ( !m_extender && firstChild() ) {
+ setOpen( !isOpen() );
+ }
+ }
+ updateIcon();
+}
+
+void ExtendableItem::paintBranches( QPainter *p,
+ const QColorGroup &cg, int w, int y, int h )
+{
+ /* if (!isAlternate())
+ p->setBackgroundColor(
+ KGlobalSettings::alternateBackgroundColor() );
+ p->eraseRect( 0, y, w, h ); */
+ p->eraseRect( 0, 0, w, h );
+}
+
+/* void ExtendableItem::paintCell( QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ KListViewItem::paintCell( &_p, cg, column, width, alignment );
+ p->drawPixmap( 0, 0, pm );
+ } */
+
+
+static void setcolor( QWidget *w, ExtendableItem *i ) {
+ if ( i->isSelected() && i->list()->extenderHighlight() )
+ w->setPaletteBackgroundColor( w->colorGroup().highlight() );
+ else if ( i->isAlternate() )
+ w->setPaletteBackgroundColor(
+ KGlobalSettings::alternateBackgroundColor() );
+ else
+ w->setPaletteBackgroundColor( w->colorGroup().base() );
+ // w->setBackgroundMode( QWidget::PaletteBase );
+}
+void ItemExtender::setupColors()
+{
+ if ( !item() ) return;
+ setcolor( this, item() );
+ QObjectList *chld = queryList( "QWidget" );
+ QObjectListIt it( *chld );
+ QWidget *o;
+ while ((o = dynamic_cast< QWidget * >( it.current() )) != 0) {
+ setcolor( o, item() );
+ ++it;
+ }
+}
+
+ExtendableItem::~ExtendableItem()
+{
+ // kdDebug() << "~ExtendableList; list = " << list() << endl;
+ // kdDebug() << "extender() = " << extender() << endl;
+ while ( firstChild() )
+ delete firstChild(); // har har
+ if( extender() && list() ) // list() could be 0...
+ list()->removeExtender( this );
+ if (extender())
+ extender()->deleteLater();
+}
diff --git a/adept/adept/extendablelist.h b/adept/adept/extendablelist.h
new file mode 100644
index 0000000..e95df03
--- /dev/null
+++ b/adept/adept/extendablelist.h
@@ -0,0 +1,166 @@
+// -*- C++ -*-
+#include <klistview.h>
+#include <qpixmap.h>
+#include <qlayout.h>
+#include <kglobalsettings.h>
+#include <vector>
+
+#include <apt-front/utils/range.h>
+
+#ifndef EPT_EXTENDABLELIST_H
+#define EPT_EXTENDABLELIST_H
+namespace adept {
+
+using namespace aptFront;
+
+class ExtendableItem;
+class ExtendableList;
+class ItemExtender;
+
+class ExtendableList : public KListView {
+ Q_OBJECT
+public:
+ typedef bool(*ItemCompare)( const ExtendableItem *,
+ const ExtendableItem * );
+ ExtendableList( QWidget *p = 0, const char *n = 0 );
+ virtual ~ExtendableList();
+ QPixmap extendedIcon() { return m_extendedIcon; }
+ QPixmap baseIcon() { return m_baseIcon; }
+ QPixmap unextendableIcon() { return m_unextendableIcon; }
+ int extenderOffset( ExtendableItem *i );
+ void setExtenderHighlight( bool e ) { m_extenderHighlight = e; }
+ bool extenderHighlight() { return m_extenderHighlight; }
+public slots:
+ void addExtender( ExtendableItem *i );
+ void removeExtender( ExtendableItem *i );
+ void updateExtender( ExtendableItem *i );
+ void delayedUpdateExtenders();
+ void updateExtenders();
+ void setToggleColumn( int c ) {
+ m_toggleColumn = c;
+ }
+ unsigned toggleColumn() { return m_toggleColumn; }
+ virtual void show();
+ virtual void clear();
+ utils::Range< ExtendableItem * > extenders() {
+ return utils::range( m_extenders.begin(), m_extenders.end() ); }
+ void openToplevel();
+protected slots:
+ void processClick( QListViewItem *, const QPoint &, int );
+signals:
+ void extendersChanged();
+protected:
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void showEvent( QShowEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+ std::vector< ExtendableItem * > m_extenders;
+ QPixmap m_extendedIcon;
+ QPixmap m_baseIcon;
+ QPixmap m_unextendableIcon;
+ int m_toggleColumn;
+ bool m_inDtor:1;
+ bool m_extenderUpdateScheduled:1;
+ bool m_needSort:1;
+ bool m_extenderHighlight:1;
+};
+
+class ExtendableItem : public KListViewItem {
+public:
+
+ ExtendableItem( ExtendableList *l )
+ : KListViewItem( l ), m_extender( 0 ) {
+ }
+
+ ExtendableItem( ExtendableList *l, ExtendableItem *prev )
+ : KListViewItem( l, prev ), m_extender( 0 ) {
+ }
+
+ ExtendableItem( ExtendableItem *p, ExtendableItem *prev )
+ : KListViewItem( p, prev ), m_extender( 0 ) {
+ }
+
+ ExtendableItem( ExtendableItem *p )
+ : KListViewItem( p ), m_extender( 0 ) {
+ }
+
+ virtual void setup() {
+ KListViewItem::setup();
+ updateIcon();
+ }
+ void toggleExtender();
+
+ void hideExtender() {
+ if (extender())
+ toggleExtender();
+ }
+
+ void showExtender() {
+ if (!extender())
+ toggleExtender();
+ }
+
+ ItemExtender *extender() { return m_extender; }
+
+ static bool s_less( const ExtendableItem *a, const ExtendableItem *b );
+
+ ExtendableList *list();
+
+ virtual void updateIcon();
+ virtual void setUpdatedIcon(QPixmap& pm) { return; };
+
+ virtual void paintBranches( QPainter *, const QColorGroup &, int, int, int );
+
+ virtual ItemExtender *createExtender() = 0;
+ virtual bool extendable() const { return false; }
+ virtual bool less( const ExtendableItem * ) const = 0;
+ virtual int compare( QListViewItem *other, int col, bool ascending ) const;
+
+ virtual ~ExtendableItem();
+ virtual void setHeight( int h ) { KListViewItem::setHeight( h ); }
+protected:
+ ItemExtender *m_extender;
+};
+
+class ItemExtender : public QWidget {
+ Q_OBJECT
+public:
+ // ItemExtender( ExtendableItem *item );
+ ItemExtender( QWidget *parent, const char *n )
+ : QWidget( parent, n ), m_item( 0 )
+ {}
+
+ virtual void setItem( ExtendableItem *i ) {
+ m_item = i;
+ }
+
+ virtual void polish() {
+ setupColors();
+ }
+
+ ExtendableItem *item() {
+ return m_item;
+ }
+
+ void resize( int w, int h ) {
+ setUpdatesEnabled( false );
+ QWidget::resize( w, h );
+ setUpdatesEnabled( true );
+ QWidget::resize( w, layout()->minimumSize().height() );
+ }
+
+ void resize( const QSize &s ) {
+ resize( s.width(), s.height() );
+ }
+
+public slots:
+ void setupColors();
+protected:
+ virtual void mouseReleaseEvent( QMouseEvent *e ) {
+ e->accept();
+ } // throw away mouse clicks :-)
+ ExtendableItem *m_item;
+};
+
+}
+
+#endif
diff --git a/adept/adept/filterlist.cpp b/adept/adept/filterlist.cpp
new file mode 100644
index 0000000..bb798cd
--- /dev/null
+++ b/adept/adept/filterlist.cpp
@@ -0,0 +1,232 @@
+#include <kdebug.h>
+#include <qpopupmenu.h>
+#include <qheader.h>
+#include <klineedit.h>
+
+//#include <tagcoll/InputMerger.h>
+
+//#include <apt-front/cache/component/tags.h>
+#include <apt-front/cache/entity/package.h>
+
+#include <adept/lister.h>
+#include <adept/filterlist.h>
+#include <adept/quickfilter.h>
+#include <adept/statefilter.h>
+#include <adept/easytagfilter.h>
+#include <adept/tagfilter.h>
+
+
+using namespace adept;
+
+/*
+// TODO: Beat enrico till this lands in some of our libs...
+template< typename PKG, typename TAG >
+class TagcollConsumerAdaptor :
+ public utils::ConsumerImpl< PKG,TagcollConsumerAdaptor<PKG, TAG> >
+{
+protected:
+ Consumer<PKG, TAG>& m_out;
+
+public:
+ TagcollConsumerAdaptor( Consumer<PKG, TAG>& out) : m_out( out ) {}
+ virtual void consume( const PKG& a ) {
+ if (a != PKG())
+ m_out.consume(a, a.tags());
+ }
+};
+*/
+
+PredicateInterface::PredicateInterface( QWidget *w, const char *n )
+ : ItemExtender( w, n )
+{
+}
+
+void PredicateInterface::widgetsChanged() {
+ kdDebug() << "PredicateInterface::widgetsChanged()" << endl;
+ emit predicateDrop( m_pred );
+ m_pred = predicate();
+ emit predicateAdd( m_pred );
+ downcast< FilterItem >( item() ).setPredicate( m_pred );
+}
+
+FilterList::FilterList( QWidget *parent, const char *name )
+ : ExtendableList( parent, name ),
+ m_pred( predicate::True< entity::Entity >() ),
+ m_hidden( predicate::True< entity::Entity >() )
+{
+ m_itemsSeen = 0;
+ // addColumn( " ", 20 );
+ addColumn( i18n( "Active filters" ), 240 );
+ // setSortColumn( -1 );
+ /* setItemsMovable( true );
+ setDragEnabled( true );
+ setAcceptDrops( true ); */
+ setResizeMode( LastColumn );
+ setAllColumnsShowFocus (true);
+
+ resize( 240, 180 );
+ connect( this, SIGNAL(
+ contextMenuRequested( QListViewItem *, const QPoint
+ &, int ) ),
+ this, SLOT( contextMenu( QListViewItem *, const
+ QPoint &, int) ) );
+ connect( this, SIGNAL( extendersChanged() ),
+ this, SLOT( updateHeight() ) );
+}
+
+void FilterList::emitPredicateChanged() {
+ predicateChanged( m_hidden and m_pred );
+}
+
+void FilterList::updateHeight() {
+ int h = header()->height() + 4;
+ for ( QListViewItem *i = firstChild(); i != 0; i = i->nextSibling() ) {
+ h += i->totalHeight();
+ }
+ // int h = contentsHeight() + header()->height() + 4; // magic constant
+ setMinimumHeight( h );
+ setMaximumHeight( h );
+}
+
+void FilterList::drawContents( QPainter *p, int a, int b, int c, int d ) {
+ if ( m_itemsSeen != childCount() ) {
+ m_itemsSeen = childCount();
+ updateHeight();
+ } // hmm, doesn't work... bah :p
+ KListView::drawContents( p, a, b, c, d );
+}
+
+void FilterList::plugLister( Lister *l ) {
+ m_lister = l;
+ connect( this, SIGNAL( predicateChanged( ListerPredicate ) ),
+ l, SLOT( baseSet( ListerPredicate ) ) );
+}
+
+void FilterList::setPredicate( Predicate p ) {
+ clear();
+ m_pred = p;
+ appendPredicate( p );
+ emitPredicateChanged();
+}
+
+void FilterList::setHiddenPredicate( Predicate p ) {
+ m_hidden = p;
+ emitPredicateChanged();
+}
+
+void FilterList::editorPredicateDrop( Predicate p ) {
+ m_pred = predicate::remove( m_pred, p );
+ emitPredicateChanged();
+}
+
+void FilterList::editorPredicateAdd( Predicate p ) {
+ kdDebug() << "FilterList::editorPredicateAdd" << endl;
+ m_pred = m_pred and p;
+ emitPredicateChanged();
+}
+
+void FilterList::appendPredicate( Predicate p ) {
+ if (p.is< And >()) {
+ And a = p;
+ for (utils::Range< Predicate > r = a.parts();
+ r != r.end(); ++r )
+ appendPredicate( *r );
+ } else if (p.is< predicate::True< entity::Entity > >() ) {
+ // we generally ignore truth
+ } else {
+ m_pred = m_pred and p;
+ // kdDebug() << p.serialize() << endl;
+ // kdDebug() << p.prettyPrint() << endl;
+ FilterItem *i;
+ i = new FilterItem( this );
+ i->setPredicate( p );
+ }
+}
+
+void FilterList::contextMenu( QListViewItem *it, const QPoint &pt, int /*c*/ )
+{
+ std::cerr << "FilterList::contextMenu(p);" << std::endl;
+ FilterItem *i = dynamic_cast< FilterItem * >( it );
+ if (! i)
+ return;
+ QPopupMenu *m = new QPopupMenu( this );
+ m->insertItem( i18n( "Reset Filter" ), 1 );
+ m->insertItem( i18n( "Remove Filter" ), 0 );
+ m->insertSeparator();
+ m->insertItem( i18n( "Add Quick Filter" ), 8 );
+ m->insertItem( i18n( "Add State Filter" ), 9 );
+ m->insertItem( i18n( "Add Tag Filter" ), 10 );
+ m->insertItem( i18n( "Add Easy Tag Filter" ), 11 );
+ // m->insertItem( "Add Tag Filter", tagMenu() );
+ m_context = i;
+ connect(m, SIGNAL(activated(int)), this, SLOT(contextActivated(int)));
+ m->exec(pt);
+ delete m;
+}
+
+
+void FilterList::contextActivated( int i )
+{
+ predicate::Predicate< entity::Entity > p;
+ switch (i) {
+ case 0:
+ m_pred = predicate::remove( m_pred, m_context->predicate() );
+ delete m_context;
+ emitPredicateChanged();
+ return;
+ case 1:
+ m_context->reset();
+ return;
+ case 8:
+ p = predicate::adapt< entity::Entity >(
+ QuickFilter< entity::Package >() );
+ break;
+ case 9:
+ p = predicate::adapt< entity::Entity >(
+ StateFilter< entity::Package >() );
+ break;
+ case 10:
+ p = predicate::adapt< entity::Entity >(
+ TagFilter< entity::Package >() );
+ break;
+ case 11:
+ p = predicate::adapt< entity::Entity >(
+ EasyTagFilter< entity::Package >() );
+ break;
+ }
+ if (p.impl()) {
+ kdDebug() << "summary: " <<
+ downcast< InterfacingPredicate >( p ).summary() << endl;
+ appendPredicate( p );
+ emitPredicateChanged();
+ }
+}
+
+ItemExtender *FilterItem::createExtender()
+{
+ PredicateInterface *o = 0;
+ if (m_pred.is< QuickFilter< entity::Package > >()) {
+ o = new QuickFilterWidget( list(), 0 );
+ } else if (m_pred.is< StateFilter< entity::Package > >()) {
+ o = new StateFilterWidget( list(), 0 );
+ } else if (m_pred.is< EasyTagFilter< entity::Package > >()) {
+ o = new EasyTagFilterWidget( list(), 0 );
+ } else if (m_pred.is< TagFilter< entity::Package > >()) {
+ o = new TagFilterWidget( list(), 0 );
+ }
+ if (o) {
+ o->setPredicate( m_pred );
+ QObject::connect( o, SIGNAL( predicateAdd( Predicate ) ),
+ list(), SLOT( editorPredicateAdd( Predicate ) ) );
+ QObject::connect( o, SIGNAL( predicateDrop( Predicate ) ),
+ list(), SLOT( editorPredicateDrop( Predicate ) ) );
+ }
+ return o;
+}
+
+QString FilterItem::text( int c ) const {
+ InterfacingPredicate &ip = downcast< InterfacingPredicate >( m_pred.impl() );
+ if (c == 0)
+ return ip.summary();
+ return u8( "" );
+}
diff --git a/adept/adept/filterlist.h b/adept/adept/filterlist.h
new file mode 100644
index 0000000..212ab5a
--- /dev/null
+++ b/adept/adept/filterlist.h
@@ -0,0 +1,149 @@
+/** -*- C++ -*-
+ @file adept/filterlist.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qtooltip.h>
+#include <kdebug.h>
+
+#include <apt-front/predicate/matchers.h>
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/component/packagetags.h>
+//#include <apt-front/cache/component/tags.h>
+
+#include <adept/listerpredicate.h>
+#include <adept/extendablelist.h>
+
+#ifndef EPT_FILTERLIST_H
+#define EPT_FILTERLIST_H
+
+class QPopupMenu;
+
+namespace adept {
+using namespace aptFront;
+using namespace aptFront::cache;
+class Lister;
+
+struct InterfacingPredicate
+{
+public:
+ virtual std::string summary() const = 0;
+ virtual void reset() {}
+signals:
+ void changed();
+};
+
+
+class PredicateInterface: public ItemExtender
+{
+ Q_OBJECT
+public:
+ typedef predicate::Predicate< entity::Entity > Predicate;
+ PredicateInterface( QWidget *w = 0, const char *n = 0 );
+ virtual Predicate predicate() = 0;
+signals:
+ void predicateAdd( Predicate );
+ void predicateDrop( Predicate );
+public slots:
+ virtual void setPredicate( const Predicate &p ) {
+ m_pred = p;
+ predicateChanged();
+ }
+ virtual void widgetsChanged();
+ virtual void predicateChanged() = 0;
+protected:
+ predicate::Predicate< entity::Entity > m_pred;
+};
+
+class FilterItem;
+
+class FilterList : public ExtendableList
+{
+ Q_OBJECT
+public:
+ friend class FilterItem;
+ typedef predicate::Predicate< entity::Entity > Predicate;
+ // typedef std::map< KListViewItem *, Predicate > Map;
+ FilterList( QWidget *parent = 0, const char *name = 0 );
+ typedef predicate::And< entity::Entity > And;
+ void appendPredicate( Predicate p );
+ void plugLister( Lister *l );
+ void emitPredicateChanged();
+signals:
+ void predicateChanged( ListerPredicate p );
+public slots:
+ void setPredicate( Predicate p );
+ void setHiddenPredicate( Predicate p );
+protected slots:
+ void editorPredicateDrop( Predicate );
+ void editorPredicateAdd( Predicate );
+ void contextMenu( QListViewItem *, const QPoint &, int );
+ // QPopupMenu *tagMenu();
+ void contextActivated( int );
+ // void tagMenuActivated( int );
+ void updateHeight();
+protected:
+ void drawContents( QPainter *, int, int, int, int );
+ Predicate m_pred;
+ Predicate m_hidden;
+ FilterItem *m_context;
+ bool m_changed;
+ Lister *m_lister;
+ int m_itemsSeen;
+ std::vector< ept::debtags::Tag > m_tagMenuMap;
+};
+
+class FilterItem : public ExtendableItem
+{
+public:
+ ItemExtender *createExtender();
+ FilterItem( FilterList *l )
+ : ExtendableItem( l ), m_delayedDone( false )
+ {
+ }
+ void setup() {
+ ExtendableItem::setup();
+ if (m_delayedDone)
+ return;
+ m_delayedDone = true;
+ showExtender();
+ }
+
+ QString text( int ) const;
+
+ virtual bool less( const ExtendableItem *other ) const {
+ const FilterItem *o = dynamic_cast< const FilterItem * >( other );
+ return downcast< InterfacingPredicate >( m_pred ).summary() <
+ downcast< InterfacingPredicate >( o->m_pred ).summary();
+ }
+
+ void setPredicate( predicate::Predicate< entity::Entity > p ) {
+ m_pred = p;
+ }
+
+ FilterList::Predicate predicate() const {
+ return m_pred;
+ }
+
+ FilterList *filterList() { return dynamic_cast< FilterList * >( list() ); }
+
+ void reset() {
+ filterList()->editorPredicateDrop( m_pred );
+ downcast< InterfacingPredicate >( m_pred ).reset();
+ if ( extender() ) {
+ downcast< PredicateInterface >( extender() ).setPredicate( m_pred );
+ extender()->setFocus();
+ }
+ filterList()->editorPredicateAdd( m_pred );
+ }
+
+protected:
+ predicate::Predicate< entity::Entity > m_pred;
+ bool m_delayedDone:1;
+};
+
+}
+
+#endif
diff --git a/adept/adept/filtersidebar.cpp b/adept/adept/filtersidebar.cpp
new file mode 100644
index 0000000..777fa44
--- /dev/null
+++ b/adept/adept/filtersidebar.cpp
@@ -0,0 +1,72 @@
+#include <functional>
+#include <ext/functional>
+#include <algorithm>
+#include <cmath>
+#include <ept/debtags/tag.h>
+#include <ept/debtags/vocabulary.h>
+#include <adept/filtersidebar.h>
+#include <adept/tagchooser.h>
+
+using namespace adept;
+using namespace aptFront;
+using namespace std;
+using namespace __gnu_cxx;
+
+template< typename H, typename G1, typename G2 >
+struct _compose2_binary {
+ _compose2_binary( H _h, G1 _g1, G2 _g2 )
+ : h( _h ), g1( _g1 ), g2( _g2 )
+ {}
+
+ typename H::result_type operator()(
+ typename G1::argument_type a,
+ typename G2::argument_type b )
+ {
+ return h( g1( a ), g2( b ) );
+ }
+
+ H h;
+ G1 g1;
+ G2 g2;
+};
+
+template< typename H, typename G1, typename G2 >
+_compose2_binary< H, G1, G2 > compose2_binary( H h, G1 g1, G2 g2 ) {
+ return _compose2_binary< H, G1, G2 >( h, g1, g2 );
+}
+
+void FilterSidebar::setCardinality( const Lister::Cardinality &c )
+{
+ using namespace wibble::operators;
+ ept::debtags::Tag::Set all, smart;
+
+ kdDebug() << "FilterSidebar::setCardinality" << endl;
+ Lister::Cardinality cprime;
+ remove_copy_if( c.begin(), c.end(), inserter( cprime, cprime.begin() ),
+ compose1( bind1st( equal_to< int >(), 0 ),
+ select2nd<
+ Lister::Cardinality::value_type >() ) );
+ transform( cprime.begin(), cprime.end(), inserter( all, all.begin() ),
+ select1st< Lister::Cardinality::value_type >() );
+ m_all->setTags( all );
+ ept::debtags::Vocabulary &t = cache::Global().get().tags();
+ m_easy->setTags( all & ( t.facetByName( "interface" ).tags()
+ | t.facetByName( "works-with" ).tags()
+ | t.facetByName( "use" ).tags()
+ | t.facetByName( "role" ).tags() ) );
+
+ typedef vector< pair< ept::debtags::Tag, int > > Vec;
+ Vec vec;
+ copy( cprime.begin(), cprime.end(), back_inserter( vec ) );
+ sort( vec.begin(), vec.end(),
+ compose2_binary( less< int >(),
+ select2nd< Vec::value_type >(),
+ select2nd< Vec::value_type >() ) );
+ Vec::reverse_iterator end = vec.rbegin();
+ advance( end, vec.size() < 10 ? vec.size() : 10 );
+ transform( vec.rbegin(), end, inserter( smart, smart.begin() ),
+ select1st< Vec::value_type >() );
+
+ m_smart->setTags( smart );
+ m_smart->openToplevel();
+}
diff --git a/adept/adept/filtersidebar.h b/adept/adept/filtersidebar.h
new file mode 100644
index 0000000..0fac201
--- /dev/null
+++ b/adept/adept/filtersidebar.h
@@ -0,0 +1,26 @@
+/* -*- C++ -*- file adept/filtersidebar.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <adept/filtersidebarui.h>
+#include <adept/lister.h>
+
+#ifndef EPT_FILTERSIDEBAR_H
+#define EPT_FILTERSIDEBAR_H
+
+namespace adept {
+
+// using namespace aptFront;
+
+class FilterSidebar : public FilterSidebarUi {
+ Q_OBJECT
+public:
+ FilterSidebar( QWidget *p = 0, const char *n = 0 )
+ : FilterSidebarUi( p, n )
+ {}
+public slots:
+ void setCardinality( const Lister::Cardinality & );
+};
+
+}
+
+#endif
diff --git a/adept/adept/filtersidebarui.ui b/adept/adept/filtersidebarui.ui
new file mode 100644
index 0000000..0f2efb4
--- /dev/null
+++ b/adept/adept/filtersidebarui.ui
@@ -0,0 +1,119 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::FilterSidebarUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>adept::FilterSidebarUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>227</width>
+ <height>469</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form2</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>m_tabs</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab0</cstring>
+ </property>
+ <attribute name="title">
+ <string>Smart</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::TagChooser" row="0" column="0">
+ <property name="name">
+ <cstring>m_smart</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab1</cstring>
+ </property>
+ <attribute name="title">
+ <string>Simple</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::TagChooser" row="0" column="0">
+ <property name="name">
+ <cstring>m_easy</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab2</cstring>
+ </property>
+ <attribute name="title">
+ <string>All</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::TagChooser" row="0" column="0">
+ <property name="name">
+ <cstring>m_all</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::TagChooser</class>
+ <header location="global">adept/tagchooser.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </customwidget>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/tagchooser.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/filterwidget.cpp b/adept/adept/filterwidget.cpp
new file mode 100644
index 0000000..f294327
--- /dev/null
+++ b/adept/adept/filterwidget.cpp
@@ -0,0 +1,36 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include "filterwidget.h"
+
+using namespace aptFront;
+using namespace adept;
+
+void FilterWidget::connectLister( Lister *l ) {
+ connect( this, SIGNAL( drop( ListerPredicate ) ),
+ l, SLOT( interactiveDrop( ListerPredicate ) ) );
+ connect( this, SIGNAL( changed( ListerPredicate ) ),
+ l, SLOT( interactiveAnd( ListerPredicate ) ) );
+ connect( this, SIGNAL( apply( ListerPredicate ) ),
+ l, SLOT( baseAnd( ListerPredicate ) ) );
+
+}
+
+void FilterWidget::changedInternal() {
+ setEnabled( false );
+ emit drop( m_old );
+ emit changed( m_old = predicate() );
+ setEnabled( true );
+ setFocus();
+}
+
+void FilterWidget::applyInternal() {
+ // check for emptiness?
+ setEnabled( false );
+ emit drop( m_old );
+ emit apply( m_old = predicate() );
+ reset();
+ setEnabled( true );
+ setFocus();
+}
diff --git a/adept/adept/filterwidget.h b/adept/adept/filterwidget.h
new file mode 100644
index 0000000..78b0c38
--- /dev/null
+++ b/adept/adept/filterwidget.h
@@ -0,0 +1,39 @@
+/** -*- C++ -*-
+ @file adept/filterwidgets.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <adept/lister.h>
+
+#ifndef EPT_FILTERWIDGET_H
+#define EPT_FILTERWIDGET_H
+
+class KLineEdit;
+
+namespace adept {
+
+class FilterWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ FilterWidget( QWidget *parent = 0, const char *n = 0 )
+ : QWidget( parent, n ) {}
+ virtual ListerPredicate predicate() = 0;
+ void connectLister( Lister *l );
+protected slots:
+ void changedInternal();
+ void applyInternal();
+ virtual void reset() = 0;
+signals:
+ void changed( ListerPredicate op );
+ void apply( ListerPredicate op );
+ void drop( ListerPredicate op );
+protected:
+ ListerPredicate m_old;
+};
+
+}
+
+#endif
diff --git a/adept/adept/groupeddesktopselector.cpp b/adept/adept/groupeddesktopselector.cpp
new file mode 100644
index 0000000..68afa98
--- /dev/null
+++ b/adept/adept/groupeddesktopselector.cpp
@@ -0,0 +1,137 @@
+/** -*- C++ -*-
+ @file adept/groupeddestkopselector.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qobjectlist.h>
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kseparator.h>
+#include <kapplication.h>
+
+#include <apt-front/cache/component/desktop.h>
+#include <adept/groupeddesktopselector.h>
+#include <adept/desktoplist.h>
+#include <adept/utils.h>
+
+using namespace aptFront;
+using namespace cache;
+
+namespace adept {
+
+GroupedDesktopSelector::GroupedDesktopSelector( QWidget *p, const char *n )
+ : KJanusWidget( p, n, IconList ), m_policy( 0 )
+{
+ observeComponent< cache::component::Packages >();
+ m_pages.push_back( addPage( QString( "Initializing..." ) ) );
+ QObjectList *chld = queryList( "QWidget" );
+ QObjectListIt it( *chld ); QWidget *o;
+ while ((o = dynamic_cast< QWidget * >( it.current() )) != 0) {
+ if ( dynamic_cast< QLabel * >( o ) != 0 )
+ o->hide();
+ if ( dynamic_cast< KSeparator * >( o ) != 0 )
+ o->hide();
+ ++it;
+ } // *hack*
+
+ // AAAA hack
+ QLayoutIterator li = layout()->iterator();
+ QHBoxLayout *hbox = 0;
+ while ( li.current() != 0 ) {
+ hbox = dynamic_cast< QHBoxLayout * >( li.current() );
+ if ( hbox ) break;
+ ++li;
+ }
+ kdDebug() << "hacking hbox = " << hbox << endl;
+ if ( hbox ) {
+ li = hbox->iterator();
+ while ( li.current() != 0 ) {
+ QSpacerItem *spacer = dynamic_cast< QSpacerItem * >( li.current() );
+ if ( spacer ) {
+ hbox->removeItem( spacer );
+ delete spacer;
+ }
+ ++li;
+ }
+ }
+}
+
+void GroupedDesktopSelector::notifyPreRebuild( component::Base * ) {
+ clear();
+}
+
+void GroupedDesktopSelector::notifyPostRebuild( component::Base * ) {
+ // QTimer::singleShot( 0, this, SLOT( fill() ) );
+}
+
+void GroupedDesktopSelector::clear()
+{
+ if ( !m_pages.empty() )
+ showPage( m_pages.front() );
+ while ( !m_pages.empty() ) {
+ removePage( m_pages.back() );
+ delete m_pages.back();
+ m_pages.pop_back();
+ }
+}
+
+void GroupedDesktopSelector::fill()
+{
+ component::Desktop &d = cache::Global::get().component< component::Desktop >();
+ fill( d.entries() );
+}
+
+void GroupedDesktopSelector::fill( component::Desktop::EntityRange r )
+{
+ component::Desktop &d = cache::Global::get().component< component::Desktop >();
+ utils::Range< std::string > gr;
+ QString last = pageTitle( activePageIndex() );
+
+ clear();
+
+ bool shown = false;
+
+ for ( gr = d.availableGroups( r ); gr != gr.end(); gr.advance() ) {
+
+ component::Desktop::EntityRange cr = d.group( *gr );
+ QString name = u8( *gr );
+ std::cerr << "group for " << cr->name() << ": " << r->group() << std::endl;
+ name = ( name != u8( "" ) ? name : u8( "Legacy" ) );
+
+ QPixmap icon( KGlobal::iconLoader()->iconPath(
+ policy() ? policy()->iconForGroup( name ) : u8( "" ), -32 ) );
+
+ QVBox *b = addVBoxPage( name, name, icon );
+ m_pages.push_back( b );
+ std::cerr << "creating list for " << *gr << std::endl;
+
+ DesktopList *l = new DesktopList( b );
+ l->setTitle( name );
+ connect( l, SIGNAL( request( cache::entity::Package,
+ cache::component::State::Action ) ),
+ this, SIGNAL( request( cache::entity::Package,
+ cache::component::State::Action ) ) );
+ connect( l, SIGNAL( showDescription( cache::entity::Desktop ) ),
+ this, SIGNAL( showDescription( cache::entity::Desktop ) ) );
+
+ l->insertRange( intersectionRange( r, cr ) );
+ // l->insertRange( cr );
+
+ std::cerr << "created list for " << *gr << std::endl;
+ if ( name == last ) {
+ showPage( b );
+ shown = true;
+ }
+ kapp->processEvents();
+ }
+
+ if ( m_pages.empty() )
+ m_pages.push_back( addPage( QString( "No Results" ) ) );
+ if ( !shown )
+ showPage( pageIndex( m_pages.front() ) );
+}
+
+}
diff --git a/adept/adept/groupeddesktopselector.h b/adept/adept/groupeddesktopselector.h
new file mode 100644
index 0000000..a54f7aa
--- /dev/null
+++ b/adept/adept/groupeddesktopselector.h
@@ -0,0 +1,39 @@
+/** -*- C++ -*-
+ @file adept/groupeddestkopselector.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <kjanuswidget.h>
+#include <apt-front/cache/entity/desktop.h>
+
+namespace adept {
+using namespace aptFront;
+using namespace aptFront::cache;
+
+// XXX needs fixing
+class GroupedDesktopSelector : public KJanusWidget, cache::Observer
+{
+ Q_OBJECT
+public:
+ struct IconPolicy {
+ virtual QString iconForGroup( QString group ) { return group; }
+ };
+ GroupedDesktopSelector( QWidget *p = 0, const char *n = 0 );
+ void fill( component::Desktop::EntityRange r );
+ void setPolicy( IconPolicy *p ) { m_policy = p; }
+ IconPolicy *policy() { return m_policy; }
+ virtual void notifyPreRebuild( cache::component::Base * );
+ virtual void notifyPostRebuild( cache::component::Base * );
+public slots:
+ void clear();
+ void fill();
+signals:
+ void request( cache::entity::Package, cache::component::State::Action );
+ void showDescription( cache::entity::Desktop );
+protected:
+ IconPolicy *m_policy;
+ std::vector< QWidget * > m_pages;
+ // IconPolicy m_defaultPolicy;
+};
+
+}
diff --git a/adept/adept/installerview.cpp b/adept/adept/installerview.cpp
new file mode 100644
index 0000000..052fa41
--- /dev/null
+++ b/adept/adept/installerview.cpp
@@ -0,0 +1,112 @@
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qtextbrowser.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+#include <kconfig.h>
+
+#include <cmath>
+
+#include <apt-front/cache/entity/desktop.h>
+#include <apt-front/predicate/factory.h>
+#include <ept/debtags/vocabulary.h>
+#include <adept/installerview.h>
+#include <adept/packageinfo.h>
+#include <adept/utils.h>
+
+using namespace adept;
+using namespace aptFront;
+using namespace cache;
+
+void InstallerView::rebuild()
+{
+ typedef predicate::Factory< entity::Desktop > Factory;
+ if ( m_inRebuild ) {
+ QTimer::singleShot( 500, this, SLOT( rebuild() ) );
+ return;
+ }
+ m_inRebuild = true;
+
+ component::Desktop &d = cache::Global::get().component< component::Desktop >();
+ ept::debtags::Vocabulary &t =
+ cache::Global::get().tags();
+
+ Predicate p = predicate::True< entity::Desktop >();
+ if ( m_search->text() != u8( "" ) ) {
+ Predicate tmp = Factory::name( u8( m_search->text() ) )
+ or Factory::description( u8( m_search->text() ) );
+ p = p and tmp;
+ }
+
+ std::string st = "";
+ int si = m_suite->currentItem();
+
+ if ( si == 0 ) st = "suite::kde";
+ if ( si == 1 ) st = "suite::gnome";
+
+ if ( st != "" )
+ p = p and Factory::tag( t.tagByName( st ) );
+
+ if ( !m_unsupported->isChecked() ) {
+ p = p and not Factory::sectionSubstring( "contrib" )
+ and not Factory::sectionSubstring( "universe" )
+ and not Factory::sectionSubstring( "multiverse" );
+ }
+
+ if ( !m_nonfree->isChecked() ) {
+ p = p and not Factory::sectionSubstring( "non-free" )
+ and not Factory::sectionSubstring( "multiverse" )
+ and not Factory::sectionSubstring( "restricted" );
+ }
+
+ selector()->fill( filteredRange( d.entries(), p ) );
+
+ m_inRebuild = false;
+}
+
+InstallerView::InstallerView( QWidget *p , const char *n )
+ : InstallerViewUi( p, n ), m_inRebuild( false )
+{
+ connect( m_search, SIGNAL( textChanged( const QString & ) ),
+ this, SLOT( textChanged() ) );
+ connect( &timer, SIGNAL( timeout() ), this, SLOT( rebuild() ) );
+ connect( m_suite, SIGNAL( activated( int ) ), this, SLOT( rebuild() ) );
+ connect( m_unsupported, SIGNAL( toggled( bool ) ), this, SLOT( rebuild() ) );
+ connect( m_nonfree, SIGNAL( toggled( bool ) ), this, SLOT( rebuild() ) );
+ connect( selector(), SIGNAL( showDescription( cache::entity::Desktop ) ),
+ this, SLOT( showDescription( cache::entity::Desktop ) ) );
+}
+
+void InstallerView::textChanged() {
+ timer.start( 1000, true );
+}
+
+void InstallerView::showDescription( entity::Desktop e )
+{
+ kdDebug() << "InstallerView::showDescription..." << endl;
+ QString file("/usr/share/app-install/desktop/" + e.package().name() + ".desktop");
+ KConfig desktopFile(QString("/usr/share/app-install/desktop/" + e.package().name() + ".desktop"), false, false);
+ QString name(desktopFile.name());
+
+ desktopFile.setGroup("Desktop Entry");
+ int popularity = desktopFile.readNumEntry("X-AppInstall-Popcon");
+
+ int popcon_max = 64284; //FIXME should be read at startup, this will change
+ int rank = 0;
+ if (popularity > 0) {
+ rank = (int)(5.0* log(popularity) / log(popcon_max+1));
+ }
+
+ QString rankText(" ");
+ for (int i = 0; i < rank; i++) {
+ rankText = rankText + "<img src='/usr/share/icons/crystalsvg/16x16/actions/bookmark.png' />";
+ }
+
+ QString l = u8(e.package().longDescription(
+ u8( i18n( "No long description available" ) ) ) );
+
+ m_description->setText( u8( "<b>" ) + e.name() + u8( "</b>" )
+ + u8("<br /><b>") + i18n("Rank: ") + u8("</b>") + rankText.latin1()
+ + i18n( "<br><b>Package:</b> " ) + e.package().name()
+ + formatLongDescription( l ) );
+}
diff --git a/adept/adept/installerview.h b/adept/adept/installerview.h
new file mode 100644
index 0000000..ed955dc
--- /dev/null
+++ b/adept/adept/installerview.h
@@ -0,0 +1,33 @@
+/** -*- C++ -*-
+ @file adept/installerview.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qtimer.h>
+#include <adept/installerviewui.h>
+#include <adept/groupeddesktopselector.h>
+
+#ifndef EPT_INSTALLERVIEW_H
+#define EPT_INSTALLERVIEW_H
+
+namespace adept {
+class InstallerView : public InstallerViewUi
+{
+ Q_OBJECT
+public:
+ typedef predicate::Predicate< entity::Desktop > Predicate;
+ InstallerView( QWidget *p = 0, const char *n = 0 );
+ GroupedDesktopSelector *selector() { return m_selector; }
+protected slots:
+ void textChanged();
+ void showDescription( cache::entity::Desktop );
+public slots:
+ void rebuild();
+protected:
+ bool m_inRebuild;
+ QTimer timer;
+};
+
+}
+
+#endif
diff --git a/adept/adept/installerviewui.ui b/adept/adept/installerviewui.ui
new file mode 100644
index 0000000..b289650
--- /dev/null
+++ b/adept/adept/installerviewui.ui
@@ -0,0 +1,203 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>InstallerViewUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>InstallerViewUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>666</width>
+ <height>314</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>4</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Search:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_search</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>KDE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>GNOME</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Any Suite</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_suite</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentItem">
+ <number>2</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Show:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_unsupported</cstring>
+ </property>
+ <property name="text">
+ <string>unsupported,</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_nonfree</cstring>
+ </property>
+ <property name="text">
+ <string>proprietary software.</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="adept::GroupedDesktopSelector" row="1" column="0">
+ <property name="name">
+ <cstring>m_selector</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>6</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QTextBrowser" row="1" column="1">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::GroupedDesktopSelector</class>
+ <header location="local">adept/groupeddesktopselector.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1122">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042949444154388db5954d6c545514c77ff7de37eff1a6a550da994e5ba798868f948fc847a2a2911816c436b0a02ed0083161a1981877ee10d90aa94656063491882c5cd4c4b8103f20cd806909a98604da8482341de80cb69de9bcd799799d79efba980f1da3a80b4f727273939bdff99f9b93f3175a6b6a21849080020c4002a29a8f0a5dcd002803bed63a1035f0d0d0504b6f6fef51d7758fa4d3e98d8ee3fc03af128ee3303939399548242eb8aefb09300f78464de9f0f0f0d148cc7caf3d5424de97a7ec17104220242805520a44557bbd4b21f083801d33e63a6d1bc7bf19c6064e0319a35a58b9ae7ba43d54e4d7c54b64dc097c7f09d30ef04b36736983cc7c11b4456b9b492c5e20dc54a6540e00896a8268a7017010f8bcae1830d2e9f4c69ebe3c197782b2ce60d94ddc9b30f9feeb45ae5d7181c5ead35636ef08d3ffe26a76ee3208b4031a56d80aa00768fda362e9380e25bf80ef3b587613d7afc099533380a4b5dda46fcb5aa42998b9eb7173dce5e6788e434763ec7fc942532008ea436003660d2caa7f8d69c3bd8910674e4d033e83877ad8d36fb0aa4d6058658ac5358c5df6383bf480f31fdda5a3632bbbfb6da4ccd5c00a10b2012cc12fd97cfb5516f0187c25cee0619396480ec3ca909d0f3372d1e5f9fe66de3ad605587c712ec55256a2540d5519d19ae24a29057329839f7ecc138944d833102290f3184ae1e6d6f0e98739c61229e6d21eafbed1c9c8c5558c8f3ee4ceed76946a1c43d97091828585223e2eebfbc295f60d45de89707628cb58224577bc85a79e5d4d786581cddb9b0148259711b20145836221400416e0232d1f6595c9ce4538773ac7b54406f0b15784e8e80aa1ac2594190220d021e49f2437960156b70ba095e95f96f18acd8c263cc6122962b1167a7ba34cdd7ec8c977a699bed546722a8fc2a02b6e2185fff78ab586ce78894ddb9ab9f5738ed14b1e030756929d8ff2e4ae5544632b38f96e89a99b298ebd6950cc2d12ed0eb3618b26f520788462ad09877df60db600f0f1fb49c646f21c7ebd836dcf94e9d9b4c0db27d6d3bd36c6426a96bce731703046d7da129a4670836284a054869d4f1b1c7e2dca67676ef3c1898091ef5ad8bc358c3205c93bf7c9a40ad4c660f4728edd7bbb3142ea2fc1da711cfc200011e08b45f6bd1c261adbce9717928c5f9d63fc6a19f0014567773303073790f8214bd6f5282dfbb8b9fa1f6b40d7c1939393533b92e63ad9240990484aec7e41b27d579cbb531e0f67023492d86316ebb768ba1e0f786e6f37e56550c62237aee7011e54abd7c1412291b8a06de378b4d3c0b215da9708e5a3a442192085404a83d4accfecac067c0c43e13a70e3fa12e96409e0325000966bbb354465339d04a6f9dd15fe6dde07ce030780278088d05ad72cc9a6b2f2daaaa74d75a1f0e8d0d5f60b40868a8364ead6248430000b0857a126ffcdf396abf03ce089ffcb4c7f033046c6b4a995e7a00000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/groupeddesktopselector.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/lister.cpp b/adept/adept/lister.cpp
new file mode 100644
index 0000000..ddd70d8
--- /dev/null
+++ b/adept/adept/lister.cpp
@@ -0,0 +1,818 @@
+// -*- Mode: C++; c-basic-offset: 4; -*-
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qpushbutton.h>
+#include <qthread.h>
+#include <qtextbrowser.h>
+#include <qpixmap.h>
+#include <qheader.h>
+
+#include <kpopupmenu.h>
+#include <kdebug.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+
+#include <functional>
+#include <iostream>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/actor.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/utils.h>
+#include <adept/lister.h>
+#include <adept/packageinfo.h>
+
+using namespace aptFront;
+using namespace aptFront::predicate;
+using namespace aptFront::cache;
+using namespace aptFront::utils;
+using namespace adept;
+
+#ifdef KUBUNTU
+QPixmap* main_icon = 0;
+QPixmap* non_main_icon = 0;
+#endif
+
+Lister::Lister( QWidget *parent, const char *name )
+ : ExtendableList( parent, name ),
+ m_rangeProvider( 0 ),
+ m_baseF( predicate::True< entity::Entity >() ),
+ m_interactiveF( True<entity::Entity>() ), m_itemCount( -1 ),
+ m_rebuildScheduled( false ), m_inRebuild( false ), m_cancelRebuild( false ),
+ m_openToplevel( false ), m_rebuildMutex( true )
+{
+ observeComponent< component::State >();
+ observeComponent< component::Packages >();
+ observeComponent< component::PackageTags >();
+ setRootIsDecorated( false );
+ setSelectionModeExt( Extended );
+ setAllColumnsShowFocus (true);
+
+#ifdef KUBUNTU
+ // The tip
+ // ListerItemTooltip* i_tip = new ListerItemTooltip(this);
+ setTooltipColumn(Lister::ColIcon);
+#endif //KUBUNTU
+
+ m_icons[ u8( "package-install" ) ] = u8( "adept_install" );
+ m_icons[ u8( "package-remove" ) ] = u8( "adept_remove" );
+ m_icons[ u8( "package-upgrade" ) ] = u8( "adept_upgrade" );
+ m_icons[ u8( "package-keep" )] = u8( "adept_keep" );
+ m_icons[ u8( "package-reinstall" )] = u8( "adept_reinstall" );
+ m_icons[ u8( "package-purge" )] = u8( "adept_purge" );
+
+ setSorting( -1 );
+ // addColumn(" ", 40);
+ // addColumn(" ", 18);
+ QFontMetrics met( font() );
+
+ // BE SURE TO UPDATE THE Column ENUM WHEN YOU UPDATE HERE!
+ addColumn( i18n( "Package" ), 180);
+#ifdef KUBUNTU
+ addColumn( i18n( " " ), 18); // This column is for identifying
+ // main packages. (manchicken)
+#endif
+ addColumn( i18n( "Status" ), met.width( i18n( "not installed" ) ) + 10 );
+ addColumn( i18n( "Requested" ), met.width( i18n( "Requested" ) ) + 10 );
+ addColumn( i18n( "Description" ), 300);
+ setToggleColumn( Lister::ColFirst );
+
+ for ( int col = ColFirst; col < ColLast; ++col )
+ setColumnAlignment( col, Qt::AlignLeft | Qt::AlignVCenter );
+
+ setResizeMode( LastColumn );
+ connect( this, SIGNAL( selectionChanged() ), SLOT( updateActions() ) );
+ connect( this,
+ SIGNAL( contextMenuRequested( QListViewItem *,
+ const QPoint &, int ) ),
+ this, SLOT(
+ contextMenu( QListViewItem *, const QPoint &, int) ) );
+ m_tip = 0;
+ // m_tip = new ListerTooltip( viewport(), this );
+}
+
+Lister::~Lister()
+{
+ delete m_tip;
+}
+
+void Lister::scheduleRebuild()
+{
+ if (!m_rebuildScheduled) {
+ // kdDebug() << "Lister scheduling rebuild" << endl;
+ QTimer::singleShot( 0, this, SLOT( rebuild() ) );
+ }
+ m_rebuildScheduled = true;
+}
+
+void Lister::updateActions()
+{
+ emit actionsChanged( this );
+}
+
+void Lister::notifyPostChange( component::Base * )
+{
+ kdDebug() << "notifyRefresh()" << endl;
+ updateActions();
+ triggerUpdate();
+}
+
+void Lister::notifyPreRebuild( component::Base *b )
+{
+ kdDebug() << "Lister::notifyPreRebuild( " << b << " )" << endl;
+ // Cache &c = cache::Global::get( m_cache );
+ setEnabled( false );
+ if ( dynamic_cast< component::PackageTags * >( b ) != 0 ) {
+ kdDebug() << "clearing cardinality" << endl;
+ m_cardinality.clear();
+ }
+ if ( dynamic_cast< component::Packages * >( b ) != 0 ) {
+ kdDebug() << "clearing lister" << endl;
+ clear();
+ m_items.clear();
+ m_cardinality.clear();
+ }
+}
+
+void Lister::notifyPostRebuild( component::Base *b )
+{
+ kdDebug() << "Lister::notifyPostRebuild( " << b << " )" << endl;
+ scheduleRebuild();
+ if ( dynamic_cast< component::State * >( b ) != 0 ) {
+ setEnabled( true );
+ }
+}
+
+bool lessByName( const entity::Entity &e1, const entity::Entity &e2 )
+{
+ if ( e1.is< entity::Named >() && e2.is< entity::Named >() ) {
+ entity::Named &n1 = downcast< entity::Named >( e1 ),
+ &n2 = downcast< entity::Named >( e2 );
+ return n1.name() < n2.name();
+ }
+ return e1 < e2;
+}
+
+bool Lister::cancelRebuild() {
+ // kdDebug() << "cancel rebuild: " << m_inRebuild << ", " << m_cancelRebuild << endl;
+ if ( m_inRebuild ) {
+ m_rebuildScheduled = false;
+ m_cancelRebuild = true;
+ }
+ if ( !cache::Global::get( m_cache ).isOpen() ) {
+ m_rebuildScheduled = false;
+ return true;
+ }
+ return m_cancelRebuild;
+}
+
+void Lister::cleanRebuild()
+{
+ scheduleRebuild();
+}
+
+Lister::CreateItem::CreateItem( Lister *_l, ListerItem *p )
+ : l( _l ), time( 0 ), items( 0 ), last( 0 ), parent( p )
+{
+}
+
+Lister::CreateItem::~CreateItem()
+{
+ // delete timer;
+}
+
+Lister::Map::value_type Lister::CreateItem::operator()( entity::Entity e )
+{
+ items ++;
+ if ( l->m_cancelRebuild ) throw 0; // XXX proper exception please
+ // kdDebug() << "trying to acquire mutex" << endl;
+ l->m_rebuildMutex.lock();
+ // kdDebug() << "mutex acquired" << endl;
+
+ // count tags
+ if ( e.is< entity::Package >() ) {
+ const std::set<ept::debtags::Tag> &tags = downcast< entity::Package >( e ).tags();
+ for (std::set<ept::debtags::Tag>::iterator i = tags.begin(); i != tags.end(); ++ i )
+ l->m_cardinality[ *i ] ++;
+ }
+
+ if ( last ) {
+ if ( parent )
+ last = new ListerItem( parent, last, e );
+ else
+ last = new ListerItem( l, last, e );
+ } else {
+ if ( parent )
+ last = new ListerItem( parent, e );
+ else
+ last = new ListerItem( l, e );
+ }
+ l->m_rebuildMutex.unlock();
+ if ( e.is< entity::Relation >() )
+ // this should be safe because the parent thread is waiting
+ // for us and ensures that universe (libapt-front) is kept
+ // unchanged while we run
+ l->insertRangeInternal( InsertRangePair(
+ last, downcast< entity::Relation >( e ).targetPackages() ) );
+ // we may want to use recursive async call instead? why?
+ /* Threads::enqueue(
+ asyncCall( std::bind2nd( std::mem_fun( &Lister::insertRangeInternal ),
+ InsertRangePair(
+ last,
+ downcast< entity::Relation >( e ).targetPackages() ) ),
+ l ), &(l->m_rebuildMutex) );
+ */
+ return std::make_pair( e, last );
+}
+
+void Lister::reallyUpdate()
+{
+ bool en = isUpdatesEnabled();
+ setUpdatesEnabled( true );
+ triggerUpdate();
+ setUpdatesEnabled( en );
+}
+
+void Lister::insertRange( Range r ) {
+ insertRangeInternal( InsertRangePair( 0, r ) );
+}
+void Lister::insertRangeInternal( InsertRangePair a )
+{
+ // kdDebug() << "insertRange running..." << endl;
+ try {
+ std::transform( a.second, a.second.end(),
+ inserter( m_items, m_items.begin() ),
+ CreateItem( this, a.first ) );
+ } catch ( ... ) {}
+ m_itemCount = m_items.size();
+}
+
+/* void Lister::rebuildInsertRange( Range r ) {
+ insertRange( 0, r );
+ } */
+
+void Lister::rebuild()
+{
+ Cache &c = cache::Global::get( m_cache );
+ if ( cancelRebuild() ) {
+ scheduleRebuild();
+ return;
+ }
+
+ m_inRebuild = true;
+ m_rebuildMutex.lock();
+
+ emit rebuildStarted();
+
+ c.progress().OverallProgress( 0, 0, 0, i18n( "Filtering" ) );
+ kdDebug() << "rebuild running" << endl;
+ clock_t _c = clock(), C;
+ for ( Cardinality::iterator i = m_cardinality.begin();
+ i != m_cardinality.end(); ++i )
+ i->second = 0;
+
+ kdDebug() << "querying m_rangeProvider " << m_rangeProvider << "..." << endl;
+
+ Range r = filteredRange( m_rangeProvider ?
+ m_rangeProvider->listerRange() : range( VectorRange() ),
+ m_baseF );
+ C = (clock() - _c) / 1000; _c = clock();
+
+ setUpdatesEnabled( false );
+ kdDebug() << "clearing..." << endl;
+ clear();
+ m_items.clear();
+
+ kdDebug() << "asyncCall to rebuildInsertRange..." << endl;
+ QThread *t = asyncCall( std::bind2nd(
+ std::mem_fun( &Lister::insertRangeInternal ),
+ InsertRangePair( 0, r ) ),
+ this );
+
+ kdDebug() << "starting the thread..." << endl;
+
+ QTimer timer;
+ connect( &timer, SIGNAL( timeout() ),
+ this, SLOT( reallyUpdate() ) );
+ timer.start( 0 );
+
+ m_rebuildMutex.unlock();
+ Threads::enqueue( t, &m_rebuildMutex );
+ Threads::wait();
+
+ timer.stop();
+
+ kdDebug() << "thread finished..." << endl;
+ C = (clock() - _c) / 1000; _c = clock();
+ kdDebug() << m_items.size() << " entities synced, time = " << C << endl;
+
+ setUpdatesEnabled( true );
+ c.progress().Done();
+ if ( m_openToplevel ) openToplevel();
+ triggerUpdate();
+
+ if ( !m_cancelRebuild ) {
+ for ( Cardinality::iterator i = m_cardinality.begin();
+ i != m_cardinality.end(); ++i )
+ if ( i->second == m_itemCount )
+ i->second = -1;
+ emit cardinalityChanged( m_cardinality );
+ }
+
+ m_inRebuild = false;
+ m_rebuildScheduled = false;
+ m_cancelRebuild = false;
+ emit rebuildFinished();
+}
+
+void Lister::baseAnd( Predicate o )
+{
+ m_baseF = predicate::predicate( m_baseF and o );
+ // emit filterChanged( m_baseF );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+void Lister::baseSet( Predicate o )
+{
+ m_baseF = o;
+ // emit filterChanged( m_baseF );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+void Lister::interactiveAnd( Predicate o )
+{
+ m_interactiveF = predicate::predicate( m_interactiveF and o );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+void Lister::interactiveDrop( Predicate o )
+{
+ m_interactiveF = predicate::remove( m_interactiveF, o );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+bool Lister::itemSelected( Map::value_type i )
+{
+ return not i.second->isSelected();
+}
+
+entity::Entity Lister::extractKey( Map::value_type i )
+{
+ return i.first;
+}
+
+Lister::VectorRange Lister::selection()
+{
+ VectorRange ret;
+ Map m;
+ std::remove_copy_if( m_items.begin(), m_items.end(),
+ inserter( m, m.begin() ),
+ itemSelected );
+ std::transform( m.begin(), m.end(),
+ consumer( ret ),
+ extractKey );
+ return ret;
+}
+
+Lister::VectorRange Lister::content()
+{
+ VectorRange ret;
+ std::transform( m_items.begin(), m_items.end(),
+ consumer( ret ),
+ extractKey );
+ return ret;
+}
+
+QString ListerItem::text( int column ) const
+{
+ // if (column == 0) return ""; // until we redo paintcell for the col
+ if (entity().is<entity::Package>()) {
+ entity::Package p = entity();
+ switch (column) {
+
+ case Lister::ColPackage: return u8( p.name( u8( i18n( "n/a" ) ) ) );
+ case Lister::ColStatus: return u8( p.statusString( u8( i18n( "n/a" ) ) ) );
+ case Lister::ColRequested: return u8( p.actionString( u8( i18n( "n/a" ) ) ) );
+ case Lister::ColDescription: return u8( p.shortDescription( u8( i18n( "n/a" ) ) ) );
+ // case 2: return p.candidateVersion().versionString();
+ }
+ }
+ if ( entity().is< entity::Relation >() && column == 0 )
+ return downcast< entity::Relation >( entity() ).format();
+ return u8( "" );
+}
+
+#ifdef KUBUNTU
+const QPixmap* ListerItem::pixmap( int column ) const
+{
+ if (entity().is<entity::Package>()) {
+ entity::Package p = entity();
+
+ // Are we in a main repo? A slash indicates a non-main repo.
+ if (column == Lister::ColIcon &&
+ p.section(string("/")).find("/") == string::npos) {
+
+ // Load the icon if it hasn't been created.
+ if (main_icon == 0) {
+ main_icon = new QPixmap(SmallIcon(u8("adept_main_indicator")));
+ }
+
+ // Return the icon...
+ return main_icon;
+ } else if (column == Lister::ColFirst) {
+ return static_cast<const QPixmap*>(&m_pixmap);
+ }
+ }
+
+ if (non_main_icon == 0) {
+ non_main_icon = new QPixmap();
+ }
+
+ return non_main_icon;
+}
+#endif /* KUBUNTU */
+
+ListerItem::~ListerItem()
+{
+}
+
+void ListerItem::paintCell ( QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ if ( width <= 0 )
+ return;
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ if ( entity().is<entity::Package>() ) {
+ entity::Package p = entity();
+
+ // Paint the status column
+ if ( column == Lister::ColStatus ) {
+ c = statusColor( p );
+ }
+
+ // Paint the action column
+ if ( column == Lister::ColRequested ) {
+ c = actionColor( p );
+ }
+ }
+ _cg.setColor( QColorGroup::Text, c );
+ if ( extender() ) { // make the icon appear at top... this
+ // probably breaks big-text displays?
+ // --> somewhat, but not too badly
+ alignment &= ~AlignVertical_Mask;
+ alignment |= AlignTop;
+ }
+ KListViewItem::paintCell( &_p, _cg, column, width, alignment );
+ p->drawPixmap( 0, 0, pm );
+}
+
+void Lister::contextMenu( QListViewItem *it, const QPoint &pt, int /*c*/ )
+{
+ if (! it) // check for actor when we have one...
+ return;
+ m_context = dynamic_cast< ListerItem * >( it );
+ VectorRange sel = selection();
+ // entity::Package p = (dynamic_cast<ListerItem *>(it)->entity());
+ KPopupMenu *m = new KPopupMenu (this);
+ utils::Range< Actor > r = actor::Global< entity::Package >::list();
+ int id = 8;
+ try {
+ for (; r != r.end(); ++r) {
+ m->insertItem( SmallIconSet( m_icons[ u8( r->name() ) ] ),
+ i18n(QString(r->prettyName()).ascii()), id );
+ m->setItemEnabled(
+ id, r->possible( utils::upcastRange< entity::Package >( sel ) ) );
+ ++id;
+ }
+ } catch ( std::bad_cast ) {} // ignore (this is broken, but
+ // easiest fix)
+ bool open = m_context->extender();
+ m->insertItem( open ? i18n( "Hide details" ) :
+ i18n( "Show details" ), open ? 1 : 0 );
+ connect(m, SIGNAL(activated(int)), this, SLOT(contextActivated(int)));
+ m->exec(pt);
+ delete m;
+}
+
+void Lister::contextActivated( int id )
+{
+ VectorRange sel = selection();
+ try {
+ if (id >= 8) {
+ utils::Range< Actor > r = actor::Global< entity::Package >::list();
+ std::advance( r, id - 8 );
+ (*r)( utils::upcastRange< entity::Package >( sel ) );
+ updateActions();
+ }
+ if (id < 8) {
+ VectorRange i = sel.begin();
+ while (i != i.end()) {
+ if (id == 0)
+ m_items[*i]->showExtender();
+ if (id == 1)
+ m_items[*i]->hideExtender();
+ ++ i;
+ }
+ }
+ } catch ( std::bad_cast ) {} // ignore (this is broken, but
+}
+
+ListerItemExtender::~ListerItemExtender()
+{
+}
+
+ListerItemExtender::ListerItemExtender( QWidget *parent, const char * n)
+ : ListerItemExtenderUi( parent, n )
+{
+ observeComponent< component::State >();
+ adjustFontSize( m_description, -1 );
+ connect( m_details, SIGNAL( clicked() ),
+ this, SLOT( detailsClicked() ) );
+
+ m_packageInfo->adjustFontSize( -1 );
+ m_packageInfo->hideStatus();
+}
+
+void ListerItemExtender::detailsClicked() {
+ detailsRequested( m_entity );
+}
+
+ListerItem *ListerItemExtender::item()
+{
+ return dynamic_cast< ListerItem * >( m_item );
+}
+
+void ListerItemExtender::mouseReleaseEvent( QMouseEvent *e ) {
+ e->ignore();
+ if ( childAt( e->pos() ) != static_cast< QWidget * >( m_name ) )
+ e->accept();
+}
+void ListerItemExtender::setItem( ExtendableItem *i )
+{
+ ItemExtender::setItem( i );
+ m_entity = item()->entity();
+ // setupColors();
+ m_indicator->setPixmap(*(item()->pixmap(Lister::ColIcon)));
+ m_indicator->setMinimumWidth(18);
+
+ kdDebug() << "ListerItemExtender::setItem connecting" << endl;
+ connect( this, SIGNAL( detailsRequested( Lister::Entity ) ),
+ item()->list(), SIGNAL( detailsRequested( Lister::Entity ) ) );
+
+ entity::Version v;
+ entity::Package p;
+
+ if ( m_entity.is< entity::Version >() ) {
+ v = m_entity;
+ p = v.package();
+ }
+
+ if ( m_entity.is< entity::Package >() ) {
+ p = m_entity;
+ v = p.anyVersion();
+ }
+
+ if ( !v.valid() ) {
+ m_logical->setText( i18n( "Immutable" ) );
+ m_logical->setEnabled( false );
+ m_details->setEnabled( false );
+ return;
+ }
+
+ m_name->setText( /* QString( "<b>" ) + */
+ v.package().name( std::string( "oops" ) ) /* + "</b>" */ );
+ QString l = u8( v.longDescription(
+ u8( i18n( "No long description available" ) ) ) );
+
+ m_description->setText( QString( "<qt>" )
+ + formatLongDescription( l ) + "</qt>" );
+ m_description->adjustSize();
+ m_description->installEventFilter( this );
+
+ m_packageInfo->setVersion( v, m_entity.is< entity::Version >() );
+
+ notifyPostChange( 0 );
+}
+
+void ListerItemExtender::notifyPostRebuild( component::Base *b )
+{ // need to catch undo/redo effects
+ return notifyPostChange( b );
+}
+
+void ListerItemExtender::notifyPostChange( component::Base * )
+{
+ // without the timer to break it, there could be a loop where
+ // we connect the clicked() signal to a slot which would be
+ // invoked right away when we return -> evil
+ QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
+}
+
+void ListerItemExtender::updateLogical() {
+ entity::Package pkg = entity();
+ EntityActor *a = 0;
+
+ m_status->setText( colorify(
+ statusColor( pkg ),
+ u8( pkg.statusString( u8( i18n( "Unknown" ) ) ) ) ) );
+ m_change->setText( colorify(
+ actionColor( pkg ),
+ u8( pkg.actionString( u8( i18n( "Unknown" ) ) ) ) ) );
+
+
+ m_logical->setEnabled( true );
+ if (pkg.canKeep()) {
+ a = new EntityActor( pkg.keep() );
+ } else if (pkg.canUpgrade()) {
+ a = new EntityActor( pkg.upgrade() );
+ } else if (pkg.canInstall()) {
+ a = new EntityActor( pkg.install() );
+ } else if (pkg.canRemove()) {
+ a = new EntityActor( pkg.remove() );
+ }
+
+ if (a) {
+ m_logical->setText( u8( a->actor().prettyName() ) );
+ connect( m_logical, SIGNAL( clicked() ),
+ a, SLOT( destructiveAct() ) );
+ } else {
+ m_logical->setText( i18n( "Immutable" ) );
+ m_logical->setEnabled( false );
+ }
+
+}
+
+bool ListerItemExtender::eventFilter( QObject *o, QEvent *e )
+{
+ if (o == m_description && e->type() == QEvent::Wheel) {
+ // kdDebug() << "discarding wheel event..." << endl;
+ QApplication::sendEvent( this, e );
+ return true;
+ }
+ return false;
+}
+
+void ListerItemExtender::resize( int w, int h )
+{
+ // XXX the magic constants are probably style-dependent... AW
+ int namew = - item()->lister()->extenderOffset( item() )
+ - layout()->margin()
+ - layout()->spacing()
+ + item()->lister()->columnWidth( 0 );
+ int statw = item()->lister()->columnWidth( Lister::ColStatus )
+ - layout()->spacing();
+ int chw = item()->lister()->columnWidth( Lister::ColRequested )
+ - layout()->spacing() - 3; // wth...
+ m_name->setMinimumWidth( namew );
+ m_status->setMinimumWidth( statw );
+ m_change->setMinimumWidth( chw );
+ m_packageInfo->adjustSize();
+ m_leftHeight = m_name->height() + m_packageInfo->height()
+ + m_logical->height() + 20;
+ QWidget::resize( w, 500 );
+ QWidget::resize(
+ w,
+ QMAX( m_description->contentsHeight() + 16,
+ m_leftHeight ) );
+}
+
+bool entityLess::operator()( entity::Entity e1, entity::Entity e2 )
+{
+ if ( e1.is< entity::Package >() ) {
+ if ( e2.is< entity::Package >() )
+ return e1 < e2;
+ return true;
+ }
+
+ if ( e1.is< entity::Version >() ) {
+ if ( e2.is< entity::Package >() )
+ return false;
+ if ( e2.is< entity::Version >() )
+ return e1 < e2;
+ return true;
+ }
+
+ if ( e1.is< entity::Relation >() ) {
+ if ( e2.is< entity::Package >() )
+ return false;
+ if ( e2.is< entity::Version >() )
+ return false;
+ if ( e2.is< entity::Relation >() )
+ return e1 < e2;
+ return true;
+ }
+ return true;
+}
+
+bool ListerItem::less( const ExtendableItem *b ) const
+{
+ entity::Entity e1 = entity(), e2 = dynamic_cast< const ListerItem * >( b )->entity();
+ return entityLess()( e1, e2 );
+}
+
+bool ListerItem::keepLess( const ListerItem *o ) const
+{
+ const ListerItem *b = o;
+ while ( b != 0 ) {
+ if ( b == this )
+ return false;
+ b = b->m_previous;
+ }
+ while ( o != 0 ) {
+ o = dynamic_cast< const ListerItem * >( o->nextSibling() );
+ if ( o == this )
+ return true;
+ }
+ return false;
+}
+
+QString ListerTooltip::format( const QString &what,
+ const QString &txt, bool nobr )
+{
+ QString ret = "<b>" + what + "</b>&nbsp;" + (nobr ? "<nobr>" : "")
+ + txt + (nobr ? "</nobr>" : "") + "<br>";
+ return ret;
+}
+
+void ListerTooltip::maybeTip( const QPoint &pt )
+{
+ if ( !m_parent )
+ return;
+ kdDebug() << "ListTreeWidgetTooltip::maybeTip ()" << endl;
+ ListerItem *x = dynamic_cast<ListerItem *>( m_parent->itemAt( pt ) );
+ if ( !x )
+ return;
+ if ( x->extender() )
+ return; // no tips for extended items, thank you
+ QString str = u8( "<qt>" );
+ QString descr, cand, cur;
+ descr = cand = cur = i18n( "<i>Not available</i>" );
+ entity::Package p( x->entity() );
+ descr = p.shortDescription( std::string(
+ i18n( "<i>Not available</i>" ).local8Bit() ) );
+ try {
+ cand = u8( p.candidateVersion().versionString() );
+ } catch (...) {}
+ try {
+ cur = u8( p.installedVersion().versionString() );
+ } catch (...) {}
+
+ str += format( i18n( "Package:" ), u8( p.name() ) );
+ str += format( i18n( "Description:" ), descr );
+ str += format( i18n( "Current&nbsp;Version:" ), cur );
+ str += format( i18n( "Candidate&nbsp;Version:" ), cand );
+
+ str.append( u8( "</qt>" ) );
+ tip( m_parent->itemRect( x ), str );
+}
+
+void ListerItemTooltip::maybeTip(const QPoint& pt) {
+ if (!m_parent) {
+ return;
+ }
+
+ // Grab the column
+ const int col = m_parent->header()->sectionAt(pt.x());
+ if (col != Lister::ColIcon) {
+ return;
+ }
+
+ // Grab the item
+ const QListViewItem* item = m_parent->itemAt(pt);
+ if (!item) {
+ return;
+ } else if (item->pixmap(col) != main_icon) {
+ // Ignore items without pixmaps, as they have no indicator.
+ return;
+ }
+
+ // Grab the item rectangle
+ const QRect irect = m_parent->itemRect(item);
+ if (!irect.isValid()) {
+ return;
+ }
+
+ // Grab the header rectangle
+ const QRect hrect = m_parent->header()->sectionRect(col);
+ if (!hrect.isValid()) {
+ return;
+ }
+
+ // Grab the cell rectangle
+ const QRect cell(hrect.left(), irect.top(),
+ hrect.width(), irect.height());
+ tip(cell, i18n("This logo indicates that this package is officially supported by the Kubuntu development and support teams."));
+}
diff --git a/adept/adept/lister.h b/adept/adept/lister.h
new file mode 100644
index 0000000..6270c42
--- /dev/null
+++ b/adept/adept/lister.h
@@ -0,0 +1,261 @@
+/** -*- C++ -*-
+ @file adept/lister.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#define KUBUNTU
+
+#include <qtooltip.h>
+#include <qmap.h>
+#include <qmutex.h>
+#include <set>
+#include <qpixmap.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/actor.h>
+#include <apt-front/predicate/matchers.h>
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/utils/range.h>
+
+#include <adept/extendablelist.h>
+#include <adept/listerextenderui.h>
+#include <adept/actor.h>
+#include <adept/listerpredicate.h>
+
+#ifndef EPT_LISTER_H
+#define EPT_LISTER_H
+
+class KLineEdit;
+
+namespace adept {
+
+using namespace aptFront;
+using namespace aptFront::cache;
+class ListerTooltip;
+class ListerItemTooltip;
+class ListerItemExtender;
+class ListerItem;
+class Lister;
+
+struct entityLess {
+ bool operator()( entity::Entity e1, entity::Entity e2 );
+};
+
+class Lister: public ExtendableList, public Observer
+{
+ Q_OBJECT;
+public:
+ static const int ColPackage = 0;
+#ifdef KUBUNTU
+ static const int ColIcon = 1;
+ static const int ColStatus = 2;
+ static const int ColRequested = 3;
+ static const int ColDescription = 4;
+ static const int ColLast = 4;
+#else
+ static const int ColStatus = 1;
+ static const int ColRequested = 2;
+ static const int ColDescription = 3;
+ static const int ColLast = 3;
+#endif
+ static const int ColFirst = 0;
+ typedef entity::Entity Entity;
+ typedef std::vector< Entity > Vector;
+ typedef utils::Range< Entity > Range;
+ typedef utils::VectorRange< Entity > VectorRange;
+ typedef std::set< Entity > Set;
+ typedef std::map< Entity, ListerItem *, entityLess > Map;
+ typedef actor::Actor< entity::Package > Actor;
+ typedef predicate::Predicate< Entity > Predicate;
+ typedef std::map< ept::debtags::Tag, int > Cardinality;
+ struct RangeProvider {
+ virtual Range listerRange() = 0;
+ };
+
+ Lister (QWidget *parent = 0, const char *name = 0);
+ ~Lister();
+ void setSource();
+ virtual void notifyPostChange( component::Base * );
+ virtual void notifyPreRebuild( component::Base * );
+ virtual void notifyPostRebuild( component::Base * );
+ VectorRange selection();
+ VectorRange content();
+ int itemCount() { return m_itemCount; }
+ // void setRange( const Range &r ) { m_range = r; }
+ void setRangeProvider( RangeProvider *r ) { m_rangeProvider = r; }
+ void insertRange( Range );
+ void setOpenToplevel( bool o ) { m_openToplevel = o; }
+
+ bool busy() { return m_rebuildScheduled || m_inRebuild; }
+
+signals:
+ // this is adept::Lister because of braindead moc
+ void actionsChanged( adept::Lister * );
+ void cardinalityChanged( const Lister::Cardinality & );
+ void detailsRequested( Lister::Entity );
+ void rebuildStarted();
+ void rebuildFinished();
+ // void filterChanged( Lister::Predicate );
+
+public slots:
+ virtual void cleanRebuild();
+ virtual void rebuild();
+ virtual void baseAnd( ListerPredicate );
+ virtual void interactiveDrop( ListerPredicate );
+ virtual void interactiveAnd( ListerPredicate );
+ virtual void baseSet( ListerPredicate );
+ virtual void updateActions();
+ virtual void scheduleRebuild();
+ virtual void reallyUpdate();
+protected slots:
+ void contextMenu( QListViewItem *, const QPoint &, int );
+ void contextActivated( int );
+protected:
+ typedef std::pair< ListerItem *, Range > InsertRangePair;
+ void insertRangeInternal( InsertRangePair );
+ ListerTooltip *m_tip;
+
+ static Entity extractKey( Map::value_type );
+ static bool itemSelected( Map::value_type );
+
+ struct CreateItem {
+ CreateItem( Lister *, ListerItem * );
+ ~CreateItem();
+ Map::value_type operator()( Entity );
+ Lister *l;
+ int time;
+ int items;
+ ListerItem *last;
+ ListerItem *parent;
+ };
+
+ bool cancelRebuild();
+ void rebuildInsertRange( Range );
+
+ ListerItem *m_context;
+ QMap< QString, QString > m_icons;
+ Map m_items;
+ Vector m_all;
+ RangeProvider *m_rangeProvider;
+ Predicate m_baseF, m_interactiveF;
+ int m_itemCount;
+ bool m_rebuildScheduled:1;
+ bool m_inRebuild:1;
+ bool m_cancelRebuild:1;
+ bool m_openToplevel:1;
+ Cardinality m_cardinality;
+ QMutex m_rebuildMutex;
+};
+
+class ListerTooltip : public QToolTip
+{
+public:
+ ListerTooltip (QWidget *v, Lister *p) : QToolTip (v, 0), m_parent (p) {};
+ ListerTooltip(Lister*p) : QToolTip(p,0), m_parent(p) {};
+protected:
+ QString format( const QString &, const QString &, bool = true );
+ virtual void maybeTip (const QPoint &p);
+ Lister *m_parent;
+};
+
+class ListerItemTooltip : public QToolTip {
+public:
+ ListerItemTooltip(const Lister* parent) :
+ QToolTip(parent->viewport(),0),
+ m_parent(parent) {};
+
+protected:
+ const Lister* m_parent;
+ virtual void maybeTip (const QPoint& p);
+};
+
+class ListerItemExtender : public ListerItemExtenderUi,
+ public cache::Observer {
+ Q_OBJECT
+public:
+ ListerItemExtender( QWidget *parent = 0, const char * n = 0 );
+ ~ListerItemExtender();
+ virtual void resize( int w, int h );
+ void setItem( ExtendableItem *i );
+ ListerItem *item();
+ entity::Entity entity() const { return m_entity; }
+ void notifyPostChange( component::Base * );
+ void notifyPostRebuild( component::Base * );
+protected slots:
+ void detailsClicked();
+ void updateLogical();
+signals:
+ void detailsRequested( Lister::Entity );
+protected:
+ bool eventFilter( QObject *o, QEvent *e );
+ void mouseReleaseEvent( QMouseEvent *e );
+ entity::Entity m_entity;
+ unsigned m_leftHeight;
+};
+
+class ListerItem: public ExtendableItem
+{
+public:
+ ListerItem(Lister *v, entity::Entity e)
+ : ExtendableItem (v), m_previous( 0 ), m_entity( e )
+ {};
+
+ ListerItem(Lister *v, ListerItem *i, entity::Entity e)
+ : ExtendableItem( v, i ), m_previous( i ), m_entity( e )
+ {};
+
+ ListerItem(ListerItem *p, ListerItem *i, entity::Entity e)
+ : ExtendableItem( p, i ), m_previous( i ), m_entity( e )
+ {};
+
+ ListerItem(ListerItem *p, entity::Entity e)
+ : ExtendableItem( p ), m_previous( 0 ), m_entity( e )
+ {};
+
+ ~ListerItem();
+
+ virtual ItemExtender *createExtender() {
+ if ( extendable() )
+ return new ListerItemExtender();
+ return 0;
+ }
+
+ /* virtual void updateIcon( const QPixmap &p ) {
+ if ( m_entity.is< entity::Package >()
+ || m_entity.is< entity::Version >() )
+ return ExtendableItem::updateIcon( p );
+ setPixmap( list()->toggleColumn(), QPixmap() );
+ } */
+
+ virtual QString text( int column ) const;
+#ifdef KUBUNTU
+ virtual void setUpdatedIcon(QPixmap& pm) { m_pixmap=pm; };
+ virtual const QPixmap* pixmap( int column ) const;
+#endif
+ entity::Entity entity() { return m_entity; }
+ const entity::Entity entity() const { return m_entity; }
+ virtual void paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment);
+ virtual bool less( const ExtendableItem * ) const;
+ Lister *lister() {
+ return dynamic_cast< Lister* >( listView() );
+ }
+
+ // beware, makes sort O(n^2lg(n^2))
+ bool keepLess( const ListerItem *o ) const;
+ virtual bool extendable() const {
+ return ( entity().is< entity::Package >()
+ || m_entity.is< entity::Version >() );
+ }
+
+protected:
+ ListerItem *m_previous;
+ entity::Entity m_entity;
+ QPixmap m_pixmap;
+ // ListerItemTooltip* m_tip;
+};
+
+}
+
+#endif /* ifndef PKGLIST_H */
diff --git a/adept/adept/listerextenderui.ui b/adept/adept/listerextenderui.ui
new file mode 100644
index 0000000..3f89eaf
--- /dev/null
+++ b/adept/adept/listerextenderui.ui
@@ -0,0 +1,309 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::ListerItemExtenderUi</class>
+<widget class="adept::ItemExtender">
+ <property name="name">
+ <cstring>ListerItemExtenderrUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>587</width>
+ <height>230</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>ListerItemExtenderrUi</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <spacer row="4" column="2">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>4</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="3">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>4</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>name</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_indicator</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_status</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>status</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_change</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>change</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QTextBrowser" row="0" column="2" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="resizePolicy">
+ <enum>AutoOneFit</enum>
+ </property>
+ <property name="vScrollBarMode">
+ <enum>AlwaysOff</enum>
+ </property>
+ <property name="hScrollBarMode">
+ <enum>AlwaysOff</enum>
+ </property>
+ <property name="text">
+ <string>description...</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_logical</cstring>
+ </property>
+ <property name="text">
+ <string>logical</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_details</cstring>
+ </property>
+ <property name="text">
+ <string>Details</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="adept::PackageInfo" row="1" column="1">
+ <property name="name">
+ <cstring>m_packageInfo</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>80</height>
+ </size>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>1</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::PackageInfo</class>
+ <header location="global">adept/packageinfo.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
+ </image>
+</images>
+<includes>
+ <include location="global" impldecl="in declaration">adept/extendablelist.h</include>
+</includes>
+<layoutdefaults spacing="0" margin="4"/>
+<includehints>
+ <includehint>adept/packageinfo.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/listerpredicate.h b/adept/adept/listerpredicate.h
new file mode 100644
index 0000000..98f1b41
--- /dev/null
+++ b/adept/adept/listerpredicate.h
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/predicate/predicate.h>
+
+#ifndef EPT_LISTERPREDICATE_H
+#define EPT_LISTERPREDICATE_H
+
+namespace adept {
+using namespace aptFront;
+using namespace cache;
+typedef predicate::Predicate< entity::Entity > ListerPredicate;
+}
+
+#endif
diff --git a/adept/adept/packagedetails.cpp b/adept/adept/packagedetails.cpp
new file mode 100644
index 0000000..56dd80b
--- /dev/null
+++ b/adept/adept/packagedetails.cpp
@@ -0,0 +1,273 @@
+#include <qtoolbutton.h>
+#include <qtextbrowser.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <qpushbutton.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+
+#include <kfileitem.h>
+#include <kfiledetailview.h>
+#include <kapplication.h>
+
+#include <adept/lister.h>
+#include <adept/tagchooser.h>
+#include <adept/packageinfo.h>
+#include <adept/packagedetails.h>
+#include <adept/utils.h>
+#include <adept/changelog.h>
+
+#include <fstream>
+
+using namespace adept;
+
+ItemChangelog* global_changelog = new ItemChangelog();
+
+PackageDetails::PackageDetails( QWidget *w, const char *n )
+ : PackageDetailsUi( w, n ),
+ m_thread( 0 ),
+ m_qtMutex( true ),
+ m_logicalAct( 0 ), m_removeAct( 0 ),
+ m_fileListRunning( false )
+{
+ m_toolbar->setIconSize( 22 );
+ m_toolbar->setIconText( KToolBar::IconTextRight );
+
+ m_toolbar->insertButton( u8( "back" ), BBack, false, i18n( "Back" ) );
+ m_toolbar->insertButton( u8( "forward" ), BForward, false, i18n( "Forward" ) );
+ m_toolbar->insertLineSeparator();
+ m_toolbar->insertButton( u8( "" ), BShow, true, i18n( "Show List" ) );
+
+ m_tags->setTitle( i18n( "Assigned Tags" ) );
+
+ m_lister->setRangeProvider( this ); // wee
+ // m_lister->setOpenToplevel( true );
+
+ m_description->setPaper( QBrush( colorGroup().background() ) );
+
+ connect( m_toolbar->getButton( BShow ), SIGNAL( clicked() ),
+ this, SIGNAL( showList() ) );
+ connect( m_toolbar->getButton( BBack ), SIGNAL( clicked() ),
+ this, SIGNAL( back() ) );
+ connect( m_toolbar->getButton( BForward ), SIGNAL( clicked() ),
+ this, SIGNAL( forward() ) );
+ connect( m_lister, SIGNAL( detailsRequested( Lister::Entity ) ),
+ this, SIGNAL( detailsRequested( Lister::Entity ) ) );
+
+ observeComponent< component::State >();
+
+ adjustFontSize( m_name, 1 );
+
+ Cache &c = cache::Global::get( m_cache );
+ component::Packages::iterator i = c.packages().packagesBegin();
+ while ( !i->hasVersion() ) ++i; // ha hum...
+ setPackage( *i );
+}
+
+Lister::Range PackageDetails::listerRange() {
+ utils::Range< entity::Relation > r = m_package.depends();
+ utils::VectorRange< entity::Entity > vr;
+ while ( r != r.end() ) {
+ if ( !r->targetPackages().empty() )
+ std::cerr << r->targetPackages()->name() << std::endl;
+ vr.consume( *r );
+ r = r.next();
+ }
+ return vr.sorted();
+}
+
+void PackageDetails::loadFileListWorker()
+{
+ entity::Package p = m_package;
+
+ std::string fl, flfile = "/var/lib/dpkg/info/" + p.name() + ".list";
+ std::ifstream ifl( flfile.c_str() );
+
+ int i = 0;
+ kdDebug() << "PackageDetails::loadFileListWorker() entering loop" << endl;
+
+ while ( ifl.is_open() && !ifl.eof() ) {
+ std::string line;
+ getline( ifl, line );
+ if ( line == "/." || line == "" )
+ continue; // nasty evil thing go away
+ m_qtMutex.lock();
+ KURL url( "file:///" );
+ url.addPath( u8( line ) );
+ KFileItem *it = new KFileItem( url, u8( "" ), 0 );
+ it->setName( u8( line ) );
+ m_fileList->insertItem( it );
+ ++i;
+ m_qtMutex.unlock();
+ }
+ kdDebug() << "PackageDetails::loadFileListWorker() leaving loop" << endl;
+ ifl.close();
+}
+
+void PackageDetails::notifyPreRebuild( component::Base * ) {
+ kdDebug() << "PackageDetails::notifyPreRebuild()" << endl;
+ Threads::wait();
+ m_logical->setEnabled( false );
+ m_remove->setEnabled( false );
+ m_logical->disconnect( SIGNAL( clicked() ) );
+ m_remove->disconnect( SIGNAL( clicked() ) );
+ delete m_logicalAct;
+ delete m_removeAct;
+ kdDebug() << "PackageDetails::notifyPreRebuild() done" << endl;
+}
+
+void PackageDetails::loadFileList() {
+ Cache &c = cache::Global::get( m_cache );
+ if ( m_fileListRunning || !c.isOpen() ) {
+ QTimer::singleShot( 100, this, SLOT( loadFileList() ) );
+ return;
+ }
+
+ kdDebug() << "PackageDetails::loadFileList()" << endl;
+ m_fileListRunning = true;
+
+ // the following call is neccessary to invoke buildDefaultType of KMimeType
+ // the first time the method is called it will check for
+ // existence of application/octet-stream and *popup a dialog* if
+ // not found -- we don't want that to happen in a non-gui thread
+ KMimeType::defaultMimeTypePtr();
+ m_thread = asyncCall( std::mem_fun( &PackageDetails::loadFileListWorker ), this );
+
+ m_qtMutex.lock();
+ m_fileList->KFileView::clear();
+ c.progress().OverallProgress( 0, 0, 0, i18n( "Loading filelist..." ) );
+
+ m_qtMutex.unlock();
+ Threads::enqueue( m_thread, &m_qtMutex );
+ Threads::wait();
+ c.progress().Done();
+ m_fileListRunning = false;
+ kdDebug() << "PackageDetails::loadFileList() finished" << endl;
+}
+
+void PackageDetails::setPackage( cache::entity::Package p )
+{
+ kdDebug() << "PackageDetails::setPackage()" << endl;
+ m_package = p.stable();
+ m_name->setText( QString( "<b>" ) +
+ p.name( std::string( "No package" ) ) + "</b>" );
+ m_info->setPackage( p );
+ QString l = u8( p.longDescription(
+ std::string( i18n( "No long description available" ).local8Bit() ) ) );
+ m_description->setText( QString( "<qt>" )
+ + formatLongDescription( l ) + "</qt>" );
+
+ std::string na = u8( i18n( "not available" ) );
+ m_tags->setTags( p.tags( entity::Package::TagSet() ) );
+ m_tags->openToplevel();
+ m_architecture->setText( labelFormat( i18n( "Architecture: " ),
+ p.architecture( na ) ) );
+ m_filename->setText( labelFormat( i18n( "Filename: " ), p.fileName( na ) ) );
+ m_md5->setText( labelFormat( i18n( "MD5: " ), p.md5sum( na ) ) );
+ m_source->setText( labelFormat( i18n( "Source Package: " ), p.source( na ) ) );
+
+ /* IF IT ISN'T KUBUNTU, DON'T SUPPORT CHANGELOGS! */
+#ifdef KUBUNTU
+ // Lets go ahead and stick the changelog in there....
+ try {
+ global_changelog->setParent(p);
+ m_changelog->setText(i18n("Loading..."));
+ connect(dynamic_cast<QObject*>(global_changelog), SIGNAL( changelogReady(QString) ),
+ dynamic_cast<QObject*>(this), SLOT( changelogDisplay(QString) ));
+ connect(dynamic_cast<QObject*>(this), SIGNAL( requestTheChangelog() ),
+ dynamic_cast<QObject*>(global_changelog), SIGNAL( changelogNeeded() ));
+ emit requestTheChangelog();
+ } catch (...) {};
+#endif /* KUBUNTU */
+
+ notifyPostChange( 0 );
+ m_lister->cleanRebuild();
+ loadFileList();
+}
+
+void PackageDetails::changelogDisplay( QString content ) {
+ m_changelog->setText(content);
+}
+
+void PackageDetails::notifyPostChange( cache::component::Base * )
+{
+ kdDebug() << "PackageDetails::notifyPostChange()" << endl;
+ // without the timer to break it, there could be a loop where
+ // we connect the clicked() signal to a slot which would be
+ // invoked right away when we return -> evil
+ QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
+}
+
+void PackageDetails::notifyPostRebuild( cache::component::Base *b )
+{
+ kdDebug() << "PackageDetails::notifyPostRebuild( " << b << " )" << endl;
+ // can't call directly because stable entities are not guaranteed
+ // to be stabilised at this point yet
+ QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
+ QTimer::singleShot( 0, this, SLOT( loadFileList() ) );
+ m_lister->cleanRebuild();
+}
+
+void PackageDetails::updateLogical()
+{
+ Cache &c = cache::Global::get( m_cache );
+ if ( !c.isOpen() ) {
+ QTimer::singleShot( 100, this, SLOT( updateLogical() ) );
+ return;
+ }
+ kdDebug() << "PackageDetails::updateLogical()" << endl;
+ entity::Package p = m_package;
+ kdDebug() << "PackageDetails::updateLogical: p = " << p.name()
+ << " p.component() = " << &p.component() << endl;
+ if ( !p.valid() ) return; // nothing to update
+ EntityActor *a = 0, *b = 0;
+
+ if ( p.canUpgrade() ) {
+ a = new EntityActor( p.upgrade() );
+ } else if ( p.canInstall() ) {
+ a = new EntityActor( p.install() );
+ } else if ( p.canKeep() ) {
+ a = new EntityActor( p.keep() );
+ }
+
+ if ( p.canRemove() ) {
+ b = new EntityActor( p.remove() );
+ }
+
+ if ( a ) {
+ m_logical->setEnabled( true );
+ m_logical->setText( u8( a->actor().prettyName() ) );
+ connect( m_logical, SIGNAL( clicked() ),
+ a, SLOT( destructiveAct() ) );
+ } else {
+ m_logical->setText( i18n( "Install" ) );
+ m_logical->setEnabled( false );
+ }
+
+ if ( b ) {
+ m_remove->setEnabled( true );
+ m_remove->setText( u8( b->actor().prettyName() ) );
+ connect( m_remove, SIGNAL( clicked() ),
+ b, SLOT( destructiveAct() ) );
+ } else {
+ m_remove->setText( i18n( "Remove" ) );
+ m_remove->setEnabled( false );
+ }
+
+ m_logicalAct = a;
+ m_removeAct = b;
+ // std::copy( r, r.last(), vr );
+
+ // r.consume( utils::upcastRange< entity::Entity >( p.depends() ) );
+}
+
+void PackageDetails::setHasForward( bool e ) {
+ m_toolbar->setItemEnabled( BForward, e );
+ // m_forward->setEnabled( e );
+}
+
+void PackageDetails::setHasBack( bool e ) {
+ m_toolbar->setItemEnabled( BBack, e );
+ // m_back->setEnabled( e );
+}
diff --git a/adept/adept/packagedetails.h b/adept/adept/packagedetails.h
new file mode 100644
index 0000000..6d15185
--- /dev/null
+++ b/adept/adept/packagedetails.h
@@ -0,0 +1,58 @@
+/* -*- C++ -*- adept/packagedetails.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <apt-front/cache/entity/package.h>
+#include <adept/packagedetailsui.h>
+#include <adept/lister.h>
+#include <adept/changelog.h>
+
+#include <qmutex.h>
+#include <qguardedptr.h>
+
+#ifndef EPT_PACKGEDETAILS_H
+#define EPT_PACKGEDETAILS_H
+
+class KToolBarButton;
+class QThread;
+
+namespace adept {
+
+using namespace aptFront;
+
+class PackageDetails : public PackageDetailsUi, public Lister::RangeProvider,
+ public cache::Observer
+{
+ Q_OBJECT
+public:
+ enum ButtonID { BForward, BBack, BShow };
+ PackageDetails( QWidget *p = 0, const char *n = 0 );
+ void setPackage( cache::entity::Package );
+ void setHasForward( bool );
+ void setHasBack( bool );
+ virtual Lister::Range listerRange();
+ void notifyPostChange( cache::component::Base * );
+ void notifyPreRebuild( cache::component::Base * );
+ void notifyPostRebuild( cache::component::Base * );
+signals:
+ void showList();
+ void back();
+ void forward();
+ void detailsRequested( Lister::Entity );
+ void requestTheChangelog();
+protected slots:
+ void loadFileList();
+ void updateLogical();
+ void changelogDisplay(QString content);
+protected:
+ void loadFileListWorker();
+ cache::entity::StablePackage m_package;
+ QMutex m_qtMutex;
+ QThread *m_thread;
+ QGuardedPtr< EntityActor > m_logicalAct, m_removeAct;
+ int m_fileListRunning;
+
+};
+
+}
+
+#endif
diff --git a/adept/adept/packagedetailsui.ui b/adept/adept/packagedetailsui.ui
new file mode 100644
index 0000000..06e436a
--- /dev/null
+++ b/adept/adept/packagedetailsui.ui
@@ -0,0 +1,506 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>PackageDetailsUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>PackageDetailsUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>705</width>
+ <height>529</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="KToolBar">
+ <property name="name">
+ <cstring>m_toolbar</cstring>
+ </property>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>8</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>(title)</string>
+ </property>
+ </widget>
+ <widget class="adept::PackageInfo" row="1" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>m_info</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>8</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>75</height>
+ </size>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="3" column="2">
+ <property name="name">
+ <cstring>m_remove</cstring>
+ </property>
+ <property name="text">
+ <string>(remove)</string>
+ </property>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="3" column="1">
+ <property name="name">
+ <cstring>m_logical</cstring>
+ </property>
+ <property name="text">
+ <string>(logical)</string>
+ </property>
+ </widget>
+ <spacer row="3" column="3">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QTextBrowser" row="0" column="4" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>28</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="resizePolicy">
+ <enum>AutoOneFit</enum>
+ </property>
+ <property name="vScrollBarMode">
+ <enum>Auto</enum>
+ </property>
+ <property name="hScrollBarMode">
+ <enum>AlwaysOff</enum>
+ </property>
+ <property name="text">
+ <string>description...</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>16</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Package Relationships</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::Lister" row="0" column="0">
+ <property name="name">
+ <cstring>m_lister</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>120</height>
+ </size>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Installed Files</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KFileDetailView" row="0" column="0">
+ <property name="name">
+ <cstring>m_fileList</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Additional Information</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="adept::TagChooser">
+ <property name="name">
+ <cstring>m_tags</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_source</cstring>
+ </property>
+ <property name="text">
+ <string>source</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_architecture</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>architecture</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_filename</cstring>
+ </property>
+ <property name="text">
+ <string>file</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_md5</cstring>
+ </property>
+ <property name="text">
+ <string>md5</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>61</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>changelog_tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Developer Changelog</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QTextBrowser" row="0" column="0">
+ <property name="name">
+ <cstring>m_changelog</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="resizePolicy">
+ <enum>AutoOneFit</enum>
+ </property>
+ <property name="vScrollBarMode">
+ <enum>Auto</enum>
+ </property>
+ <property name="hScrollBarMode">
+ <enum>AlwaysOff</enum>
+ </property>
+ <property name="text">
+ <string>description...</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::TagChooser</class>
+ <header location="global">adept/tagchooser.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>adept::PackageInfo</class>
+ <header location="global">adept/packageinfo.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>adept::Lister</class>
+ <header location="global">adept/lister.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>KToolBar</class>
+ <header location="global">ktoolbar.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>1</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>KFileDetailView</class>
+ <header location="global">kfiledetailview.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>ktoolbar.h</includehint>
+ <includehint>adept/packageinfo.h</includehint>
+ <includehint>adept/lister.h</includehint>
+ <includehint>kfiledetailview.h</includehint>
+ <includehint>adept/tagchooser.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/packageinfo.cpp b/adept/adept/packageinfo.cpp
new file mode 100644
index 0000000..dac788b
--- /dev/null
+++ b/adept/adept/packageinfo.cpp
@@ -0,0 +1,181 @@
+/** -*- C++ -*-
+ @file adept/packageinfo.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qcolor.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <adept/packageinfo.h>
+#include <adept/utils.h>
+
+using namespace adept;
+using namespace cache;
+
+PackageInfo::PackageInfo( QWidget *p, const char *n )
+ : PackageInfoUi( p, n ), m_specificVersion( false )
+{
+ observeComponent< component::State >();
+}
+
+void PackageInfo::adjustFontSize( int s ) {
+ adept::adjustFontSize( m_status, s );
+ adept::adjustFontSize( m_change, s );
+ adept::adjustFontSize( m_section, s );
+ adept::adjustFontSize( m_installedSize, s );
+ adept::adjustFontSize( m_maintainer, s );
+ adept::adjustFontSize( m_candidateVer, s );
+ adept::adjustFontSize( m_installedVer, s );
+}
+
+void PackageInfo::hideStatus() {
+ m_status->hide();
+ m_change->hide();
+}
+
+namespace adept {
+
+QColor statusColor( entity::Package p )
+{
+ if ( !p.valid() )
+ return Qt::black;
+
+ QColor c = Qt::blue;
+ if (p.isInstalled())
+ c = Qt::darkGreen;
+ if (p.isUpgradable())
+ c = Qt::darkYellow;
+ if (p.isBroken())
+ c = Qt::red;
+ return c;
+}
+
+QColor actionColor( entity::Package p )
+{
+ if ( !p.valid() )
+ return Qt::black;
+
+ QColor c = Qt::blue;
+ if (p.markedNewInstall())
+ c = Qt::darkGreen;
+ if (p.markedUpgrade())
+ c = Qt::darkYellow;
+ if (p.markedReInstall())
+ c = Qt::darkYellow;
+ if (p.markedRemove())
+ c = Qt::darkRed;
+ if (p.markedPurge())
+ c = Qt::red;
+ if (p.willBreak())
+ c = Qt::red;
+ return c;
+}
+
+/* QString hexColor( QColor c )
+{
+ QString r( "#%1%2%3" );
+ return r.arg( c.red(), -2, 16 ).arg( c.green(), -2, 16 ).arg( c.blue(), -2, 16 );
+ } */
+
+QString colorify( QColor c, QString s )
+{
+ return QString( "<font color=\"" ) + c.name()
+ + "\">" + s + "</font>";
+}
+
+QString formatLongDescription( QString l )
+{
+ QRegExp rx( u8( "^(.*)\n" ) );
+ rx.setMinimal( true );
+ l.replace( rx, u8( "\\1</p><p>" ) );
+ rx = QRegExp( u8( "\\n[ ]*\\.\\n" ) );
+ l.replace( rx, u8( "</p><p>" ) );
+ rx = QRegExp( u8( "\n " ) );
+ l.replace( rx, u8( " " ) );
+ rx = QRegExp( u8( "\n - (.*)(\n|$)" ) );
+ rx.setMinimal( true );
+ l.replace( rx, u8( "\n<li>\\1</li>\n" ) );
+ l.replace( rx, u8( "\n<li>\\1</li>\n" ) );
+ return QString( "<p>" ) + l + u8( "</p>" );
+}
+
+void PackageInfo::setPackage( entity::Package p )
+{
+ kdDebug() << "PackageInfo::setPackage()" << endl;
+ // ho hum, probably XXX fix libapt-front?
+ setVersion( p.valid() ? p.anyVersion() : entity::Version(), false );
+}
+
+void PackageInfo::setVersion( entity::Version v, bool specific )
+{
+ m_specificVersion = specific;
+ m_version = v.stable();
+ if ( !m_version.valid() ) return;
+ kdDebug() << "PackageInfo::setVersion() (valid)" << endl;
+ m_section->setText(
+ labelFormat( i18n( "Section:" ), u8( v.section( u8( i18n( "Unknown" ) ) ) ) ) );
+ m_maintainer->setText(
+ labelFormat( i18n( "Maintainer:" ), u8( v.maintainer( u8( i18n( "Unknown" ) ) ) ),
+ false ) );
+
+ notifyPostChange( 0 );
+}
+
+void PackageInfo::notifyPostRebuild( component::Base *b ) {
+ return notifyPostChange( b );
+}
+
+void PackageInfo::notifyPostChange( component::Base * )
+{
+ if ( !m_version.valid() ) return;
+ entity::Version v = m_version;
+ entity::Package p = v.package();
+ QString cv = i18n( "n/a" ), iv = i18n( "n/a" ), is = i18n( "n/a" ), status, action;
+
+ if (p.valid()) {
+ entity::Version _cv = p.candidateVersion();
+ entity::Version _iv = p.installedVersion();
+
+ if (_cv.valid()) {
+ cv = u8( _cv.versionString() );
+ is = u8( _cv.installedSizeString() );
+ }
+
+ if (_iv.valid()) {
+ iv = _iv.versionString();
+ }
+ }
+
+ std::string unk = u8( i18n( "unknown" ) );
+ /* m_status->setText( i18n( "<nobr>Currently " ) + colorify(
+ statusColor( p ),
+ u8( p.statusString( unk ) ) )
+ + i18n( ", " ) + colorify(
+ actionColor( p ),
+ u8( p.actionString( unk ) ) ) + i18n( "
+ requested</nobr>" ) ); */
+ m_status->setText(
+ labelFormat( i18n( "Status:" ), colorify(
+ statusColor( p ),
+ u8( p.statusString( u8( i18n( "Unknown" ) ) ) ) ) ) );
+ m_change->setText(
+ labelFormat( i18n( "Requested change:" ), colorify(
+ actionColor( p ),
+ u8( p.actionString( u8( i18n( "Unknown" ) ) )
+ ) ) ) );
+
+ m_candidateVer->setText(
+ m_specificVersion ?
+ labelFormat( i18n( "Version:" ),
+ v.versionString() + "(" + i18n( "candidate" ) + " " + cv + ")" )
+ : labelFormat( i18n( "Candidate Version:" ), cv ) );
+ m_installedVer->setText(
+ labelFormat( i18n( "Installed Version:" ), iv ) );
+ m_installedSize->setText(
+ labelFormat( i18n( "Installed Size:" ), is ) );
+}
+
+}
diff --git a/adept/adept/packageinfo.h b/adept/adept/packageinfo.h
new file mode 100644
index 0000000..1a83c0d
--- /dev/null
+++ b/adept/adept/packageinfo.h
@@ -0,0 +1,49 @@
+/* -*- C++ -*- adept/packageinfo.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/cache.h>
+#include <adept/packageinfoui.h>
+
+#ifndef EPT_PACKAGEINFO_H
+#define EPT_PACKAGEINFO_H
+
+namespace adept {
+
+using namespace aptFront;
+
+class PackageInfo : public PackageInfoUi, public cache::Observer
+{
+ Q_OBJECT
+public:
+ PackageInfo( QWidget *p, const char *n = 0 );
+public slots:
+ void setVersion( cache::entity::Version v, bool = true );
+ void setPackage( cache::entity::Package v );
+ void adjustFontSize( int );
+public:
+ void notifyPostChange( cache::component::Base * );
+ void notifyPostRebuild( cache::component::Base * );
+ void hideStatus();
+protected:
+ cache::entity::StableVersion m_version;
+ bool m_specificVersion;
+};
+
+inline QString labelFormat( const QString &what,
+ const QString &txt, bool nobr = true )
+{
+ QString ret = "<b><nobr>" + what + "</nobr></b>&nbsp;" + (nobr ? "<nobr>" : "")
+ + txt + (nobr ? "</nobr>" : "");
+ return ret;
+}
+
+QColor actionColor( cache::entity::Package p );
+QColor statusColor( cache::entity::Package p );
+
+QString formatLongDescription( QString in );
+QString colorify( QColor c, QString s );
+
+}
+
+#endif
diff --git a/adept/adept/packageinfoui.ui b/adept/adept/packageinfoui.ui
new file mode 100644
index 0000000..d7d5dc5
--- /dev/null
+++ b/adept/adept/packageinfoui.ui
@@ -0,0 +1,180 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>PackageInfoUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>details</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>253</width>
+ <height>128</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form2</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>1</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>m_indent</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>16</width>
+ <height>5</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16</width>
+ <height>5</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="1">
+ <property name="name">
+ <cstring>m_maintainer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>maintainer</string>
+ </property>
+ <property name="alignment">
+ <set>AlignBottom</set>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="1">
+ <property name="name">
+ <cstring>m_candidateVer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>candidate version</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="6" column="1">
+ <property name="name">
+ <cstring>m_installedVer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>installed version</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>m_section</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>section</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="1">
+ <property name="name">
+ <cstring>m_installedSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>installed size</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>m_status</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>status</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>m_change</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>change</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/adept/progress.cpp b/adept/adept/progress.cpp
new file mode 100644
index 0000000..60a3bd3
--- /dev/null
+++ b/adept/adept/progress.cpp
@@ -0,0 +1,58 @@
+#include <kapplication.h>
+#include <qcursor.h>
+#include <kdebug.h>
+#include <adept/progress.h>
+#include <adept/utils.h>
+
+using namespace adept;
+
+Progress::Progress()
+ : m_pbar( 0 ), m_sbar( 0 ), m_busy( false )
+{
+}
+
+void Progress::Update ()
+{
+ if (!m_sbar)
+ return;
+ if (!m_pbar) {
+ if (Percent) {
+ m_pbar = new KProgress( m_sbar );
+ m_pbar->setMinimumWidth( 80 );
+ m_pbar->setMaximumWidth( 120 );
+ m_pbar->setTextEnabled( false );
+ m_pbar->show();
+ m_sbar->addWidget( m_pbar, 0, true );
+ m_pbar->setTotalSteps( 100 );
+ }
+ MajorChange = true;
+ }
+ if (MajorChange) {
+ if ( !m_busy ) {
+ QApplication::setOverrideCursor( QCursor( Qt::BusyCursor ) );
+ m_busy = true;
+ }
+ m_sbar->message( u8( Op + "..." ) );
+ }
+ if (CheckChange (0.05) == false)
+ return;
+ // kdDebug() << "Progress::Update()" << endl;
+ if (m_pbar)
+ m_pbar->setProgress( Percent );
+ kapp->processEvents();
+}
+
+void Progress::Done ()
+{
+ kdDebug() << "Progress::Done()" << endl;
+
+ QApplication::restoreOverrideCursor();
+ m_busy = false;
+
+ if (m_sbar)
+ m_sbar->clear();
+ delete m_pbar;
+ m_pbar = 0;
+}
+
+Progress::~Progress() {}
diff --git a/adept/adept/progress.h b/adept/adept/progress.h
new file mode 100644
index 0000000..aef3d92
--- /dev/null
+++ b/adept/adept/progress.h
@@ -0,0 +1,30 @@
+/** -*- C++ -*-
+ @file adept/progress.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <kprogress.h>
+#include <kstatusbar.h>
+#include <apt-pkg/progress.h>
+
+#ifndef EPT_PROGRESS_H
+#define EPT_PROGRESS_H
+
+namespace adept {
+
+class Progress : public OpProgress {
+public:
+ Progress();
+ virtual ~Progress();
+ virtual void Update();
+ virtual void Done();
+ void setStatusBar( KStatusBar *b ) { m_sbar = b; }
+protected:
+ KProgress *m_pbar;
+ KStatusBar *m_sbar;
+ bool m_busy;
+};
+
+}
+
+#endif
diff --git a/adept/adept/quickfilter.cpp b/adept/adept/quickfilter.cpp
new file mode 100644
index 0000000..2cb0577
--- /dev/null
+++ b/adept/adept/quickfilter.cpp
@@ -0,0 +1,79 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <qobjectlist.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <klineedit.h>
+#include <qcheckbox.h>
+
+#include "quickfilter.h"
+
+using namespace aptFront;
+using namespace adept;
+
+QuickFilterWidget::QuickFilterWidget( QWidget *parent, const char *name )
+ : QuickFilterUi( parent, name )
+{
+ setFocusProxy( m_match );
+ connect( m_match, SIGNAL( textChanged( const QString & ) ),
+ this, SLOT( textChanged( const QString & ) ) );
+ /* connect( m_reset, SIGNAL( clicked() ),
+ this, SLOT( reset() ) ); */
+ connect( m_match, SIGNAL( returnPressed() ),
+ this, SLOT( widgetsChanged() ) );
+ connect( &timer, SIGNAL( timeout() ),
+ this, SLOT( widgetsChanged() ) );
+
+ QObjectList *chld = queryList( "QCheckBox" );
+ QObjectListIt it( *chld );
+ while( it.current() != 0 ) {
+ connect( it.current(), SIGNAL( toggled( bool ) ),
+ this, SLOT( widgetsChanged() ) );
+ ++it;
+ }
+}
+
+void QuickFilterWidget::mouseReleaseEvent( QMouseEvent *e ) {
+ m_match->setFocus();
+ QuickFilterUi::mouseReleaseEvent( e );
+}
+
+void QuickFilterWidget::textChanged( const QString & )
+{
+ kdDebug() << "QuickFilterWidget::textChanged" << endl;
+ timer.start( 1000, true );
+}
+
+QuickFilterWidget::Predicate QuickFilterWidget::predicate()
+{
+ typedef QuickFilter< entity::Package > F;
+ F f; int w = 0;
+ if ( m_name->isChecked() ) w |= F::Name;
+ if ( m_description->isChecked() ) w |= F::Description;
+ if ( m_maintainer->isChecked() ) w |= F::Maintainer;
+
+ f.setMatch( u8( m_match->text() ) );
+ f.setWhat( w );
+
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void blockedSet( QCheckBox *b, bool v ) {
+ b->blockSignals( true );
+ b->setChecked( v );
+ b->blockSignals( false );
+}
+
+void QuickFilterWidget::predicateChanged() {
+ typedef QuickFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ m_match->blockSignals( true );
+ m_match->setText( f.match() );
+ m_match->blockSignals( false );
+ int w = f.what();
+
+ blockedSet( m_name, w & F::Name );
+ blockedSet( m_description, w & F::Description );
+ blockedSet( m_maintainer, w & F::Maintainer );
+}
+
diff --git a/adept/adept/quickfilter.h b/adept/adept/quickfilter.h
new file mode 100644
index 0000000..788c9da
--- /dev/null
+++ b/adept/adept/quickfilter.h
@@ -0,0 +1,119 @@
+/** -*- C++ -*-
+ @file adept/quickfilter.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <qtimer.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/predicate/factory.h>
+#include <adept/quickfilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+#include <adept/utils.h>
+
+#ifndef EPT_QUICKFILTER_H
+#define EPT_QUICKFILTER_H
+
+class KLineEdit;
+
+namespace adept {
+
+template< typename T >
+struct QuickFilter : predicate::Implementation< T, QuickFilter< T > >,
+ InterfacingPredicate
+{
+ enum Type { Regex, Substring, Exact };
+ enum What { Name = 0x1, Description = 0x2, Maintainer = 0x4 };
+
+ QuickFilter()
+ : m_type( Substring ), m_match( "" ), m_what( Name | Description ) {
+ setupPredicate();
+ }
+
+ void setupPredicate() {
+ predicate::ArgumentList l;
+ l.push_back( m_match );
+ predicate::Predicate< T > a = not predicate::True< T >();
+ if ( m_what & Name ) a = a or predicate::Factory< T >::name( m_match );
+ if ( m_what & Description )
+ a = a or predicate::Factory< T >::description( m_match );
+ if ( m_what & Maintainer )
+ a = a or predicate::Factory< T >::maintainer( m_match );
+ m_op = a;
+ /* m_op = predicate::map(
+ predicate::predicate( predicate::Factory< T >::description( "" )
+ or predicate::Factory< T >::name( "" )
+ or predicate::Factory< T
+ >::maintainer( "" ) ), l ); */
+ }
+
+ std::string summary() const {
+ return u8( i18n( "Search: " ) ) + "\"" + m_match + "\"";
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const QuickFilter &o ) const {
+ return o.m_type == m_type && o.m_match == m_match;
+ }
+
+ std::string typeString() const {
+ if (m_type == Regex) return "Regular Expression";
+ if (m_type == Substring) return "Substring";
+ if (m_type == Exact) return "Exact Match";
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ std::string match() const {
+ return m_match;
+ }
+
+ void setMatch( const std::string &s ) {
+ m_match = s;
+ setupPredicate();
+ }
+
+ void setWhat( int w ) {
+ m_what = w;
+ setupPredicate();
+ }
+
+ int what() { return m_what; }
+
+ virtual void reset() {
+ m_match = "";
+ setupPredicate();
+ }
+
+protected:
+ Type m_type;
+ std::string m_match;
+ int m_what;
+ predicate::Predicate< T > m_op;
+};
+
+class QuickFilterWidget : public QuickFilterUi
+{
+ Q_OBJECT
+public:
+ QuickFilterWidget( QWidget *parent, const char *name = 0 );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+protected slots:
+ void textChanged( const QString & );
+protected:
+ void mouseReleaseEvent( QMouseEvent *e );
+ QTimer timer;
+};
+
+}
+
+#endif
diff --git a/adept/adept/quickfilterui.ui b/adept/adept/quickfilterui.ui
new file mode 100644
index 0000000..d45c154
--- /dev/null
+++ b/adept/adept/quickfilterui.ui
@@ -0,0 +1,130 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::QuickFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>QuickFilterUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>805</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>QuickFilterUi</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Search:&amp;nbsp;&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_match</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Match: </string>
+ </property>
+ <property name="textFormat">
+ <enum>AutoText</enum>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="text">
+ <string>package name,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="text">
+ <string>description,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_maintainer</cstring>
+ </property>
+ <property name="text">
+ <string>maintainer.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/adept/sourceseditor.cpp b/adept/adept/sourceseditor.cpp
new file mode 100644
index 0000000..3b04cf6
--- /dev/null
+++ b/adept/adept/sourceseditor.cpp
@@ -0,0 +1,165 @@
+#include <fstream>
+#include <iostream>
+
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qpainter.h>
+
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+
+#include "sourceseditor.h"
+#include <adept/utils.h>
+
+using namespace aptFront;
+using namespace adept;
+
+SourcesEditor::SourcesEditor( std::string f, QWidget *p, const char *n )
+ : SourcesEditorUi( p, n ), m_filename( f )
+{
+ m_list->setSorting( -1 );
+ m_list->setAcceptDrops( true );
+ connect( m_close, SIGNAL( clicked() ),
+ this, SIGNAL( close() ) );
+ connect( m_apply, SIGNAL( clicked() ),
+ this, SLOT( save() ) );
+ connect( m_reset, SIGNAL( clicked() ),
+ this, SLOT( reset() ) );
+
+ connect( m_list, SIGNAL( contextMenuRequested(
+ QListViewItem *, const QPoint &, int) ),
+ this, SLOT( contextMenu( QListViewItem *, const QPoint & ) ) );
+
+ connect( m_newAdd, SIGNAL( clicked() ),
+ this, SLOT( newAdd() ) );
+
+ reset();
+}
+
+void SourcesEditor::newAdd()
+{
+ Sources::Entry e( true, Sources::Entry::Binary );
+ std::string s = m_newLine->text();
+ std::istringstream i( s );
+ i >> e;
+ new EntryItem( e, m_list );
+ m_newLine->setText( u8( "" ) );
+}
+
+void SourcesEditor::contextMenu( QListViewItem *, const QPoint &pt ) {
+ EntryItem *s = dynamic_cast< EntryItem * >( m_list->selectedItem() );
+ if (!s) return;
+ KPopupMenu *m = new KPopupMenu (this);
+ m->insertItem( s->entry().enabled() ? i18n( "Disable" ) : i18n( "Enable" ), 0 );
+ m->insertItem( i18n( "Clone" ), 1 );
+ m->insertItem( i18n( "Remove" ), 2 );
+ connect( m, SIGNAL( activated( int ) ),
+ this, SLOT( contextMenuActivated( int ) ) );
+ m->exec( pt );
+ delete m;
+}
+
+void SourcesEditor::contextMenuActivated( int i ) {
+ EntryItem *s = dynamic_cast< EntryItem * >( m_list->selectedItem() );
+ Sources::Entry e = s->entry();
+ if (i == 0) {
+ e.setEnabled( !e.enabled() );
+ s->setEntry( e );
+ }
+ if (i == 2)
+ delete s;
+ if (i == 1)
+ new EntryItem( e, m_list, s );
+}
+
+void SourcesEditor::reset() {
+ std::ifstream in( m_filename.c_str() );
+ m_sources.clear();
+ in >> m_sources;
+ utils::Range< Sources::Entry > r = m_sources.entries();
+ EntryItem *last = 0;
+ m_list->clear();
+ while( r != r.end() ) {
+ last = last ? new EntryItem( *r, m_list, last ) :
+ new EntryItem( *r, m_list );
+ ++ r;
+ }
+}
+
+void SourcesEditor::save() {
+ m_sources.clear();
+ EntryItem *i = dynamic_cast< EntryItem * >( m_list->firstChild() );
+ while (i) {
+ m_sources.add( i->entry() );
+ i = dynamic_cast< EntryItem * >( i->nextSibling() );
+ }
+ std::ofstream out( m_filename.c_str() );
+ out << m_sources;
+ std::cerr << "--" << m_sources << "--" << std::endl;
+ out.close();
+ reset(); // re-parse
+}
+
+/* void SourcesEditor::toggleSelectionEnabled()
+{
+ EntryItem *s = dynamic_cast< EntryItem * >( m_list->selectedItem() );
+ if (s) {
+ Sources::Entry e = s->entry();
+ e.setEnabled( !e.enabled() );
+ s->setEntry( e );
+ updateActions();
+ }
+ } */
+
+QString EntryItem::text( int c ) const {
+ if (entry().type() == Sources::Entry::Comment) {
+ if (c == 0)
+ if (entry().comment() == "")
+ return u8( "" );
+ else
+ return entry().typeString();
+ if (c == 1)
+ return entry().comment();
+ return u8( "" );
+ }
+
+ if (c == 0) return entry().typeString();
+ if (c == 1) return entry().url();
+ if (c == 2) return entry().distribution();
+ if (c == 3) return entry().components();
+ return u8( "" );
+}
+
+void EntryItem::setText( int c, const QString &_s )
+{
+ kdDebug() << "setText on column " << c << endl;
+ Sources::Entry e = entry();
+ std::string s;
+ s = _s.local8Bit();
+ if (c == 0) e.setTypeString( s );
+ if (c == 1)
+ if (entry().type() == Sources::Entry::Comment)
+ e.setComment( s );
+ else
+ e.setUrl( s );
+ if (c == 2) e.setDistribution( s );
+ if (c == 3) e.setComponents( s );
+ setEntry( e );
+ KListViewItem::setText( c, _s ); // stop qlistview from looping infinitely
+}
+
+void EntryItem::paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ if (!entry().enabled())
+ c = Qt::gray;
+ _cg.setColor( QColorGroup::Text, c );
+ KListViewItem::paintCell( &_p, _cg, column, width, AlignTop );
+ p->drawPixmap( 0, 0, pm );
+}
+
diff --git a/adept/adept/sourceseditor.h b/adept/adept/sourceseditor.h
new file mode 100644
index 0000000..32b474f
--- /dev/null
+++ b/adept/adept/sourceseditor.h
@@ -0,0 +1,63 @@
+/** -*- C++ -*-
+ @file adept/sourceseditor.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-front/sources.h>
+#include <adept/sourceseditorui.h>
+#include <klistview.h>
+
+namespace adept {
+
+using namespace aptFront;
+
+class SourcesEditor : public SourcesEditorUi
+{
+ Q_OBJECT
+public:
+ SourcesEditor( std::string f, QWidget *p = 0, const char *n = 0 );
+public slots:
+ void save();
+ void reset();
+protected slots:
+ void contextMenu( QListViewItem *, const QPoint & );
+ void contextMenuActivated( int );
+ void newAdd();
+signals:
+ void close();
+protected:
+ aptFront::Sources m_sources;
+ std::string m_filename;
+};
+
+class EntryItem : public KListViewItem {
+public:
+ Sources::Entry entry() const {
+ return m_entry;
+ }
+ void setEntry( const Sources::Entry &e ) {
+ m_entry = e;
+ }
+ EntryItem( Sources::Entry e, KListView *v, EntryItem *prev )
+ : KListViewItem( v, prev ), m_entry( e ) {
+ init();
+ }
+ EntryItem( Sources::Entry e, KListView *v )
+ : KListViewItem( v ), m_entry( e ) {
+ init();
+ }
+ void init() {
+ setRenameEnabled( 0, false );
+ setRenameEnabled( 1, true );
+ setRenameEnabled( 2, true );
+ setRenameEnabled( 3, true );
+ }
+ QString text( int c ) const;
+ void setText( int c, const QString &s );
+ virtual void paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment);
+protected:
+ Sources::Entry m_entry;
+};
+
+}
diff --git a/adept/adept/sourceseditorui.ui b/adept/adept/sourceseditorui.ui
new file mode 100644
index 0000000..43397d3
--- /dev/null
+++ b/adept/adept/sourceseditorui.ui
@@ -0,0 +1,173 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::SourcesEditorUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>adept::SourcesEditorUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>683</width>
+ <height>442</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>adept::SourcesEditorUi</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Distribution</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Components</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_list</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ <property name="itemsMovable">
+ <bool>true</bool>
+ </property>
+ <property name="itemsRenameable">
+ <bool>true</bool>
+ </property>
+ <property name="dragEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>New Repository:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_newLine</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Write or paste a normal sources.list line here to add it to your sources</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_newAdd</cstring>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_reset</cstring>
+ </property>
+ <property name="text">
+ <string>Reset</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_apply</cstring>
+ </property>
+ <property name="text">
+ <string>Apply</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_close</cstring>
+ </property>
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>m_newLine</tabstop>
+ <tabstop>m_newAdd</tabstop>
+ <tabstop>m_reset</tabstop>
+ <tabstop>m_apply</tabstop>
+ <tabstop>m_close</tabstop>
+ <tabstop>m_list</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/statefilter.cpp b/adept/adept/statefilter.cpp
new file mode 100644
index 0000000..45ee470
--- /dev/null
+++ b/adept/adept/statefilter.cpp
@@ -0,0 +1,60 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <qcheckbox.h>
+#include <qobjectlist.h>
+#include "statefilter.h"
+
+using namespace aptFront;
+using namespace adept;
+
+StateFilterWidget::StateFilterWidget( QWidget *parent, const char *name )
+ : StateFilterUi( parent, name )
+{
+ QObjectList *chld = queryList( "QCheckBox" );
+ QObjectListIt it( *chld );
+ while( it.current() != 0 ) {
+ connect( it.current(), SIGNAL( toggled( bool ) ),
+ this, SLOT( widgetsChanged() ) );
+ ++it;
+ }
+}
+
+StateFilterWidget::Predicate StateFilterWidget::predicate()
+{
+ typedef StateFilter< entity::Package > F;
+ unsigned mask = 0;
+ if (m_installed->isChecked()) mask |= F::Installed;
+ if (m_notInstalled->isChecked()) mask |= F::NotInstalled;
+ if (m_upgradable->isChecked()) mask |= F::Upgradable;
+ if (m_keep->isChecked()) mask |= F::Keep;
+ if (m_install->isChecked()) mask |= F::Install;
+ if (m_remove->isChecked()) mask |= F::Remove;
+ if (m_upgrade->isChecked()) mask |= F::Upgrade;
+
+ StateFilter< entity::Package > f;
+ f.setMask( mask );
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void blockedSet( QCheckBox *b, bool v ) {
+ b->blockSignals( true );
+ b->setChecked( v );
+ b->blockSignals( false );
+}
+
+void StateFilterWidget::predicateChanged()
+{
+ typedef StateFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ unsigned mask = f.mask();
+ blockedSet( m_installed, mask & F::Installed );
+ blockedSet( m_notInstalled, mask & F::NotInstalled );
+ blockedSet( m_upgradable, mask & F::Upgradable );
+ blockedSet( m_keep, mask & F::Keep );
+ blockedSet( m_install, mask & F::Install );
+ blockedSet( m_upgrade, mask & F::Upgrade );
+ blockedSet( m_remove, mask & F::Remove );
+}
+
diff --git a/adept/adept/statefilter.h b/adept/adept/statefilter.h
new file mode 100644
index 0000000..570edb1
--- /dev/null
+++ b/adept/adept/statefilter.h
@@ -0,0 +1,144 @@
+/** -*- C++ -*-
+ @file adept/filterwidgets.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/statefilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <iostream>
+#include <sstream>
+
+#ifndef EPT_STATEFILTER_H
+#define EPT_STATEFILTER_H
+
+class KLineEdit;
+
+namespace adept {
+
+template< typename T >
+struct StateFilter : predicate::Implementation< T, StateFilter< T > >,
+ InterfacingPredicate
+{
+ enum Mask { Installed = 1 << 0,
+ NotInstalled = 1 << 1,
+ Upgradable = 1 << 2,
+ Install = 1 << 3,
+ Remove = 1 << 4,
+ Keep = 1 << 5,
+ Upgrade = 1 << 6 };
+
+ StateFilter()
+ : m_mask( 0xff ) {
+ setupPredicate();
+ }
+
+ void setupPredicate() {
+ predicate::Predicate< T >
+ p0 = not predicate::True< T >(),
+ p1 = not predicate::True< T >();
+ if (m_mask & Installed)
+ p0 = p0 or (predicate::Factory< T >::member( &T::isInstalled )
+ and not predicate::Factory< T >::member( &T::isUpgradable ) );
+ if (m_mask & NotInstalled)
+ p0 = p0 or not predicate::Factory< T >::member( &T::isInstalled );
+ if (m_mask & Upgradable)
+ p0 = p0 or predicate::Factory< T >::member( &T::isUpgradable );
+
+ if (m_mask & Install)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedNewInstall );
+ if (m_mask & Remove)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedRemove );
+ if (m_mask & Keep)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedKeep );
+ if (m_mask & Upgrade)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedUpgrade );
+
+ m_op = p0 and p1;
+ }
+
+ std::string summary() const {
+ std::ostringstream s;
+ std::vector< std::string > r;
+ s << "State filter: ";
+ if (m_mask & Installed && m_mask & NotInstalled && m_mask & Upgradable)
+ r.push_back( "Any State" );
+ else {
+ if (m_mask & Installed)
+ r.push_back( i18n( "Installed" ) );
+ if (m_mask & NotInstalled)
+ r.push_back( i18n( "Not Installed" ) );
+ if (m_mask & Upgradable)
+ r.push_back( i18n( "Upgradable" ) );
+ }
+ std::copy( r.begin(), r.end(),
+ std::ostream_iterator< std::string >( s, " " ) );
+ s << "; ";
+ r.clear();
+ if (m_mask & Install && m_mask & Remove
+ && m_mask & Keep && m_mask & Upgrade)
+ r.push_back( i18n( "Any Action" ) );
+ else {
+ if (m_mask & Install)
+ r.push_back( i18n( "Install" ) );
+ if (m_mask & Remove)
+ r.push_back( i18n( "Remove" ) );
+ if (m_mask & Keep)
+ r.push_back( i18n( "Keep" ) );
+ if (m_mask & Upgrade)
+ r.push_back( i18n( "Upgrade" ) );
+ }
+ std::copy( r.begin(), r.end(),
+ std::ostream_iterator< std::string >( s, " " ) );
+ return s.str();
+ }
+
+ unsigned mask() const {
+ return m_mask;
+ }
+
+ void setMask( unsigned m ) {
+ m_mask = m;
+ setupPredicate();
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const StateFilter &o ) const {
+ return o.m_op == m_op;
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ virtual void reset() {
+ m_mask = 0xff;
+ setupPredicate();
+ }
+
+protected:
+ unsigned m_mask;
+ predicate::Predicate< T > m_op;
+};
+
+class StateFilterWidget : public StateFilterUi
+{
+ Q_OBJECT
+public:
+ StateFilterWidget( QWidget *parent, const char *name = 0 );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+};
+
+}
+
+#endif
diff --git a/adept/adept/statefilterui.ui b/adept/adept/statefilterui.ui
new file mode 100644
index 0000000..1ef19e0
--- /dev/null
+++ b/adept/adept/statefilterui.ui
@@ -0,0 +1,166 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::StateFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>StateFilterUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>574</width>
+ <height>55</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>StateFilterUi</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="text">
+ <string>Show: </string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_notInstalled</cstring>
+ </property>
+ <property name="text">
+ <string>not installed,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_installed</cstring>
+ </property>
+ <property name="text">
+ <string>installed,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_upgradable</cstring>
+ </property>
+ <property name="text">
+ <string>upgradable packages,</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>195</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_keep</cstring>
+ </property>
+ <property name="text">
+ <string>no changes,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_install</cstring>
+ </property>
+ <property name="text">
+ <string>install,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_remove</cstring>
+ </property>
+ <property name="text">
+ <string>removal,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_upgrade</cstring>
+ </property>
+ <property name="text">
+ <string>upgrade requested.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>195</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>with: </string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="3" margin="11"/>
+</UI>
diff --git a/adept/adept/tagchooser.cpp b/adept/adept/tagchooser.cpp
new file mode 100644
index 0000000..d596133
--- /dev/null
+++ b/adept/adept/tagchooser.cpp
@@ -0,0 +1,147 @@
+#include <klocale.h>
+#include <qdragobject.h>
+
+#include <ept/debtags/vocabulary.h>
+#include <apt-front/cache/component/packagetags.h>
+#include <adept/tagchooser.h>
+#include <adept/taglist.h>
+#include <adept/utils.h>
+#include <wibble/operators.h>
+
+using namespace adept;
+
+FacetItem::FacetItem( TagChooser *t )
+ : KListViewItem( t )
+{
+}
+
+void FacetItem::removeTag( TagItem::Tag t ) {
+ // kdDebug() << "removing tag " << t.fullname() << endl;
+ for ( QListViewItem *n, *i = firstChild(); i != 0; i = n ) {
+ n = i->nextSibling();
+ if ( dynamic_cast< TagItem * >( i )->tag() == t )
+ delete i;
+ }
+}
+
+TagItem::TagItem( FacetItem *p )
+ : KListViewItem( p ), m_toplevel( false )
+{
+}
+
+TagItem::TagItem( TagChooser *l )
+ : KListViewItem( l ), m_toplevel( true )
+{
+}
+
+QString TagItem::text( int c ) const
+{
+ if (c != 0) return u8( "" );
+ return QString( "[" ) + m_tag.name() + "] " + m_tag.shortDescription("");
+}
+
+TagChooser::TagChooser( QWidget *p, const char *n )
+ : KListView( p, n )
+{
+ observeComponent< cache::component::PackageTags >();
+ // addColumn( " ", 20 );
+ setRootIsDecorated( true );
+ addColumn( i18n( "Available Tags" ) );
+ setResizeMode( LastColumn );
+ setDragEnabled( true );
+ setAcceptDrops( true );
+ viewport()->setAcceptDrops( false );
+ // kdDebug() << "TagChooser: tags set" << endl;
+}
+
+void TagChooser::openToplevel() {
+ QListViewItem *i;
+ for ( i = firstChild(); i != 0; i = i->nextSibling() ) {
+ i->setOpen( true );
+ }
+}
+
+QDragObject *TagChooser::dragObject()
+{
+ TagItem *sel = dynamic_cast< TagItem * >( selectedItem() );
+ if (sel)
+ return new QTextDrag( sel->tag().fullname(), this );
+ return 0;
+}
+
+void TagChooser::dragEnterEvent( QDragEnterEvent *e )
+{
+ // hmmmmm :-)
+ kdDebug() << "TagChooser::dragEnterEvent" << endl;
+ e->accept( dynamic_cast< TagList * >( e->source() )
+ && QTextDrag::canDecode( e ) );
+ kdDebug() << dynamic_cast< TagList * >( e->source() )
+ << "; can decode " << QTextDrag::canDecode( e ) << endl;
+}
+
+void TagChooser::dropEvent( QDropEvent* e )
+{
+ using namespace wibble::operators;
+ TagList *tl = dynamic_cast< TagList * >( e->source() );
+ QString tag;
+ QTextDrag::decode( e, tag );
+ tl->setTags( tl->tags() - cache::Global::get().tags().tagByName(
+ static_cast< const char * >( tag.local8Bit() ) ) );
+}
+
+QString FacetItem::text( int column ) const
+{
+ if ( column == 0 )
+ return QString( "[" ) + m_facet.name() + "] " + m_facet.shortDescription( "" );
+ return u8( "" );
+}
+
+static bool drop( TagChooser::Tag t ) {
+ if ( t.facet().name() == "special" )
+ return true;
+ if ( t.name() == "TODO" )
+ return true;
+ return false;
+}
+
+void TagChooser::setTags( Tag::Set s )
+{
+ using namespace wibble::operators;
+ std::set<Tag> remove = m_tags - s;
+ std::set<Tag> add = s - m_tags;
+ m_tags = s;
+ Tag::Set::iterator i;
+
+ for ( i = add.begin(); i != add.end(); ++i ) {
+
+ if ( drop( *i ) )
+ continue;
+
+ FacetItem *fi = m_facets[ i->facet() ];
+ if ( fi == 0 ) {
+ fi = m_facets[ i->facet() ] = new FacetItem( this );
+ fi->setFacet( i->facet() );
+ }
+
+ TagItem *ti = new TagItem( fi );
+ ti->setTag( *i );
+ }
+
+ for ( i = remove.begin(); i != remove.end(); ++i ) {
+
+ if ( drop( *i ) )
+ continue;
+
+ FacetItem *fi = m_facets[ i->facet() ];
+ fi->removeTag( *i );
+ if ( fi->childCount() == 0 ) {
+ m_facets[ i->facet() ] = 0;
+ delete fi;
+ }
+ }
+
+}
+
+void TagChooser::notifyPreRebuild( cache::component::Base *b ) {
+ setTags( Tag::Set() );
+}
diff --git a/adept/adept/tagchooser.h b/adept/adept/tagchooser.h
new file mode 100644
index 0000000..f6c6e2e
--- /dev/null
+++ b/adept/adept/tagchooser.h
@@ -0,0 +1,83 @@
+/* -*- C++ -*- file adept/tagchooser.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <kdebug.h>
+#include <qlayout.h>
+
+#include <apt-front/utils/range.h>
+#include <apt-front/cache/cache.h>
+
+#include <ept/debtags/tag.h>
+
+#include <adept/extendablelist.h>
+
+#ifndef EPT_TAGCHOOSER_H
+#define EPT_TAGCHOOSER_H
+
+namespace adept {
+
+using namespace aptFront;
+
+class FacetItem;
+class FacetExtender;
+class TagChooser;
+
+class TagItem : public KListViewItem {
+public:
+ typedef ept::debtags::Tag Tag;
+ virtual QString text( int ) const;
+ TagItem( TagChooser *t );
+ TagItem( FacetItem *t );
+ void setTag( Tag t ) { m_tag = t; }
+ Tag tag() { return m_tag; }
+protected:
+ bool m_toplevel;
+ Tag m_tag;
+};
+
+class FacetItem : public KListViewItem
+{
+public:
+ typedef ept::debtags::Facet Facet;
+ virtual QString text( int ) const;
+ FacetItem( TagChooser *t );
+ void setFacet( Facet f ) { m_facet = f; }
+ void removeTag( TagItem::Tag );
+protected:
+ Facet m_facet;
+};
+
+class TagChooser : public KListView, public cache::Observer // ExtendableList
+{
+ Q_OBJECT
+public:
+ typedef ept::debtags::Tag Tag;
+ typedef ept::debtags::Facet Facet;
+ TagChooser( QWidget *p = 0, const char *n = 0 );
+ virtual void notifyPreRebuild( cache::component::Base * );
+public slots:
+ virtual void setTags( TagChooser::Tag::Set );
+ void setTitle( QString s ) {
+ setColumnText( 0, s );
+ }
+ void openToplevel();
+
+protected:
+ virtual void dragEnterEvent( QDragEnterEvent *e );
+ virtual void dropEvent( QDropEvent* e );
+ virtual void contentsDragEnterEvent( QDragEnterEvent *e ) {
+ kdDebug() << "TagChooser::contentsDragEnterEvent" << endl;
+ dragEnterEvent( e );
+ }
+ virtual void contentsDropEvent( QDropEvent *e ) {
+ kdDebug() << "TagChooser::contentsDropEvent" << endl;
+ dropEvent( e );
+ }
+ virtual QDragObject *dragObject();
+ Tag::Set m_tags;
+ std::map< Facet, FacetItem * > m_facets;
+};
+
+}
+
+#endif
diff --git a/adept/adept/tagfilter.cpp b/adept/adept/tagfilter.cpp
new file mode 100644
index 0000000..fb17f8c
--- /dev/null
+++ b/adept/adept/tagfilter.cpp
@@ -0,0 +1,67 @@
+/* -*- C++ -*- libapt/tagfilter.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+
+#include <adept/tagfilter.h>
+#include <adept/taglist.h>
+
+using namespace adept;
+
+TagFilterWidget::TagFilterWidget( QWidget *w, const char *n )
+ : TagFilterUi( w, n )
+{
+ m_wanted->setName( i18n( "Tags I Want (drop tags here)" ) );
+ m_unwanted->setName( i18n( "Tags I Do Not Want (drop tags here)" ) );
+
+ connect( m_wanted, SIGNAL( tagsChanged( TagList::Tag::Set ) ),
+ this, SLOT( wantedChanged() ) );
+ connect( m_unwanted, SIGNAL( tagsChanged( TagList::Tag::Set ) ),
+ this, SLOT( unwantedChanged() ) );
+}
+
+TagFilterWidget::Predicate TagFilterWidget::predicate()
+{
+ TagFilter< entity::Package > f;
+ f.setWanted( m_wanted->tags() );
+ f.setUnwanted( m_unwanted->tags() );
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void setTagsBlocking( TagList *l, TagList::Tag::Set s ) {
+ l->blockSignals( true );
+ l->setTags( s );
+ l->blockSignals( false );
+}
+
+void TagFilterWidget::predicateChanged()
+{
+ typedef TagFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ setTagsBlocking( m_wanted, f.wanted() );
+ setTagsBlocking( m_unwanted, f.unwanted() );
+ if ( item() && item()->list() ) {
+ setupColors();
+ item()->list()->delayedUpdateExtenders();
+ }
+}
+
+void TagFilterWidget::wantedChanged()
+{
+ using namespace wibble::operators;
+ setTagsBlocking( m_unwanted, m_unwanted->tags() - m_wanted->tags() );
+ setupColors();
+ widgetsChanged();
+ item()->list()->delayedUpdateExtenders();
+}
+
+void TagFilterWidget::unwantedChanged()
+{
+ using namespace wibble::operators;
+ setTagsBlocking( m_wanted, m_wanted->tags() - m_unwanted->tags() );
+ setupColors();
+ widgetsChanged();
+ item()->list()->delayedUpdateExtenders();
+}
diff --git a/adept/adept/tagfilter.h b/adept/adept/tagfilter.h
new file mode 100644
index 0000000..5ff8e47
--- /dev/null
+++ b/adept/adept/tagfilter.h
@@ -0,0 +1,110 @@
+/* -*- C++ -*- adept/tagfilter.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qpoint.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/quickfilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+#include <adept/taglist.h>
+#include <adept/tagfilterui.h>
+#include <adept/utils.h>
+
+#ifndef EPT_TAGFILTER_H
+#define EPT_TAGFILTER_H
+
+namespace adept {
+
+template< typename T >
+struct TagFilter : predicate::Implementation< T, TagFilter< T > >,
+ InterfacingPredicate, cache::Observer
+{
+ typedef ept::debtags::Tag Tag;
+
+ TagFilter() {
+ setupPredicate();
+ observeComponent< cache::component::PackageTags >();
+ }
+
+ void setupPredicate() {
+ Cache &cache = cache::Global::get(); // FIXME?
+ m_op = predicate::Factory< T >::tagSet( m_wanted );
+ for (Tag::Set::iterator i = m_unwanted.begin(); i != m_unwanted.end(); ++i ) {
+ m_op = m_op and not predicate::Factory< T >::tag( *i );
+ }
+ }
+
+ std::string summary() const {
+ return u8( i18n( "Tag Filter" ) );
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const TagFilter &o ) const {
+ return o.m_wanted == m_wanted && o.m_unwanted == m_unwanted;
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ void setWanted( Tag::Set t ) {
+ m_wanted = t;
+ setupPredicate();
+ }
+
+ void setUnwanted( Tag::Set t ) {
+ m_unwanted = t;
+ setupPredicate();
+ }
+
+ Tag::Set wanted() const { return m_wanted; }
+ Tag::Set unwanted() const { return m_unwanted; }
+
+ void notifyPreRebuild( cache::component::Base * ) {
+ kdDebug() << "TagFilter pre-rebuild" << endl;
+ m_unwanted.clear(); m_wanted.clear();
+ }
+
+ void notifyPostRebuild( cache::component::Base * ) {
+ Cache &c = cache::Global::get( m_cache );
+ setupPredicate();
+ }
+
+ virtual void reset() {
+ m_wanted.clear();
+ m_unwanted.clear();
+ setupPredicate();
+ }
+
+protected:
+ predicate::Predicate< T > m_op;
+ Tag::Set m_wanted;
+ Tag::Set m_unwanted;
+};
+
+class TagFilterWidget : public TagFilterUi
+{
+ Q_OBJECT
+public:
+ TagFilterWidget( QWidget *p, const char *n );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+ void wantedChanged();
+ void unwantedChanged();
+protected:
+ TagList *m_addingTo;
+ std::vector< ept::debtags::Tag > m_tagMenuMap;
+};
+
+}
+
+#endif
diff --git a/adept/adept/tagfilterui.ui b/adept/adept/tagfilterui.ui
new file mode 100644
index 0000000..1f78b8a
--- /dev/null
+++ b/adept/adept/tagfilterui.ui
@@ -0,0 +1,95 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::TagFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>TagFilterUi</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>627</width>
+ <height>130</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <widget class="adept::TagList">
+ <property name="name">
+ <cstring>m_wanted</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>90</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="adept::TagList">
+ <property name="name">
+ <cstring>m_unwanted</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::TagList</class>
+ <header location="global">adept/taglist.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
+ </image>
+</images>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/taglist.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/adept/taglist.cpp b/adept/adept/taglist.cpp
new file mode 100644
index 0000000..c27d74f
--- /dev/null
+++ b/adept/adept/taglist.cpp
@@ -0,0 +1,138 @@
+/* -*- C++ -*- adept/taglist.cpp
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <qlabel.h>
+#include <qtimer.h>
+#include <kdebug.h>
+#include <qdragobject.h>
+#include <qevent.h>
+#include <klocale.h>
+
+#include <apt-front/cache/cache.h>
+#include <ept/debtags/vocabulary.h>
+#include <adept/taglist.h>
+#include <adept/utils.h>
+#include <wibble/operators.h>
+
+using namespace adept;
+
+TagLabel::TagLabel( Tag t, TagList *l, QWidget *p, const char *n )
+ : QHBox( p, n ), m_tag( t ), m_list( l )
+{
+ if ( t == Tag() ) {
+ m_description = new QLabel( QString( " " ) + i18n( "[none]" ), this );
+ } else {
+ m_remove = new QLabel( this );
+ m_remove->setPixmap( SmallIcon( u8( "cancel" ) ) );
+ m_remove->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ m_description = new QLabel( QString( " [" ) + t.fullname( "n/a" ) + "] "
+ + t.shortDescription( "n/a" ), this );
+ }
+}
+
+void TagLabel::mouseReleaseEvent( QMouseEvent *e ) {
+ using namespace wibble::operators;
+ if ( e->button() == Qt::LeftButton &&
+ dynamic_cast< QLabel * >( childAt( e->pos() ) ) == m_remove )
+ m_list->setTags( m_list->tags() - m_tag );
+}
+
+TagList::TagList( QWidget *p, const char *n )
+ : QVBox( p, n )
+{
+ m_name = new QLabel( this );
+ m_tagBox = new QVBox( this );
+ m_tagBox->setFrameShape( QFrame::Panel );
+ m_tagBox->setFrameShadow( QFrame::Sunken );
+ m_updateScheduled = false;
+ setAcceptDrops( true );
+ scheduleUpdateList();
+ m_tagSpacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
+}
+
+void TagList::setTags( Tag::Set t )
+{
+ m_tags = t;
+ scheduleUpdateList();
+ emit tagsChanged( m_tags );
+}
+
+void TagList::addTag( Tag t )
+{
+ using namespace wibble::operators;
+ if ( t == Tag() )
+ return;
+ m_tags |= t;
+ scheduleUpdateList();
+ emit tagsChanged( m_tags );
+}
+
+void TagList::setName( QString n )
+{
+ m_name->setText( n );
+}
+
+void TagList::scheduleUpdateList()
+{
+ if (! m_updateScheduled) {
+ kdDebug() << "TagList: scheduling update" << endl;
+ QTimer::singleShot( 0, this, SLOT( updateList() ) );
+ m_updateScheduled = true;
+ }
+}
+
+void TagList::updateList()
+{
+ kdDebug() << "TagList (" + m_name->text() + "): updating list" << endl;
+ clearList();
+ if ( m_tags.empty() ) {
+ appendLabel( new TagLabel( Tag(), this, m_tagBox ) );
+ } else {
+ for ( Tag::Set::iterator i = m_tags.begin(); i != m_tags.end(); ++i ) {
+ appendLabel( new TagLabel( *i, this, m_tagBox ) );
+ }
+ }
+ m_tagBox->layout()->addItem( m_tagSpacer );
+ update();
+ parentWidget()->adjustSize();
+ m_updateScheduled = false;
+}
+
+void TagList::appendLabel( TagLabel *l )
+{
+ m_list.push_back( l );
+ l->show();
+}
+
+void TagList::mouseMoveEvent( QMouseEvent *e ) {
+ TagLabel *child = dynamic_cast< TagLabel * >( childAt( e->pos() )->parentWidget() );
+ if ( !child )
+ return;
+ QDragObject *d = new QTextDrag( child->tag().fullname( "" ), this );
+ d->dragCopy();
+}
+
+void TagList::dragEnterEvent( QDragEnterEvent *e ) {
+ kdDebug() << "TagList::dragEnterEvent" << endl;
+ e->accept( QTextDrag::canDecode( e ) );
+}
+
+void TagList::dropEvent( QDropEvent* e ) {
+ QString tag;
+ kdDebug() << "TagList: drop event" << endl;
+ QTextDrag::decode( e, tag );
+ try {
+ addTag( aptFront::cache::Global::get().tags().tagByName(
+ static_cast< const char * >( tag.local8Bit() ) ) );
+ } catch (...) {} // not a tag, ignore
+ scheduleUpdateList();
+}
+
+void TagList::clearList()
+{
+ for (List::iterator i = m_list.begin(); i != m_list.end(); ++i ) {
+ delete *i;
+ }
+ m_list.clear();
+ m_tagBox->layout()->removeItem( m_tagSpacer );
+}
diff --git a/adept/adept/taglist.h b/adept/adept/taglist.h
new file mode 100644
index 0000000..3f652a9
--- /dev/null
+++ b/adept/adept/taglist.h
@@ -0,0 +1,72 @@
+/** -*- C++ -*-
+ @file adept/taglist.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <kiconloader.h>
+#include <vector>
+#include <ept/debtags/tag.h>
+
+#ifndef EPT_TAGLIST_H
+#define EPT_TAGLIST_H
+
+class QLabel;
+
+namespace adept {
+
+class TagList;
+
+class TagLabel : public QHBox
+{
+ Q_OBJECT
+public:
+ typedef ept::debtags::Tag Tag;
+ TagLabel( Tag t, TagList *l, QWidget *p = 0, const char *n = 0 );
+ Tag tag() { return m_tag; }
+protected:
+ void mouseReleaseEvent( QMouseEvent *e );
+ Tag m_tag;
+ QLabel *m_remove;
+ QLabel *m_description;
+ TagList *m_list;
+};
+
+class TagList : public QVBox
+{
+ Q_OBJECT
+public:
+ typedef ept::debtags::Tag Tag;
+ TagList( QWidget *p = 0, const char *n = 0 );
+ void setTags( Tag::Set t );
+ void addTag( Tag t );
+ Tag::Set tags() { return m_tags; }
+ void setName( QString n );
+public slots:
+ void scheduleUpdateList();
+ void updateList();
+signals:
+ void tagsChanged( TagList::Tag::Set );
+protected:
+ void mouseMoveEvent( QMouseEvent *e );
+ void dropEvent( QDropEvent * );
+ void dragEnterEvent( QDragEnterEvent * );
+ void appendLabel( TagLabel * );
+ void clearList();
+
+ bool m_updateScheduled;
+ Tag::Set m_tags;
+ QLabel *m_name;
+ QVBox *m_tagBox;
+ QSpacerItem *m_tagSpacer;
+ typedef std::vector< TagLabel * > List;
+ List m_list;
+};
+
+}
+
+#endif
diff --git a/adept/adept/threadutils.cpp b/adept/adept/threadutils.cpp
new file mode 100644
index 0000000..722f75d
--- /dev/null
+++ b/adept/adept/threadutils.cpp
@@ -0,0 +1,44 @@
+/** -*- C++ -*-
+ @file adept/utils.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <map>
+#include <adept/utils.h>
+
+namespace adept {
+
+QMutex Threads::serialize;
+Threads::Queue Threads::threads;
+
+void Threads::wait() {
+ static std::map< QMutex *, int > locked;
+ while ( !threads.empty() ) {
+ QThread *current = threads.front().first;
+ if ( current->finished() ) {
+ delete current;
+ threads.pop_front();
+ continue;
+ }
+ for ( Queue::iterator thr = threads.begin(); thr != threads.end(); ++thr ) {
+ ++locked[ thr->second ];
+ thr->second->lock();
+ }
+ kapp->processEvents();
+ for ( Queue::iterator thr = threads.begin(); thr != threads.end(); ++thr ) {
+ while ( locked[ thr->second ] > 0 ) {
+ thr->second->unlock();
+ --locked[ thr->second ];
+ }
+ }
+ usleep( 50000 );
+ }
+}
+
+void Threads::enqueue( QThread *t, QMutex *m )
+{
+ threads.push_back( std::make_pair( t, m ) );
+ t->start();
+}
+
+}
diff --git a/adept/adept/utils.h b/adept/adept/utils.h
new file mode 100644
index 0000000..6c3a3d3
--- /dev/null
+++ b/adept/adept/utils.h
@@ -0,0 +1,71 @@
+/** -*- C++ -*-
+ @file adept/utils.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qthread.h>
+#include <qstring.h>
+#include <kapplication.h>
+#include <string>
+#include <queue>
+#include <kdebug.h>
+
+#ifndef EPT_UTILS_H
+#define EPT_UTILS_H
+
+namespace adept {
+
+inline QString u8( std::string s ) {
+ return QString::fromUtf8( s.c_str() );
+}
+
+inline std::string u8( QString s ) {
+ return std::string( s.utf8() );
+}
+
+inline QString u8( const char *s ) {
+ return QString::fromUtf8( s );
+}
+
+struct Threads {
+ static QMutex serialize;
+ typedef std::deque< std::pair< QThread *, QMutex * > > Queue;
+ static Queue threads;
+ static void enqueue( QThread *t, QMutex *m );
+ static void wait();
+};
+
+template< typename F, typename P >
+struct AsyncCall : public QThread
+{
+ AsyncCall( F f, P p ) : func( f ), param( p ) {}
+ virtual void run()
+ {
+ // kdDebug() << "Thread waiting for mutex..." << endl;
+ Threads::serialize.lock();
+ // kdDebug() << "starting thread (mutex acquired)" << endl;
+ func( param );
+ // kdDebug() << "finishing thread (releasing mutex)" << endl;
+ Threads::serialize.unlock();
+ }
+ virtual ~AsyncCall() {}
+protected:
+ F func;
+ P param;
+};
+
+
+template< typename F, typename P > AsyncCall< F, P > *asyncCall( F f, P p ) {
+ return new AsyncCall< F, P >( f, p );
+}
+
+inline static void adjustFontSize( QWidget *w, int off ) {
+ QFont f = w->font();
+ f.setPointSize( f.pointSize() + off ); // a bit smaller font...
+ w->setFont( f );
+ w->updateGeometry();
+}
+
+}
+
+#endif
diff --git a/adept/adept/view.cpp b/adept/adept/view.cpp
new file mode 100644
index 0000000..207277c
--- /dev/null
+++ b/adept/adept/view.cpp
@@ -0,0 +1,153 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/quickfilter.h>
+#include <adept/statefilter.h>
+#include <adept/tagfilter.h>
+
+#include <adept/packagedetails.h>
+#include <adept/view.h>
+#include <adept/filtersidebar.h>
+
+using namespace adept;
+
+View::View( QWidget *p, const char *n )
+ : QSplitter( p, n )
+{
+ setOrientation( Qt::Vertical );
+ m_flist = new FilterList( this );
+ m_bottom = new QSplitter( this );
+ m_bottom->setOrientation( Qt::Horizontal );
+ m_lister = new Lister( m_bottom );
+ m_flist->plugLister( m_lister );
+ m_sidebar = new FilterSidebar( m_bottom );
+
+ connect( m_lister, SIGNAL( cardinalityChanged( const Lister::Cardinality & ) ),
+ m_sidebar, SLOT( setCardinality( const Lister::Cardinality & ) ) );
+
+ m_flist->setHiddenPredicate(
+ predicate::adapt< entity::Entity >(
+ predicate::Package::member( &entity::Package::hasVersion ) ) );
+ m_flist->appendPredicate(
+ predicate::adapt< entity::Entity >(
+ StateFilter< entity::Package >() ) );
+ m_flist->appendPredicate(
+ predicate::adapt< entity::Entity >(
+ TagFilter< entity::Package >() ) );
+ m_flist->appendPredicate(
+ predicate::adapt< entity::Entity >(
+ QuickFilter< entity::Package >() ) );
+
+ m_lister->setRangeProvider( this );
+
+ QTimer::singleShot( 0, this, SLOT( delayed() ) );
+}
+
+Lister::Range View::listerRange() {
+ component::Packages &cp = cache::Global::get().packages();
+ return cp.sorted();
+ // return range( cp.packagesBegin(), cp.packagesEnd() );
+}
+
+void View::hideTags() {
+ QValueList< int > szl;
+ szl.append( 0 ); szl.append( 1 );
+ setSizes( szl );
+}
+
+void View::hideFilters() {
+ QValueList< int > szl;
+ szl.append( 1 ); szl.append( 0 );
+ m_bottom->setSizes( szl );
+}
+
+predicate::Predicate< entity::Entity > View::previewPredicate()
+{
+ return predicate::adapt< entity::Entity >(
+ (not predicate::Package::member( &entity::Package::markedKeep ))
+ or predicate::Package::member( &entity::Package::isBroken )
+ or predicate::Package::member( &entity::Package::willBreak ) );
+}
+
+void View::setUpgradeMode()
+{
+ setPreviewMode();
+ filterList()->setHiddenPredicate(
+ previewPredicate() or predicate::adapt< entity::Entity >(
+ predicate::Package::member( &entity::Package::isUpgradable ) ) );
+}
+
+void View::setPreviewMode()
+{
+ filterList()->setHiddenPredicate( previewPredicate() );
+ hideFilters();
+ hideTags();
+}
+
+void View::delayed()
+{
+ // cleanRebuild();
+}
+
+Browser::Browser( QWidget *p, const char *n )
+ : QWidgetStack( p, n ), m_currentValid( false )
+{
+ m_current = entity::Entity();
+ addWidget( m_view = new View( this ) );
+ addWidget( m_details = new PackageDetails( this ) );
+ connect( m_view->lister(), SIGNAL( detailsRequested( Lister::Entity ) ),
+ this, SLOT( show( Lister::Entity ) ) );
+ connect( m_details, SIGNAL( showList() ),
+ this, SLOT( showList() ) );
+ connect( m_details, SIGNAL( back() ),
+ this, SLOT( back() ) );
+ connect( m_details, SIGNAL( forward() ),
+ this, SLOT( forward() ) );
+ connect( m_details, SIGNAL( detailsRequested( Lister::Entity ) ),
+ this, SLOT( show( Lister::Entity ) ) );
+}
+
+void Browser::showList()
+{
+ raiseWidget( m_view );
+}
+
+void Browser::back()
+{
+ m_forward.push_back( m_current );
+ m_current = m_back.back();
+ m_back.pop_back();
+ doShow( m_current );
+}
+
+void Browser::forward()
+{
+ m_back.push_back( m_current );
+ m_current = m_forward.back();
+ m_forward.pop_back();
+ doShow( m_current );
+}
+
+void Browser::doShow( Lister::Entity e )
+{
+ m_details->setHasForward( !m_forward.empty() );
+ m_details->setHasBack( !m_back.empty() );
+ raiseWidget( m_details );
+ m_details->setPackage( downcast< entity::Package >( e ) );
+}
+
+void Browser::show( Lister::Entity e )
+{
+ m_forward.clear();
+ if ( m_currentValid )
+ m_back.push_back( m_current );
+ m_currentValid = true;
+ m_current = e.stable();
+ doShow( e );
+}
+
+/* Kolik existencialistu je potreba k zasroubovani zarovky?
+ Dva. Jeden sroubuje zarovku, a druhy premysli jak zarovka
+ sama o sobe predstavuje jednotlivy zarivy bod v subjektivni
+ realite v podsveti nekonecne absurdity dosahujici neuprimny
+ vesmir nicoty. */
diff --git a/adept/adept/view.h b/adept/adept/view.h
new file mode 100644
index 0000000..ea6c6f5
--- /dev/null
+++ b/adept/adept/view.h
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+
+#include <deque>
+
+#include <qsplitter.h>
+#include <qwidgetstack.h>
+
+#include <adept/lister.h>
+#include <adept/filterlist.h>
+
+#ifndef EPT_VIEW_H
+#define EPT_VIEW_H
+
+class QSplitter;
+
+namespace adept {
+
+class FilterSidebar;
+class PackageDetails;
+
+class View: public QSplitter, public Lister::RangeProvider {
+ Q_OBJECT
+public:
+ View( QWidget *p = 0, const char *n = 0 );
+ FilterList *filterList() { return m_flist; }
+ Lister *lister() { return m_lister; }
+ virtual Lister::Range listerRange();
+public slots:
+ void cleanRebuild() { m_lister->cleanRebuild(); }
+ void hideFilters();
+ void hideTags();
+ void setPreviewMode();
+ void setUpgradeMode();
+protected slots:
+ void delayed();
+protected:
+ predicate::Predicate< entity::Entity > previewPredicate();
+ QSplitter *m_bottom;
+ FilterList *m_flist;
+ Lister *m_lister;
+ FilterSidebar *m_sidebar;
+};
+
+class Browser : public QWidgetStack {
+ Q_OBJECT
+public:
+ Browser( QWidget *p = 0, const char *n = 0 );
+ View *searchView() const { return m_view; }
+public slots:
+ void forward();
+ void back();
+ void show( Lister::Entity e );
+ void showList();
+ void doShow( Lister::Entity e );
+protected:
+ typedef std::deque< Lister::Entity > Deque;
+ Deque m_forward, m_back;
+ entity::Entity m_current;
+ View *m_view;
+ PackageDetails *m_details;
+ bool m_currentValid;
+};
+
+}
+
+#endif
diff --git a/adept/batch/Makefile.am b/adept/batch/Makefile.am
new file mode 100644
index 0000000..a14de1f
--- /dev/null
+++ b/adept/batch/Makefile.am
@@ -0,0 +1,20 @@
+bin_PROGRAMS = adept_batch
+noinst_HEADERS = app.h
+adept_batch_SOURCES = main.cpp app.cpp
+adept_batch_LDADD = ../adept/libadept.la $(LIBAPT_FRONT_LIBS) $(LIBEPT_LIBS) $(LIBTAGCOLL2_LIBS) $(LIBWIBBLE_LIBS) $(LIB_KIO) $(LIBKDE_UI) ../kubuntu_upgrader/libkubuntuupgradewizard.la
+adept_batch_LDFLAGS = -L/usr/lib/debug
+INCLUDES = $(all_includes) $(LIBAPT_FRONT_CFLAGS) $(LIBEPT_CFLAGS) $(LIBTAGCOLL2_CFLAGS) $(LIBWIBBLE_CFLAGS) -I$(srcdir)/.. -I..
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII
+METASOURCES = AUTO
+KDE_ICON = AUTO
+
+rcdir = $(kde_datadir)/adept_batch
+rc_DATA = adept_batchui.rc
+
+#shelldesktopdir = $(kde_appsdir)/System
+#xdg_apps_DATA = adept_batch.desktop
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(EXTRACTRC) `find . -name "*.rc"` >> rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/adept_batch.pot
diff --git a/adept/batch/adept_batchui.rc b/adept/batch/adept_batchui.rc
new file mode 100644
index 0000000..083b9e8
--- /dev/null
+++ b/adept/batch/adept_batchui.rc
@@ -0,0 +1,16 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="6" name="adept-updater">
+ <MenuBar>
+ <Menu name="file" noMerge="1">
+ <text>&amp;Adept</text>
+ <Action name="file_quit" />
+ </Menu>
+ <Menu name="edit" noMerge="1">
+ <text>&amp;Edit</text>
+ <Action name="edit_undo" />
+ <Action name="edit_redo" />
+ </Menu>
+ </MenuBar>
+ <ToolBar name="mainToolBar" noMerge="1">
+ </ToolBar>
+</kpartgui>
diff --git a/adept/batch/adept_updater.desktop b/adept/batch/adept_updater.desktop
new file mode 100644
index 0000000..dedcbab
--- /dev/null
+++ b/adept/batch/adept_updater.desktop
@@ -0,0 +1,70 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Adept Updater
+Name[bg]=Обновяване на Adept
+Name[ca]=Actualitzador Adept
+Name[da]=Adept-opdatering
+Name[el]=Ανανεωτής Adept
+Name[es]=Actualizador experto
+Name[et]=Adepti uuendaja
+Name[fr]=Mise à jour Adept
+Name[ga]=Nuashonróir Adept
+Name[gl]=Actualizador de Adept
+Name[it]=Aggiornamento Adept
+Name[ka]=Adept განმაახლებელი
+Name[lt]=Adept atnaujinimai
+Name[pt]=Actualizador do Adept
+Name[sk]=Adept aktualizácia
+Name[sv]=Adept-uppdaterare
+Name[xx]=xxAdept Updaterxx
+GenericName=System Update Wizard
+GenericName[bg]=Обновяване на Adept
+GenericName[ca]=Assistent d'actualització del sistema
+GenericName[cs]=Průvodce aktualizací systému
+GenericName[da]=Systemopdateringsguide
+GenericName[de]=Systemaktualisierungsassistent
+GenericName[el]=Μάγος ενημέρωσης συστήματος
+GenericName[es]=Asistente de actualización del sistema
+GenericName[et]=Süsteemi uuendamine nõustaja
+GenericName[fr]=Assistant de mise à jour du système
+GenericName[gl]=Asistente de Actualizazón do Sistema
+GenericName[it]=Procedura guidata aggiornamento sistema
+GenericName[ja]=システムアップデートウィザード
+GenericName[ka]=სისტემის განახლების ოსტატი
+GenericName[lt]=Sistemos atnaujinimo vediklis
+GenericName[nl]=Systeem-update-assistent
+GenericName[pt]=Assistente de Actualização do Sistema
+GenericName[sk]=Sprievodca systémovou aktualizáciou
+GenericName[sv]=Systemuppdateringsguide
+GenericName[xx]=xxSystem Update Wizardxx
+Exec=adept_updater %i %m -caption "%c"
+TryExec=adept_updater
+Categories=Qt;KDE;System;
+Icon=adept_updater
+Type=Application
+X-KDE-SubstituteUID=true
+Comment=Update installed software
+Comment[bg]=Обновяване на инсталиран софтуер
+Comment[ca]=Actualitza el programari instal·lat
+Comment[cs]=Aktualizace nainstalovaného softwaru
+Comment[da]=Opdatér installeret programmel
+Comment[de]=Aktualisiert installierte Software
+Comment[el]=Ενημέρωση εγκατεστημένου λογισμικού
+Comment[es]=Actualizar el software instalado
+Comment[et]=Paigaldatud tarkvara uuendamine
+Comment[fr]=Mise à jour des logiciels installés
+Comment[ga]=Nuashonraigh bogearraí suiteáilte
+Comment[gl]=Actualiza o software instalado
+Comment[it]=Aggiorna il software installato
+Comment[ja]=インストール済みのソフトウェアをアップデート
+Comment[ka]=დაყენებული პროგრამების განახლება
+Comment[lt]=Įdiegtų programų atnaujinimas
+Comment[nl]=Geïnstalleerde software bijwerken
+Comment[pt]=Actualiza o 'software' instalado
+Comment[sk]=Aktualizácia inštalovaného softwaru
+Comment[sr]=Ажурира инсталиране програме
+Comment[sr@Latn]=Ažurira instalirane programe
+Comment[sv]=Uppdatera installerad programvara
+Comment[xx]=xxUpdate installed softwarexx
+Terminal=false
+NoDisplay=true
diff --git a/adept/batch/app.cpp b/adept/batch/app.cpp
new file mode 100644
index 0000000..dd99ec1
--- /dev/null
+++ b/adept/batch/app.cpp
@@ -0,0 +1,142 @@
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qsplitter.h>
+#include <qtimer.h>
+#include <qwidgetstack.h>
+
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kaction.h>
+#include <kactionclasses.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kparts/part.h>
+#include <ktrader.h>
+#include <klibloader.h>
+#include <kstatusbar.h>
+
+#include <apt-pkg/packagemanager.h>
+#include <apt-front/manager.h>
+#include <apt-front/init.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/acqprogresswidget.h>
+#include <adept/progress.h>
+#include <adept/utils.h>
+
+#include <iostream>
+
+#include "app.h"
+
+using namespace aptFront;
+using namespace aptFront::cache;
+using namespace adept;
+
+App::App( KCmdLineArgs *args ) {
+ setMainWidget( this );
+ initialize();
+ QString qs_pkgname;
+
+ updating = false;
+ enum { None, Remove, Install } m = None;
+ for(int i = 0; i < args->count(); i++) {
+ QCString a = args->arg( i );
+
+ if (m == None ||
+ cache().packages().packageByName( std::string( a ) ).valid()) {
+ if ( m == Install ) {
+ kdDebug() << "installing " << a << endl;
+ cache().packages().packageByName( std::string( a ) ).markInstall();
+ } else if ( m == Remove ) {
+ kdDebug() << "removing " << a << endl;
+ cache().packages().packageByName( std::string( a ) ).markRemove();
+ }
+
+ if ( m == None && a == "install" ) {
+ m = Install;
+ } if ( m == None && a == "remove" ) {
+ m = Remove;
+ } if ( m == None && a == "update" ) {
+ updating = true;
+ }
+ } else {
+ qs_pkgname = a;
+ kdDebug() << "The package '"<<a<<"' could not be found." << endl;
+ KMessageBox::sorry(
+ this, i18n( "The package '%1' could not be found." ).arg(u8(qs_pkgname)),
+ i18n( "Could not commit changes" ) );
+ exit(1);
+ }
+ }
+
+ if (!updating && m == 0) {
+ exit( 1 );
+ }
+
+ observeComponent< component::State >();
+
+ m_all = new QVBox( this );
+ m_stack = new QWidgetStack( m_all );
+
+ m_stack->addWidget( m_progress = new adept::AcqProgressWidget( m_stack ) );
+ m_stack->addWidget( m_commitProgress = new CommitProgress( m_stack ) );
+
+ connect(this, SIGNAL( imDone() ),
+ this, SLOT( handleDone() ));
+
+ setStandardToolBarMenuEnabled( false );
+ createStandardStatusBarAction();
+ setupGUI( Keys|StatusBar|Save|Create );
+ delete toolBar();
+
+ Application::setStatusBar( statusBar() );
+
+ QTimer::singleShot(
+ 0, this,
+ SLOT( delayed() ) );
+
+ m_stack->raiseWidget( m_progress );
+ setCentralWidget( m_all );
+}
+
+void App::delayed() {
+ statusBar()->clear();
+
+ kdDebug() << "App::delayed starting commit" << endl;
+
+ aptFront::Manager m;
+ m.setProgressCallback( m_progress->callback() );
+ m.setUpdateInterval( 100000 );
+ try {
+ if (updating) {
+ m_stack->raiseWidget( m_progress );
+ m.update();
+ } else {
+ m_stack->raiseWidget( m_progress );
+ m.download();
+ m_stack->raiseWidget( m_commitProgress );
+ m.commit();
+ }
+ emit imDone();
+ } catch ( exception::OperationCancelled ) {
+ emit imDone();
+ } catch ( ... ) {
+ KMessageBox::sorry(
+ this, i18n( "There was an error commiting changes. "
+ "Possibly there was a problem downloading some "
+ "packages or the commit would break packages. " ),
+ i18n( "Could not commit changes" ) );
+ emit imDone();
+ }
+}
+
+void App::handleDone() {
+ kdDebug() << "I'm done here" << endl;
+ close();
+}
+
+#include "app.moc"
diff --git a/adept/batch/app.h b/adept/batch/app.h
new file mode 100644
index 0000000..604a5a2
--- /dev/null
+++ b/adept/batch/app.h
@@ -0,0 +1,54 @@
+/* -*- C++ -*- */
+#ifndef APP_H
+#define APP_H
+
+#include <kmainwindow.h>
+#include <kparts/part.h>
+#include <kactionclasses.h>
+#include <kcmdlineargs.h>
+#include <apt-front/cache/observer.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+#include <adept/view.h>
+#include <adept/commitprogress.h>
+#include <adept/application.h>
+
+#include <adept/acqprogresswidget.h>
+
+class QVBox;
+class QWidgetStack;
+class QSplitter;
+class KAction;
+class KPushButton;
+namespace adept {
+class AcqProgressWidget;
+}
+
+using namespace aptFront;
+using namespace adept;
+
+class App : public KMainWindow, Application {
+ Q_OBJECT
+public:
+ void setupActions();
+ ExtTerminalInterface *terminal();
+ App( KCmdLineArgs *a );
+signals:
+ void imDone();
+protected slots:
+ void delayed();
+ void handleDone();
+protected:
+ friend class WaitForLister;
+
+ QWidgetStack *m_stack;
+ QVBox *m_all;
+
+ // stacked widgets
+ adept::AcqProgressWidget *m_progress;
+ adept::CommitProgress *m_commitProgress;
+
+ bool updating;
+};
+
+#endif
diff --git a/adept/batch/main.cpp b/adept/batch/main.cpp
new file mode 100644
index 0000000..7521f6c
--- /dev/null
+++ b/adept/batch/main.cpp
@@ -0,0 +1,48 @@
+// KDE includes
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kuniqueapplication.h>
+
+#include "app.h"
+
+static KCmdLineOptions options[] =
+{
+ { "+command", I18N_NOOP("Command"), 0 },
+ KCmdLineLastOption
+};
+
+int main(int argc, char *argv[])
+{
+ KLocale::setMainCatalogue("adept");
+
+ QString description = i18n("Adept Batch");
+
+ KAboutData aboutData( "adept_batch",
+ I18N_NOOP("Adept Batch"),
+ "2.1 Cruiser",
+ description.latin1(),
+ KAboutData::License_BSD,
+ I18N_NOOP("(c) 2006 Peter Rockai"),
+ 0,
+ "http://web.mornfall.net/adept.html");
+
+ aboutData.addAuthor ( "Peter Rockai",
+ I18N_NOOP("developer"),
+ "me at mornfall dot net",
+ "http://web.mornfall.net");
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+ KGlobal::locale()->insertCatalogue(QString::fromUtf8("libept"));
+
+ App *ta = new App( args );
+
+ app.setMainWidget( ta );
+ ta->show();
+
+ return app.exec();
+}
diff --git a/adept/configure.in.in b/adept/configure.in.in
new file mode 100644
index 0000000..eac3946
--- /dev/null
+++ b/adept/configure.in.in
@@ -0,0 +1,5 @@
+AC_ARG_ENABLE(adept, [ --enable-adept compile adept],, [DO_NOT_COMPILE="$DO_NOT_COMPILE adept"])
+LIBTAGCOLL2_DEFS
+LIBAPT_FRONT_DEFS
+LIBEPT_DEFS
+LIBWIBBLE_DEFS
diff --git a/adept/deb-build b/adept/deb-build
new file mode 100755
index 0000000..dcd2967
--- /dev/null
+++ b/adept/deb-build
@@ -0,0 +1,21 @@
+#!/bin/sh
+version=`head -1 debian/changelog | sed -r 's/.+\(([^)]+)\).+/\1/'`
+tgt=_dist/adept-$version
+wd="$(pwd)"
+
+dir=`basename $(pwd)`
+cd ..
+
+rm -rf $tgt
+mkdir -p $tgt
+
+cp -a $dir/debian $tgt/
+cp -a $dir $tgt/adept
+cp -a admin $tgt/
+cp configure.in.in Makefile.am.in $tgt/
+(cd $tgt && patch -p1 < $wd/fix-autoconf.patch)
+(cd $tgt && libtoolize --force)
+cp -f /usr/share/aclocal/libtool.m4 $tgt/admin/libtool.m4.in
+export UNSERMAKE=no
+(cd $tgt && make -f admin/Makefile.common cvs)
+(cd $tgt && debuild $@)
diff --git a/adept/icons/Makefile.am b/adept/icons/Makefile.am
new file mode 100644
index 0000000..e5515a8
--- /dev/null
+++ b/adept/icons/Makefile.am
@@ -0,0 +1 @@
+KDE_ICON = AUTO
diff --git a/adept/icons/cr128-action-adept_notifier_warning.png b/adept/icons/cr128-action-adept_notifier_warning.png
new file mode 100644
index 0000000..49b0960
--- /dev/null
+++ b/adept/icons/cr128-action-adept_notifier_warning.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_commit.png b/adept/icons/cr16-action-adept_commit.png
new file mode 100644
index 0000000..5b0f6a6
--- /dev/null
+++ b/adept/icons/cr16-action-adept_commit.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_distupgrade.png b/adept/icons/cr16-action-adept_distupgrade.png
new file mode 100644
index 0000000..3de9a44
--- /dev/null
+++ b/adept/icons/cr16-action-adept_distupgrade.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_install.png b/adept/icons/cr16-action-adept_install.png
new file mode 100644
index 0000000..e948508
--- /dev/null
+++ b/adept/icons/cr16-action-adept_install.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_keep.png b/adept/icons/cr16-action-adept_keep.png
new file mode 100644
index 0000000..3fe8b17
--- /dev/null
+++ b/adept/icons/cr16-action-adept_keep.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_main_indicator.png b/adept/icons/cr16-action-adept_main_indicator.png
new file mode 100644
index 0000000..cc09bc8
--- /dev/null
+++ b/adept/icons/cr16-action-adept_main_indicator.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_notifier_ok.png b/adept/icons/cr16-action-adept_notifier_ok.png
new file mode 100644
index 0000000..08b9c9d
--- /dev/null
+++ b/adept/icons/cr16-action-adept_notifier_ok.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_notifier_warning.png b/adept/icons/cr16-action-adept_notifier_warning.png
new file mode 100644
index 0000000..c3b9428
--- /dev/null
+++ b/adept/icons/cr16-action-adept_notifier_warning.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_preview.png b/adept/icons/cr16-action-adept_preview.png
new file mode 100644
index 0000000..487a3ec
--- /dev/null
+++ b/adept/icons/cr16-action-adept_preview.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_purge.png b/adept/icons/cr16-action-adept_purge.png
new file mode 100644
index 0000000..145aca4
--- /dev/null
+++ b/adept/icons/cr16-action-adept_purge.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_reinstall.png b/adept/icons/cr16-action-adept_reinstall.png
new file mode 100644
index 0000000..3f1c7ae
--- /dev/null
+++ b/adept/icons/cr16-action-adept_reinstall.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_remove.png b/adept/icons/cr16-action-adept_remove.png
new file mode 100644
index 0000000..d555d92
--- /dev/null
+++ b/adept/icons/cr16-action-adept_remove.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_sourceseditor.png b/adept/icons/cr16-action-adept_sourceseditor.png
new file mode 100644
index 0000000..9d47a67
--- /dev/null
+++ b/adept/icons/cr16-action-adept_sourceseditor.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_update.png b/adept/icons/cr16-action-adept_update.png
new file mode 100644
index 0000000..1c026d3
--- /dev/null
+++ b/adept/icons/cr16-action-adept_update.png
Binary files differ
diff --git a/adept/icons/cr16-action-adept_upgrade.png b/adept/icons/cr16-action-adept_upgrade.png
new file mode 100644
index 0000000..184c118
--- /dev/null
+++ b/adept/icons/cr16-action-adept_upgrade.png
Binary files differ
diff --git a/adept/icons/cr16-action-extender_closed.png b/adept/icons/cr16-action-extender_closed.png
new file mode 100644
index 0000000..24a89b5
--- /dev/null
+++ b/adept/icons/cr16-action-extender_closed.png
Binary files differ
diff --git a/adept/icons/cr16-action-extender_opened.png b/adept/icons/cr16-action-extender_opened.png
new file mode 100644
index 0000000..a4f8e50
--- /dev/null
+++ b/adept/icons/cr16-action-extender_opened.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_commit.png b/adept/icons/cr22-action-adept_commit.png
new file mode 100644
index 0000000..2166fdf
--- /dev/null
+++ b/adept/icons/cr22-action-adept_commit.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_distupgrade.png b/adept/icons/cr22-action-adept_distupgrade.png
new file mode 100644
index 0000000..251f3a0
--- /dev/null
+++ b/adept/icons/cr22-action-adept_distupgrade.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_install.png b/adept/icons/cr22-action-adept_install.png
new file mode 100644
index 0000000..e2823ba
--- /dev/null
+++ b/adept/icons/cr22-action-adept_install.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_keep.png b/adept/icons/cr22-action-adept_keep.png
new file mode 100644
index 0000000..f392596
--- /dev/null
+++ b/adept/icons/cr22-action-adept_keep.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_notifier_ok.png b/adept/icons/cr22-action-adept_notifier_ok.png
new file mode 100644
index 0000000..5cf1392
--- /dev/null
+++ b/adept/icons/cr22-action-adept_notifier_ok.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_notifier_warning.png b/adept/icons/cr22-action-adept_notifier_warning.png
new file mode 100644
index 0000000..5d8fb4f
--- /dev/null
+++ b/adept/icons/cr22-action-adept_notifier_warning.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_preview.png b/adept/icons/cr22-action-adept_preview.png
new file mode 100644
index 0000000..6f5792a
--- /dev/null
+++ b/adept/icons/cr22-action-adept_preview.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_purge.png b/adept/icons/cr22-action-adept_purge.png
new file mode 100644
index 0000000..5d1bce8
--- /dev/null
+++ b/adept/icons/cr22-action-adept_purge.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_reinstall.png b/adept/icons/cr22-action-adept_reinstall.png
new file mode 100644
index 0000000..3054f31
--- /dev/null
+++ b/adept/icons/cr22-action-adept_reinstall.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_remove.png b/adept/icons/cr22-action-adept_remove.png
new file mode 100644
index 0000000..bb16f03
--- /dev/null
+++ b/adept/icons/cr22-action-adept_remove.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_sourceseditor.png b/adept/icons/cr22-action-adept_sourceseditor.png
new file mode 100644
index 0000000..ceb2cbf
--- /dev/null
+++ b/adept/icons/cr22-action-adept_sourceseditor.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_update.png b/adept/icons/cr22-action-adept_update.png
new file mode 100644
index 0000000..0d1ae45
--- /dev/null
+++ b/adept/icons/cr22-action-adept_update.png
Binary files differ
diff --git a/adept/icons/cr22-action-adept_upgrade.png b/adept/icons/cr22-action-adept_upgrade.png
new file mode 100644
index 0000000..7475f6a
--- /dev/null
+++ b/adept/icons/cr22-action-adept_upgrade.png
Binary files differ
diff --git a/adept/icons/cr22-action-extender_closed.png b/adept/icons/cr22-action-extender_closed.png
new file mode 100644
index 0000000..95fc568
--- /dev/null
+++ b/adept/icons/cr22-action-extender_closed.png
Binary files differ
diff --git a/adept/icons/cr22-action-extender_opened.png b/adept/icons/cr22-action-extender_opened.png
new file mode 100644
index 0000000..53c2297
--- /dev/null
+++ b/adept/icons/cr22-action-extender_opened.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_commit.png b/adept/icons/cr32-action-adept_commit.png
new file mode 100644
index 0000000..592ce6f
--- /dev/null
+++ b/adept/icons/cr32-action-adept_commit.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_distupgrade.png b/adept/icons/cr32-action-adept_distupgrade.png
new file mode 100644
index 0000000..63e8ebf
--- /dev/null
+++ b/adept/icons/cr32-action-adept_distupgrade.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_install.png b/adept/icons/cr32-action-adept_install.png
new file mode 100644
index 0000000..90fec1d
--- /dev/null
+++ b/adept/icons/cr32-action-adept_install.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_keep.png b/adept/icons/cr32-action-adept_keep.png
new file mode 100644
index 0000000..2568b59
--- /dev/null
+++ b/adept/icons/cr32-action-adept_keep.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_notifier_ok.png b/adept/icons/cr32-action-adept_notifier_ok.png
new file mode 100644
index 0000000..1914a42
--- /dev/null
+++ b/adept/icons/cr32-action-adept_notifier_ok.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_notifier_warning.png b/adept/icons/cr32-action-adept_notifier_warning.png
new file mode 100644
index 0000000..d2db447
--- /dev/null
+++ b/adept/icons/cr32-action-adept_notifier_warning.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_preview.png b/adept/icons/cr32-action-adept_preview.png
new file mode 100644
index 0000000..e92f3ca
--- /dev/null
+++ b/adept/icons/cr32-action-adept_preview.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_purge.png b/adept/icons/cr32-action-adept_purge.png
new file mode 100644
index 0000000..9a6aadb
--- /dev/null
+++ b/adept/icons/cr32-action-adept_purge.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_reinstall.png b/adept/icons/cr32-action-adept_reinstall.png
new file mode 100644
index 0000000..cb734f8
--- /dev/null
+++ b/adept/icons/cr32-action-adept_reinstall.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_remove.png b/adept/icons/cr32-action-adept_remove.png
new file mode 100644
index 0000000..5a6b15a
--- /dev/null
+++ b/adept/icons/cr32-action-adept_remove.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_sourceseditor.png b/adept/icons/cr32-action-adept_sourceseditor.png
new file mode 100644
index 0000000..ff21ea5
--- /dev/null
+++ b/adept/icons/cr32-action-adept_sourceseditor.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_update.png b/adept/icons/cr32-action-adept_update.png
new file mode 100644
index 0000000..4b0e37a
--- /dev/null
+++ b/adept/icons/cr32-action-adept_update.png
Binary files differ
diff --git a/adept/icons/cr32-action-adept_upgrade.png b/adept/icons/cr32-action-adept_upgrade.png
new file mode 100644
index 0000000..899ad4f
--- /dev/null
+++ b/adept/icons/cr32-action-adept_upgrade.png
Binary files differ
diff --git a/adept/icons/cr32-action-extender_closed.png b/adept/icons/cr32-action-extender_closed.png
new file mode 100644
index 0000000..cd1be0c
--- /dev/null
+++ b/adept/icons/cr32-action-extender_closed.png
Binary files differ
diff --git a/adept/icons/cr32-action-extender_opened.png b/adept/icons/cr32-action-extender_opened.png
new file mode 100644
index 0000000..2c9074d
--- /dev/null
+++ b/adept/icons/cr32-action-extender_opened.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_commit.png b/adept/icons/cr48-action-adept_commit.png
new file mode 100644
index 0000000..3b7a690
--- /dev/null
+++ b/adept/icons/cr48-action-adept_commit.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_distupgrade.png b/adept/icons/cr48-action-adept_distupgrade.png
new file mode 100644
index 0000000..fb43a06
--- /dev/null
+++ b/adept/icons/cr48-action-adept_distupgrade.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_install.png b/adept/icons/cr48-action-adept_install.png
new file mode 100644
index 0000000..1b12d6c
--- /dev/null
+++ b/adept/icons/cr48-action-adept_install.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_keep.png b/adept/icons/cr48-action-adept_keep.png
new file mode 100644
index 0000000..753b14f
--- /dev/null
+++ b/adept/icons/cr48-action-adept_keep.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_notifier_ok.png b/adept/icons/cr48-action-adept_notifier_ok.png
new file mode 100644
index 0000000..5707ba9
--- /dev/null
+++ b/adept/icons/cr48-action-adept_notifier_ok.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_notifier_warning.png b/adept/icons/cr48-action-adept_notifier_warning.png
new file mode 100644
index 0000000..5add449
--- /dev/null
+++ b/adept/icons/cr48-action-adept_notifier_warning.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_preview.png b/adept/icons/cr48-action-adept_preview.png
new file mode 100644
index 0000000..3dc1678
--- /dev/null
+++ b/adept/icons/cr48-action-adept_preview.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_purge.png b/adept/icons/cr48-action-adept_purge.png
new file mode 100644
index 0000000..70e8012
--- /dev/null
+++ b/adept/icons/cr48-action-adept_purge.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_reinstall.png b/adept/icons/cr48-action-adept_reinstall.png
new file mode 100644
index 0000000..00cd6ef
--- /dev/null
+++ b/adept/icons/cr48-action-adept_reinstall.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_remove.png b/adept/icons/cr48-action-adept_remove.png
new file mode 100644
index 0000000..984bf23
--- /dev/null
+++ b/adept/icons/cr48-action-adept_remove.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_sourceseditor.png b/adept/icons/cr48-action-adept_sourceseditor.png
new file mode 100644
index 0000000..cab2a62
--- /dev/null
+++ b/adept/icons/cr48-action-adept_sourceseditor.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_update.png b/adept/icons/cr48-action-adept_update.png
new file mode 100644
index 0000000..248f614
--- /dev/null
+++ b/adept/icons/cr48-action-adept_update.png
Binary files differ
diff --git a/adept/icons/cr48-action-adept_upgrade.png b/adept/icons/cr48-action-adept_upgrade.png
new file mode 100644
index 0000000..6af2494
--- /dev/null
+++ b/adept/icons/cr48-action-adept_upgrade.png
Binary files differ
diff --git a/adept/icons/cr48-action-extender_closed.png b/adept/icons/cr48-action-extender_closed.png
new file mode 100644
index 0000000..fbce893
--- /dev/null
+++ b/adept/icons/cr48-action-extender_closed.png
Binary files differ
diff --git a/adept/icons/cr48-action-extender_opened.png b/adept/icons/cr48-action-extender_opened.png
new file mode 100644
index 0000000..ee52113
--- /dev/null
+++ b/adept/icons/cr48-action-extender_opened.png
Binary files differ
diff --git a/adept/icons/cr64-action-adept_notifier_warning.png b/adept/icons/cr64-action-adept_notifier_warning.png
new file mode 100644
index 0000000..d868276
--- /dev/null
+++ b/adept/icons/cr64-action-adept_notifier_warning.png
Binary files differ
diff --git a/adept/icons/crsc-action-adept_notifier_warning.svgz b/adept/icons/crsc-action-adept_notifier_warning.svgz
new file mode 100644
index 0000000..208a4f6
--- /dev/null
+++ b/adept/icons/crsc-action-adept_notifier_warning.svgz
Binary files differ
diff --git a/adept/installer/Makefile.am b/adept/installer/Makefile.am
new file mode 100644
index 0000000..7275f75
--- /dev/null
+++ b/adept/installer/Makefile.am
@@ -0,0 +1,22 @@
+
+bin_PROGRAMS = adept_installer
+noinst_HEADERS = app.h
+adept_installer_SOURCES = main.cpp app.cpp
+adept_installer_LDADD = ../adept/libadept.la -lapt-front $(LIBTAGCOLL2_LIBS) $(LIB_KIO) $(LIBKDE_UI)
+adept_installer_LDFLAGS = -L/usr/lib/debug
+INCLUDES = $(all_includes) $(LIBEPT_CFLAGS) $(LIBTAGCOLL2_CFLAGS) $(LIBAPT_FRONT_CFLAGS) $(LIBWIBBLE_CFLAGS) -I$(srcdir)/.. -I..
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII \
+ -DINSTALLER_DATA=\"/usr/share/app-install\"
+METASOURCES = AUTO
+KDE_ICON = AUTO
+
+rcdir = $(kde_datadir)/adept_installer
+rc_DATA = adept_installerui.rc
+
+#shelldesktopdir = $(kde_appsdir)/System
+xdg_apps_DATA = adept_installer.desktop
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(EXTRACTRC) `find . -name "*.rc"` >> rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/adept_installer.pot
diff --git a/adept/installer/adept_installer.desktop b/adept/installer/adept_installer.desktop
new file mode 100644
index 0000000..4bba24c
--- /dev/null
+++ b/adept/installer/adept_installer.desktop
@@ -0,0 +1,45 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Add/Remove Programs
+Name[bg]=Добавяне/Премахване на програми
+Name[br]=Ouzhpennañ/Lemel programmoù
+Name[ca]=Afegeix/Elimina programes
+Name[cs]=Přidat/odstranit programy
+Name[da]=Tilføj/Fjern programmer
+Name[de]=Programme hinzufügen/entfernen
+Name[el]=Προσθήκη/Αφαίρεση εφαρμογών
+Name[es]=Añadir/eliminar programas
+Name[gl]=Engade/Quita Programas
+Name[it]=Aggiungi/Rimuovi Programmi
+Name[ja]=プログラムの追加と削除
+Name[ka]=პროგრამების დაყენება/წაშლა
+Name[lt]=Pridėti/šalinti programas
+Name[nl]=Programma's toevoegen/verwijderen
+Name[pt]=Adicionar/Remover Programas
+Name[sk]=Pridať/Odstrániť programy
+Name[sv]=Lägg till/Ta bort program
+Exec=/opt/kde3/bin/adept_installer
+Categories=Qt;KDE;Core;
+Icon=adept_installer
+Type=Application
+X-KDE-SubstituteUID=true
+Comment=Adept Installer: install and remove software packages
+Comment[bg]=Инсталатор Adept: инсталиране на нови софтуерни пакети
+Comment[ca]=Instal·lador Adept: instal·la i elimina paquets de programari
+Comment[cs]=Adept Installer: instalace a smazání softwarových balíčků
+Comment[da]=Adept installationsprogram: installér og fjern programmer
+Comment[de]=Adept Installationsprogramm: Softwarepakete installieren und deinstallieren
+Comment[el]=Εφαρμογή ενημέρωσης λογισμικού Adept: Εγκατάσταση και αφαίρεση πακέτων λογισμικού
+Comment[es]=Instalador Adept: instala y elimina paquetes de software
+Comment[fr]=Installeur Adept : Installation et mise à jour de paquetages logiciels
+Comment[ga]=Suiteálaí Adept: suiteáil agus bain bogearraí
+Comment[gl]=Instalador de Adept; instala e borra pacotes de software
+Comment[it]=Installatore Adept: installa e rimuove pacchetti di programmi
+Comment[ja]=Adept Installer: ソフトウェアパッケージのインストールと削除
+Comment[ka]=Adept დამყენებელი: პაკეტების დაყენება და წაშლა
+Comment[lt]=Adept tvarkytuvė: programų paketų diegimas ir šalinimas
+Comment[nl]=Adept Installer: installeer en verwijder softwarepakketten
+Comment[pt]=Instalador Adept: Instalar e remover pacotes de 'software'
+Comment[sk]=Adept Installer: inštaluje a odstraňuje softwarové balíky
+Comment[sv]=Adept installationsprogram: installera och ta bort programvarupaket
+Terminal=false
diff --git a/adept/installer/adept_installerui.rc b/adept/installer/adept_installerui.rc
new file mode 100644
index 0000000..a4eca27
--- /dev/null
+++ b/adept/installer/adept_installerui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="6" name="adept-updater">
+ <MenuBar>
+ <Menu name="file" noMerge="1">
+ <text>&amp;Adept</text>
+ <Action name="file_quit" />
+ </Menu>
+ <Menu name="edit" noMerge="1">
+ <text>&amp;Edit</text>
+ <Action name="edit_undo" />
+ <Action name="edit_redo" />
+ </Menu>
+ <Menu name="view" noMerge="1">
+ <text>&amp;View</text>
+ <Action name="review"/>
+ </Menu>
+ </MenuBar>
+ <ToolBar name="mainToolBar" noMerge="1">
+ </ToolBar>
+</kpartgui>
diff --git a/adept/installer/app.cpp b/adept/installer/app.cpp
new file mode 100644
index 0000000..7c82421
--- /dev/null
+++ b/adept/installer/app.cpp
@@ -0,0 +1,416 @@
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qpopupmenu.h>
+#include <qsplitter.h>
+#include <qtimer.h>
+#include <qwidgetstack.h>
+
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kaction.h>
+#include <kactionclasses.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kparts/part.h>
+#include <ktrader.h>
+#include <klibloader.h>
+#include <kstatusbar.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+#include <kmenubar.h>
+
+#include <apt-pkg/packagemanager.h>
+#include <apt-front/manager.h>
+#include <apt-front/init.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/desktop.h>
+#include <apt-front/cache/component/history.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/acqprogresswidget.h>
+#include <adept/desktoplist.h>
+#include <adept/utils.h>
+
+#include "app.h"
+
+#include <adept/dpkgpm-gui.h> // EVIL
+
+using namespace aptFront;
+using namespace cache;
+using namespace utils;
+using namespace adept;
+
+std::string GroupPolicy::groupForCategories( Range< std::string > r ) {
+ /* std::cerr << "groupForCategories: ";
+ for ( Range< std::string > i = r; i != i.end(); ++i ) {
+ std::cerr << *i << " ";
+ }
+ std::cerr << std::endl; */
+ for ( Range< std::string > i = r; i != i.end(); ++i ) {
+ if ( i->find( "X-KDE-settings" ) != std::string::npos )
+ return "Settings";
+ if ( i->find( "X-KDE-information" ) != std::string::npos )
+ return "Settings";
+ }
+ if ( r.contains( "Development" ) ) return "Development";
+ if ( !r.contains( "Education" ) ) {
+ if ( r.contains( "Astronomy" ) || r.contains( "Biology" )
+ || r.contains( "Chemistry" ) || r.contains( "Geology" )
+ || r.contains( "MedicalSoftware" ) || r.contains( "Physics" )
+ || r.contains( "Math" ) || r.contains( "Science" ) )
+ return "Science";
+ } else {
+ return "Edutainment";
+ }
+ if ( r.contains( "Game" ) ) return "Games";
+ if ( r.contains( "Graphics" ) ) return "Graphics";
+ if ( r.contains( "Network" ) ) return "Internet";
+ if ( r.contains( "AudioVideo" ) ) return "Multimedia";
+ if ( r.contains( "Office" ) ) return "Office";
+ if ( r.contains( "Settings" ) ) return "Settings";
+ if ( r.contains( "System" ) ) return "System";
+ if ( r.contains( "Utility" ) ) {
+ if ( r.contains( "Accessibility" ) )
+ return "Accessibility";
+ return "Utilities";
+ }
+ return "Others";
+}
+
+QString IconPolicy::iconForGroup( QString g ) {
+ if ( g == u8( "Office" ) ) return u8( "package_wordprocessing" );
+ if ( g == u8( "Internet" ) ) return u8( "package_network" );
+ if ( g == u8( "Science" ) ) return u8( "edu_science" );
+ if ( g == u8( "Accessibility" ) ) return u8( "access" );
+ if ( g == u8( "Others" ) ) return u8( "package" );
+ return QString( "package_" ) + g.lower();
+}
+
+void WaitForLister::waiting()
+{
+ kdDebug() << "WaitForLister::waiting()" << endl;
+ /* if (app->m_list->lister()->busy())
+ QTimer::singleShot( 100, this, SLOT( waiting() ) );
+ else */ {
+ QTimer::singleShot( 0, app, slot );
+ deleteLater();
+ }
+}
+
+App::App() {
+
+ m_all = new QVBox( this );
+ m_stack = new QWidgetStack( m_all );
+
+ m_stack->addWidget( m_loading = new QLabel( i18n( "Loading, please wait..." ), m_stack ) );
+ m_loading->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+
+ m_buttons = new QHBox( m_all );
+ m_editSources = new KPushButton( i18n( "Edit Software Sources" ), m_buttons );
+ m_reviewChanges = new KPushButton( i18n( "Review Changes" ), m_buttons );
+ QLabel *space = new QLabel( m_buttons ); // spacing
+ m_next = new KPushButton( i18n( "Next" ), m_buttons );
+ m_quit = new KPushButton( i18n( "Quit" ), m_buttons );
+ m_editSources->setEnabled( false );
+ m_reviewChanges->setEnabled( false );
+ m_next->setEnabled( false );
+ m_quit->setEnabled( false );
+
+ m_buttons->setSpacing( 2 );
+ m_buttons->setMargin( 2 );
+ QSizePolicy buttons( QSizePolicy::Preferred, QSizePolicy::Fixed, false );
+ m_buttons->setSizePolicy( buttons );
+ m_next->setSizePolicy( buttons );
+ m_quit->setSizePolicy( buttons );
+ space->setSizePolicy( QSizePolicy(
+ QSizePolicy::Expanding,
+ QSizePolicy::Fixed, false ) );
+
+ setStandardToolBarMenuEnabled( false );
+ createStandardStatusBarAction();
+ setupActions();
+ setupGUI( Keys|StatusBar|Save|Create );
+ delete toolBar();
+ menuBar()->hide();
+
+ Application::setStatusBar( statusBar() );
+
+ QTimer::singleShot(
+ 0, this,
+ SLOT( delayed() ) );
+
+ setCentralWidget( m_all );
+ setMinimumSize( 400, 300 );
+}
+
+void App::delayed() {
+
+ initialize();
+ cache().addComponent( new component::Desktop() );
+ KGlobal::dirs()->addResourceDir(
+ "desktopicon",
+ u8( INSTALLER_DATA "/icons/" ) );
+
+ cache().component< component::Desktop >().setPolicy( new GroupPolicy() );
+ cache().component< component::Desktop >().loadDirectory(
+ INSTALLER_DATA "/desktop/" );
+
+ QFile file(QString("/usr/bin/software-properties-kde"));
+ if (file.exists()) {
+ connect( m_editSources, SIGNAL( clicked() ), this, SLOT( editSources() ) );
+ m_editSources->setEnabled( true );
+ }
+
+ connect( m_reviewChanges, SIGNAL( clicked() ), this, SLOT( togglePreview() ) );
+ m_reviewChanges->setEnabled( true );
+
+ connect( m_quit, SIGNAL( clicked() ), this, SLOT( close() ) );
+ m_quit->setEnabled( true );
+
+ m_stack->addWidget( m_view = new InstallerView( m_stack ) );
+ connect( m_view->selector(), SIGNAL( request( cache::entity::Package,
+ cache::component::State::Action ) ),
+ this, SLOT( request( cache::entity::Package,
+ cache::component::State::Action ) ) );
+ m_stack->addWidget( m_preview = new Browser( m_stack ) );
+ m_preview->searchView()->setPreviewMode();
+ m_view->selector()->setPolicy( new IconPolicy() );
+
+ m_stack->addWidget(
+ m_bye = new QLabel( i18n( "Installation Complete!" ), m_stack ) );
+ m_bye->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+
+ m_stack->addWidget( m_progress = new adept::AcqProgressWidget( m_stack ) );
+ m_stack->addWidget( m_commitProgress = new CommitProgress( m_stack ) );
+
+ m_stack->raiseWidget( m_view );
+
+ statusBar()->clear();
+ m_view->rebuild();
+ start();
+}
+
+bool App::confirmRequest( entity::Package p, component::State::Action a )
+{
+ component::Desktop &d = cache::Global::get().component< component::Desktop >();
+ typedef predicate::AttributeAdaptor< entity::Desktop,
+ predicate::match::Exact< entity::Package > > Adaptor;
+
+ QString t;
+
+ if ( a == component::State::ARemove )
+ t = i18n( "You selected to remove a program. Following applications "
+ "are part of the same package, and they will be removed."
+ " Are you sure you want to remove? " );
+ else
+ return true;
+ // create modal dialog for the question
+ KDialogBase *db = new KDialogBase( KDialogBase::Plain, i18n( "Confirm action" ),
+ KDialogBase::Ok | KDialogBase::Cancel,
+ KDialogBase::Ok, this );
+ QVBoxLayout *layout = new QVBoxLayout( db->plainPage() );
+ layout->setSpacing( 4 );
+ // db->plainPage()->setLayout( layout = new QVBoxLayout( db->plainPage() ) );
+ // QVBox *vb = new QVBox( db );
+ QLabel *txt = new QLabel( db->plainPage() );
+ txt->setAlignment( Qt::AlignLeft | Qt::AlignTop | Qt::WordBreak );
+ txt->setMinimumWidth( 500 );
+ txt->setText( t );
+ txt->setFixedHeight( txt->heightForWidth( 320 ) );
+ txt->setSizePolicy( QSizePolicy(
+ QSizePolicy::Expanding, QSizePolicy::Fixed, false ) );
+ DesktopList *l = new DesktopList( db->plainPage() );
+ l->setMinimumHeight( 220 );
+ l->setMinimumWidth( 320 );
+ l->setDisplayCheckboxes( false );
+ layout->addWidget( txt );
+ layout->addWidget( l );
+ l->insertRange( filteredRange( d.entries(),
+ Adaptor( &entity::Desktop::package, p ) ) );
+ db->adjustSize();
+ connect( db, SIGNAL( okClicked() ), this, SLOT( requestOk() ) );
+ m_currentRequestOk = false;
+ db->exec();
+ return m_currentRequestOk;
+}
+
+void App::request( entity::Package p, component::State::Action a ) {
+ if ( !confirmRequest( p, a ) ) return;
+ RequestList::iterator rm = m_requests.end(), i;
+ for ( i = m_requests.begin(); i != m_requests.end(); ++i ) {
+ if ( i->first == p ) {
+ rm = i;
+ break;
+ }
+ }
+ if ( rm != m_requests.end() )
+ m_requests.erase( rm );
+ if ( a != component::State::AKeep )
+ m_requests.push_back( std::make_pair( p, a ) );
+ cache::Global::get().state().revert();
+ cache::Global::get().state().replay( range( m_requests.begin(),
+ m_requests.end() ) );
+}
+
+bool App::consistent() {
+ int remove = 0;
+ RequestList::iterator i;
+ for ( i = m_requests.begin(); i != m_requests.end(); ++i ) {
+ if ( i->second == component::State::ARemove ) {
+ ++remove;
+ }
+ }
+ if ( remove >= cache::Global::get().state().removeCount() )
+ return true;
+ return false;
+}
+
+void App::setupActions()
+{
+ KStdAction::quit( kapp, SLOT( quit() ), actionCollection() );
+ m_undo = KStdAction::undo( this, SLOT( undo() ), actionCollection() );
+ m_redo = KStdAction::redo( this, SLOT( redo() ), actionCollection() );
+ m_previewAction = new KToggleAction(
+ i18n( "Review Changes" ), u8( "adept_preview" ),
+ 0, this, SLOT( togglePreview() ), actionCollection(),
+ "review" );
+
+ setHistoryEnabled( false );
+ createStandardStatusBarAction();
+}
+
+void App::togglePreview()
+{
+ if ( m_state == Preview ) {
+ m_previewAction->setChecked( false );
+ setState( Select );
+ m_stack->raiseWidget( m_view );
+ notifyPostChange( 0 );
+ m_reviewChanges->setEnabled(true);
+ } else {
+ setState( Preview );
+ m_stack->raiseWidget( m_preview );
+ setNext( i18n( "Back to Program Selection" ), SLOT( togglePreview() ) );
+ m_previewAction->setChecked( true );
+ m_preview->searchView()->lister()->scheduleRebuild();
+ m_reviewChanges->setEnabled(false);
+ }
+}
+
+void App::inspect()
+{
+ m_state = Inspect;
+ m_stack->raiseWidget( m_preview );
+ setNext( i18n( "Changes are OK, proceed" ), SLOT( commit() ) );
+ m_preview->searchView()->lister()->scheduleRebuild();
+}
+
+void App::setHistoryEnabled( bool e ) {
+ if ( e && history() ) {
+ m_undo->setEnabled( history()->canUndo() );
+ m_redo->setEnabled( history()->canRedo() );
+ } else {
+ m_undo->setEnabled( false );
+ m_redo->setEnabled( false );
+ }
+}
+
+void App::notifyPreRebuild( component::Base *b )
+{
+ m_requests.clear();
+}
+
+void App::notifyPreChange( component::Base *b )
+{
+ Application::notifyPreChange( b );
+ checkpoint();
+}
+
+void App::notifyPostChange( component::Base *b )
+{
+ Application::notifyPostChange( b );
+
+ if ( m_state == Select ) {
+ if ( cache().state().changed() )
+ if ( consistent() )
+ setNext( i18n( "Apply Changes" ), SLOT( commit() ) );
+ else
+ setNext( i18n( "Inspect Changes" ), SLOT( inspect() ) );
+ else
+ disableNext();
+ }
+}
+
+void App::setNext( QString s, const char *slot ) {
+ m_next->setText( s );
+ m_next->setEnabled( true );
+ m_next->disconnect( this );
+ connect( m_next, SIGNAL( clicked() ),
+ this, slot );
+ m_quit->setEnabled( true );
+}
+
+void App::disableNext() {
+ m_next->setText( i18n( "Next" ) );
+ m_next->setEnabled( false );
+ disconnect( m_next, SIGNAL( clicked() ), 0, 0 );
+}
+
+void App::disableButtons() {
+ disableNext();
+ m_quit->setEnabled( false );
+}
+
+void App::editSources() {
+ KProcess* softwarePropertiesProcess = new KProcess(this);
+ *softwarePropertiesProcess << "/usr/bin/software-properties-kde";
+ softwarePropertiesProcess->start();
+}
+
+void App::start() {
+ m_stack->raiseWidget( m_view );
+ m_quit->setText( i18n( "Forget Changes and Quit" ) );
+ disableNext();
+ setState( Select );
+ notifyPostChange( 0 );
+}
+
+void App::commit() {
+ kdDebug() << "App::commit" << endl;
+ setState( Commit );
+ disableButtons();
+ setHistoryEnabled( false );
+
+ aptFront::Manager m;
+ m.setProgressCallback( m_progress->callback() );
+ m.setUpdateInterval( 100000 );
+ try {
+ m_stack->raiseWidget( m_progress );
+ m.download();
+ m_stack->raiseWidget( m_commitProgress );
+ m.commit();
+ } catch ( exception::OperationCancelled ) {
+ return start();
+ } catch ( ... ) {
+ KMessageBox::sorry(
+ this, i18n( "There was an error commiting changes. "
+ "Possibly there was a problem downloading some "
+ "packages or the commit would break packages. " ),
+ i18n( "Could not commit changes" ) );
+ }
+
+ cache().addComponent( new component::Desktop() );
+ cache().component< component::Desktop >().setPolicy( new GroupPolicy() );
+ cache().component< component::Desktop >().loadDirectory(
+ INSTALLER_DATA "/desktop/" );
+ QTimer::singleShot( 500, m_view, SLOT( rebuild() ) );
+
+ m_stack->raiseWidget( m_bye );
+ m_quit->setText( i18n( "Quit" ) );
+ setNext( i18n( "Back to Program Selection" ), SLOT( start() ) );
+ // setNext( i18n( "Done: Quit" ), SLOT( close() ) );
+}
+
+#include "app.moc"
diff --git a/adept/installer/app.h b/adept/installer/app.h
new file mode 100644
index 0000000..02ce2e0
--- /dev/null
+++ b/adept/installer/app.h
@@ -0,0 +1,128 @@
+/* -*- C++ -*- */
+#ifndef TESTUI_APP_H
+#define TESTUI_APP_H
+
+#include <kmainwindow.h>
+#include <kparts/part.h>
+#include <kactionclasses.h>
+#include <apt-front/cache/observer.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+#include <apt-front/cache/component/desktop.h>
+#include <adept/view.h>
+#include <adept/commitprogress.h>
+#include <adept/installerview.h>
+#include <adept/application.h>
+
+class QVBox;
+class QWidgetStack;
+class QSplitter;
+class KAction;
+class KPushButton;
+class KProcess;
+namespace adept {
+class AcqProgressWidget;
+}
+
+using namespace aptFront;
+using namespace adept;
+
+struct GroupPolicy : cache::component::Desktop::GroupPolicy {
+ virtual std::string groupForCategories( utils::Range< std::string > );
+};
+
+struct IconPolicy : GroupedDesktopSelector::IconPolicy {
+ virtual QString iconForGroup( QString );
+};
+
+class App : public KMainWindow, Application {
+ Q_OBJECT
+public:
+ enum State { Select, Preview, Inspect, Commit };
+ void setupActions();
+ ExtTerminalInterface *terminal();
+ App();
+
+ // check if the changes in cache are consistent with what is
+ // checked in the tree and we don't have any suspicious removals
+ // or other artifacts (broken packages)
+ bool consistent();
+
+protected slots:
+ void start();
+ void commit();
+ void inspect();
+
+ void delayed();
+
+ void undo() { Application::undo(); }
+ void redo() { Application::redo(); }
+ void checkpoint() { Application::checkpoint(); }
+
+ void setHistoryEnabled( bool );
+
+ void disableNext();
+ void disableButtons();
+ void setNext( QString str, const char *slot );
+ void togglePreview();
+ void editSources();
+
+ void request( cache::entity::Package, cache::component::State::Action );
+
+ bool confirmRequest( entity::Package, component::State::Action );
+ void requestOk() { m_currentRequestOk = true; }
+
+protected:
+ friend class WaitForLister;
+
+ void setState( State s ) { m_lastState = m_state; m_state = s; }
+
+ virtual void notifyPreRebuild( cache::component::Base * );
+ virtual void notifyPostChange( cache::component::Base * );
+ virtual void notifyPreChange( cache::component::Base * );
+
+ QWidgetStack *m_stack;
+ QVBox *m_all;
+ QHBox *m_buttons;
+ QLabel *m_bye, *m_loading;
+ KPushButton *m_next, *m_quit;
+ KPushButton *m_editSources, *m_reviewChanges;
+
+ // stacked widgets
+ adept::AcqProgressWidget *m_progress;
+ adept::CommitProgress *m_commitProgress;
+ // adept::GroupedDesktopSelector *m_desktopSelector;
+ adept::InstallerView *m_view;
+ adept::Browser *m_preview;
+
+ // other stuff
+ std::vector<KAction *> m_actions;
+ QMap< QString, QString > m_icons;
+ KAction *m_undo, *m_redo;
+ KToggleAction *m_previewAction;
+ State m_state, m_lastState;
+
+ typedef std::list< component::State::Request > RequestList;
+ RequestList m_requests;
+
+ // XXX hack
+ bool m_currentRequestOk;
+};
+
+class WaitForLister : public QObject {
+ Q_OBJECT
+public:
+ WaitForLister( App *a, const char *s )
+ : app( a ), slot( s )
+ {
+ waiting();
+ }
+protected slots:
+ void waiting();
+protected:
+ App *app;
+ const char *slot;
+
+};
+
+#endif
diff --git a/adept/installer/hi128-app-adept_installer.png b/adept/installer/hi128-app-adept_installer.png
new file mode 100644
index 0000000..98f792b
--- /dev/null
+++ b/adept/installer/hi128-app-adept_installer.png
Binary files differ
diff --git a/adept/installer/hi16-app-adept_installer.png b/adept/installer/hi16-app-adept_installer.png
new file mode 100644
index 0000000..7426896
--- /dev/null
+++ b/adept/installer/hi16-app-adept_installer.png
Binary files differ
diff --git a/adept/installer/hi22-app-adept_installer.png b/adept/installer/hi22-app-adept_installer.png
new file mode 100644
index 0000000..d0f221f
--- /dev/null
+++ b/adept/installer/hi22-app-adept_installer.png
Binary files differ
diff --git a/adept/installer/hi32-app-adept_installer.png b/adept/installer/hi32-app-adept_installer.png
new file mode 100644
index 0000000..3f79aa4
--- /dev/null
+++ b/adept/installer/hi32-app-adept_installer.png
Binary files differ
diff --git a/adept/installer/hi48-app-adept_installer.png b/adept/installer/hi48-app-adept_installer.png
new file mode 100644
index 0000000..33f9459
--- /dev/null
+++ b/adept/installer/hi48-app-adept_installer.png
Binary files differ
diff --git a/adept/installer/hi64-app-adept_installer.png b/adept/installer/hi64-app-adept_installer.png
new file mode 100644
index 0000000..e2a2666
--- /dev/null
+++ b/adept/installer/hi64-app-adept_installer.png
Binary files differ
diff --git a/adept/installer/hisc-app-adept_installer.svgz b/adept/installer/hisc-app-adept_installer.svgz
new file mode 100644
index 0000000..00cfa1c
--- /dev/null
+++ b/adept/installer/hisc-app-adept_installer.svgz
Binary files differ
diff --git a/adept/installer/main.cpp b/adept/installer/main.cpp
new file mode 100644
index 0000000..079cb19
--- /dev/null
+++ b/adept/installer/main.cpp
@@ -0,0 +1,51 @@
+// KDE includes
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kuniqueapplication.h>
+
+#include "app.h"
+
+static KCmdLineOptions options[] =
+{
+ KCmdLineLastOption
+};
+
+int main(int argc, char *argv[])
+{
+
+ KLocale::setMainCatalogue("adept_installer");
+
+ putenv( "QT_IM_MODULE=xim" );
+ QString description = i18n("Adept Installer");
+
+ KAboutData aboutData( "adept_installer",
+ I18N_NOOP("Adept Installer"),
+ "2.1 Cruiser",
+ description.latin1(),
+ KAboutData::License_BSD,
+ I18N_NOOP("(c) 2005, 2006 Peter Rockai"),
+ 0,
+ "http://web.mornfall.net/adept.html");
+
+ aboutData.addAuthor ( "Peter Rockai",
+ I18N_NOOP("developer"),
+ "me at mornfall dot net",
+ "http://web.mornfall.net");
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+
+ KGlobal::locale()->insertCatalogue(QString::fromUtf8("libept"));
+
+ App *ta = new App();
+
+ app.setMainWidget(ta);
+ ta->show();
+
+ return app.exec();
+}
diff --git a/adept/kubuntu_upgrader/Makefile.am b/adept/kubuntu_upgrader/Makefile.am
new file mode 100644
index 0000000..63e9569
--- /dev/null
+++ b/adept/kubuntu_upgrader/Makefile.am
@@ -0,0 +1,11 @@
+METASOURCES = AUTO
+noinst_LTLIBRARIES = libkubuntuupgradewizard.la
+libkubuntuupgradewizard_la_SOURCES = \
+ upgradewizardbase.ui errordialogbase.ui \
+ errordialog.cpp upgradewizard.cpp
+libkubuntuupgradewizard_la_LIBADD = $(LIB_KIO) $(LIBKDE_UI)
+libkubuntuupgradewizard_la_LDFLAGS = -L/usr/lib/debug $(all_libraries)
+
+INCLUDES = $(all_includes)
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII
+
diff --git a/adept/kubuntu_upgrader/errordialog.cpp b/adept/kubuntu_upgrader/errordialog.cpp
new file mode 100644
index 0000000..0a1feb0
--- /dev/null
+++ b/adept/kubuntu_upgrader/errordialog.cpp
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Vladimir Stefan *
+ * vstefan85@gmail.com *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qlabel.h>
+
+#include "errordialog.h"
+
+ErrorDialog::ErrorDialog(QWidget* parent, QString error_text, const char* name, bool modal, WFlags fl )
+ : ErrorDialogDlg(parent,name, modal,fl)
+{
+ errorLabel->setText( error_text );
+}
+
+ErrorDialog::~ErrorDialog()
+{}
+
+/*$SPECIALIZATION$*/
+void ErrorDialog::reject()
+{
+ QDialog::reject();
+}
+
+void ErrorDialog::accept()
+{
+ QDialog::accept();
+}
+
+
+
+#include "errordialog.moc"
+
diff --git a/adept/kubuntu_upgrader/errordialog.h b/adept/kubuntu_upgrader/errordialog.h
new file mode 100644
index 0000000..cdb7d14
--- /dev/null
+++ b/adept/kubuntu_upgrader/errordialog.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Vladimir Stefan *
+ * vstefan85@gmail.com *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef ERRORDIALOG_H
+#define ERRORDIALOG_H
+
+#include "errordialogbase.h"
+
+class QString;
+
+class ErrorDialog : public ErrorDialogDlg
+{
+ Q_OBJECT
+
+public:
+ ErrorDialog(QWidget* parent = 0, QString error_text = QString::null, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~ErrorDialog();
+ /*$PUBLIC_FUNCTIONS$*/
+
+public slots:
+ /*$PUBLIC_SLOTS$*/
+
+protected:
+ /*$PROTECTED_FUNCTIONS$*/
+
+protected slots:
+ /*$PROTECTED_SLOTS$*/
+ virtual void reject();
+ virtual void accept();
+
+};
+
+#endif
+
diff --git a/adept/kubuntu_upgrader/errordialogbase.ui b/adept/kubuntu_upgrader/errordialogbase.ui
new file mode 100644
index 0000000..21af975
--- /dev/null
+++ b/adept/kubuntu_upgrader/errordialogbase.ui
@@ -0,0 +1,67 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ErrorDialogDlg</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>errorform</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>222</width>
+ <height>163</height>
+ </rect>
+ </property>
+ <property name="cursor">
+ <cursor>0</cursor>
+ </property>
+ <property name="caption">
+ <string>Error!</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>errorLabel</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;&lt;/p&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>exitButton</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;xit</string>
+ </property>
+ <property name="accel">
+ <string>Alt+X</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>retryButton</cstring>
+ </property>
+ <property name="text">
+ <string>Retr&amp;y</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Y</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/kubuntu_upgrader/upgradewizard.cpp b/adept/kubuntu_upgrader/upgradewizard.cpp
new file mode 100644
index 0000000..9b81c4d
--- /dev/null
+++ b/adept/kubuntu_upgrader/upgradewizard.cpp
@@ -0,0 +1,545 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Vladimir Stefan *
+ * vstefan85@gmail.com *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include <kurl.h>
+#include <kio/netaccess.h>
+#include <kio/job.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <ktar.h>
+#include <kdebug.h>
+
+#include <qwizard.h>
+#include <qwidget.h>
+#include <qpushbutton.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qtextbrowser.h>
+#include <qmime.h>
+#include <qstring.h>
+#include <qdialog.h>
+#include <qlabel.h>
+#include <qdatetime.h>
+#include <qtextstream.h>
+#include <qptrlist.h>
+#include <qdir.h>
+
+#include <iostream>
+#include <cstdlib>
+
+#include "upgradewizard.h"
+#include "errordialog.h"
+
+DistroEntry::DistroEntry(QString *d_field)
+{
+ dist_field = d_field;
+ supported_field = false;
+ name_field = NULL;
+ version_field = NULL;
+ date_field = NULL;
+ desc_field = NULL;
+ release_file_url = NULL;
+ release_notes_url = NULL;
+ upgrade_tool_url = NULL;
+ upgrade_tool_sig_url = NULL;
+}
+
+DistroEntry::~DistroEntry() {
+ free( dist_field );
+ free( name_field );
+ free( version_field );
+ free( date_field );
+ free( desc_field );
+ free( release_file_url );
+ free( release_notes_url );
+ free( upgrade_tool_url );
+ free( upgrade_tool_sig_url );
+}
+
+UpgradeWizard::UpgradeWizard(QWidget* parent, const char* name, bool modal, WFlags fl)
+ : UpgradeWizardDlg(parent,name, modal,fl)
+{
+ err_dlg = NULL;
+
+ for(int i=0; i<pageCount(); i++) {
+ QWidget* p = page( i );
+ setHelpEnabled( p, false );
+ }
+
+ QWidget *p = page( pageCount()-1 );
+ setBackEnabled( p, false );
+ textLabel3->hide();
+
+ p = page( pageCount()-2 );
+ setNextEnabled( p, false );
+
+ QPushButton *fin = finishButton();
+ connect(fin, SIGNAL( clicked() ), this, SLOT( launchDistUpdater() ) );
+
+}
+
+UpgradeWizard::~UpgradeWizard()
+{}
+
+// ** FUNCTIONS ** //
+
+void UpgradeWizard::removeDirectory(QString directoryName)
+{
+ // recursively delete a directory structure
+ // Mar-22-2007 Billy Pollifrone
+ QDir dir(directoryName);
+ QStringList files(dir.entryList());
+ for (QStringList::Iterator i=files.begin(); i!=files.end(); i++) {
+ QString fileName(*(i));
+ if (fileName == QString(".") || fileName == QString("..")) continue;
+ QFileInfo fileInfo(directoryName, fileName);
+ if (fileInfo.isDir()) {
+ removeDirectory(fileInfo.absFilePath());
+ } else {
+ QFile file(fileInfo.absFilePath());
+ file.remove();
+ }
+ }
+ dir.rmdir(directoryName);
+}
+
+void UpgradeWizard::removeOldUpgradeTool()
+{
+ // remove old files from dist-upgrade when we check if there is a knew one since
+ // adept kills us before we have a chance on the same run.
+ // Mar-22-2007 Billy Pollifrone
+ QString directoryName("/tmp/kde-root");
+ QString directoryFilter("adept_*.tmp*");
+ QDir dir(directoryName, directoryFilter);
+ QStringList files(dir.entryList());
+ for (QStringList::Iterator i=files.begin(); i!=files.end(); i++) {
+ QString fileName(*(i));
+ QFileInfo fileInfo(directoryName, fileName);
+ if (fileInfo.isDir()) {
+ removeDirectory(fileInfo.absFilePath());
+ } else {
+ QFile file(fileInfo.absFilePath());
+ file.remove();
+ }
+ }
+}
+
+bool UpgradeWizard::checkForDistUpgrade(bool skipIntrepid, QString url, bool developmentVersion) {
+ removeOldUpgradeTool();
+ std::cout << "UpgradeWizard::checkForDistUpgrade" << std::endl;
+
+ if (url == QString("")) {
+ url = QString("http://changelogs.ubuntu.com/meta-release");
+ }
+
+ bool upgrade_available = false;
+ KConfig* config = KGlobal::config();
+ config->setGroup("General Settings");
+ QString upgradeURL;
+ upgradeURL = config->readEntry(QString("upgradeURL"), url);
+ KURL metafile_url( upgradeURL );
+
+ QString temp_file_location;
+
+ if( KIO::NetAccess::download( metafile_url, temp_file_location, NULL ) ) {
+ QFile temp_file( temp_file_location );
+ temp_file.open( IO_ReadOnly );
+ QTextIStream *temp_file_stream = new QTextIStream( temp_file.readAll() );
+
+ // need to spawn a process to call lsb_release -c -s
+ // to find out which version of kubuntu we are using
+ KProcess *proc = new KProcess;
+ *proc << "lsb_release";
+ *proc << "-c" << "-s";
+ connect(proc, SIGNAL( receivedStdout( KProcess*, char *, int ) ),
+ this, SLOT( receiveDistroName( KProcess*, char *, int ) ) );
+ proc->start( KProcess::Block, KProcess::Stdout );
+
+ current_dist = 0;
+ QPtrList<DistroEntry> *entry_list = parseMetafile( temp_file_stream, distro_name );
+
+ upgrade_dist = entry_list->last();
+ DistroEntry* entry;
+
+ // if current_dist hasn't been set in parseMetafile then we can't upgrade, since we don't know what we are
+ if (current_dist == 0) {
+ return false;
+ }
+
+ // find the distro version one newer than our current one
+ for( entry = entry_list->first(); entry; entry = entry_list->next() ) {
+ //std::cout << "current date: " << (*current_dist->date_field).toString().latin1() << std::endl;
+ //std::cout << "entry date: " << (*entry->date_field).toString().latin1() << std::endl;
+ if( *entry->date_field > *current_dist->date_field /*&& entry->supported_field == true*/ ) {
+ if (!skipIntrepid || QString::compare(*entry->dist_field, QString("intrepid")) != 0) {
+ upgrade_dist = entry;
+ upgrade_available = true;
+ //std::cout << "entry date: " << (*entry->name_field).latin1() << std::endl;
+ break;
+ }
+ }
+ }
+ // if there isn't one newer, find the current one
+ if (!upgrade_available) {
+ for( entry = entry_list->first(); entry; entry = entry_list->next() ) {
+ //std::cout << "current date: " << (*current_dist->date_field).toString().latin1() << std::endl;
+ //std::cout << "entry date: " << (*entry->date_field).toString().latin1() << std::endl;
+ if( *entry->date_field >= *current_dist->date_field && developmentVersion /*&& entry->supported_field == true*/ ) {
+ upgrade_dist = entry;
+ upgrade_available = true;
+ //std::cout << "entry date: " << (*entry->name_field).latin1() << std::endl;
+ break;
+ }
+ }
+ }
+
+ // DistroEntry *entry = NULL;
+ /*Debugging
+ for( entry = entry_list->first(); entry; entry = entry_list->next() ) {
+ std::cout << "current date: " << (*current_dist->date_field).toString().latin1() << std::endl;
+ std::cout << "entry date: " << (*entry->date_field).toString().latin1() << std::endl;
+
+ std::cout << "Dist: " << *entry->dist_field->latin1() << std::endl;
+ std::cout << "Name: " << *entry->name_field->latin1() << std::endl;
+ std::cout << "Version: " << *entry->version_field->latin1() << std::endl;
+ std::cout << "Date: " << entry->date_field->toString( QString( "ddd, dd MMM yyyy hh:mm:ss UTC" ) ).latin1() << std::endl;
+ //std::cout << "Supported: " << entry->supported_field.latin1() << std::endl;
+ std::cout << "Description: " << *entry->desc_field->latin1() << std::endl;
+ std::cout << "Release-File: " << entry->release_file_url->prettyURL().latin1() << std::endl;
+ if( entry->release_notes_url != NULL ) {
+ std::cout << "ReleaseNotes: " << entry->release_notes_url->prettyURL().latin1() << std::endl;
+ }
+ if( entry->upgrade_tool_url != NULL ) {
+ std::cout << "UpgradeTool: " << entry->upgrade_tool_url->prettyURL().latin1() << std::endl;
+ }
+ if( entry->upgrade_tool_sig_url != NULL ) {
+ std::cout << "UpgradeToolSignature: " << entry->upgrade_tool_sig_url->prettyURL().latin1() << std::endl;
+ }
+
+ std::cout << std::endl;
+ }
+ */
+ temp_file.close();
+ KIO::NetAccess::removeTempFile( temp_file_location );
+ }
+
+ return upgrade_available;
+}
+
+QPtrList<DistroEntry> *UpgradeWizard::parseMetafile( QTextIStream *text_stream,
+ QString my_distro_name )
+{
+ QPtrList<DistroEntry> *metafile_entries = new QPtrList<DistroEntry>();
+ DistroEntry *entry = NULL;
+
+ while( !text_stream->atEnd() ) {
+
+ QStringList line = QStringList::split( QChar(':'), text_stream->readLine() );
+
+ if( !line.isEmpty() ) {
+ QString first = line.first();
+ if( QString::compare( first, QString( "Dist" ) ) == 0 ) {
+ // we've encountered a new entry:
+ // first save the old one
+ if( entry != NULL ) {
+ // if this entry is for the current version we are running,
+ // then add it at the start of the list
+ if( QString::compare( *entry->dist_field, my_distro_name ) == 0) {
+ current_dist = entry;
+ metafile_entries->prepend( entry );
+ } else {
+ metafile_entries->append( entry );
+ }
+ }
+ // now create a new entry
+ line.pop_front();
+ entry = new DistroEntry( new QString( line.first().stripWhiteSpace() ) );
+ }
+
+ else if( QString::compare( first, QString( "Name" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ entry->name_field = new QString( line.first().stripWhiteSpace() );
+ }
+ }
+
+ else if( QString::compare( first, QString( "Version" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ entry->version_field = new QString( line.first().stripWhiteSpace() );
+ }
+ }
+
+ else if( QString::compare( first, QString( "Date" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ QString temp = line.join( QChar(' ') ).stripWhiteSpace();
+ // get the day(verbal)
+ line = QStringList::split( QChar(' '), temp );
+ QString day_verbal = line.first();
+ day_verbal.truncate(3);
+ // get the date
+ line.pop_front();
+ QString date = line.first();
+ // get the month(verbal)
+ line.pop_front();
+ QString month_verbal = line.first();
+ // get the year
+ line.pop_front();
+ QString year = line.first();
+ // get the time
+ line.pop_front();
+ QString time = line.first() + ":";
+ line.pop_front();
+ time += line.first() + ":";
+ line.pop_front();
+ time += line.first();
+
+ QDate the_date( QDate::fromString( day_verbal + " " + month_verbal + " " + date + " " + year) );
+ QTime the_time( QTime::fromString( time ) );
+
+ entry->date_field = new QDateTime( the_date, the_time );
+ }
+ }
+
+ else if( QString::compare( first, QString( "Supported" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ entry->supported_field = line.first().stripWhiteSpace().toInt();
+ }
+ }
+
+ else if( QString::compare( first, QString( "Description" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ entry->desc_field = new QString( line.first().stripWhiteSpace() );
+ }
+ }
+
+ else if( QString::compare( first, QString( "Release-File" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ QString http_part = line.first().stripWhiteSpace() + ":";
+ line.pop_front();
+ QString complete_url = http_part + line.first().stripWhiteSpace();
+ entry->release_file_url = new KURL( complete_url );
+ }
+ }
+
+ else if( QString::compare( first, QString( "ReleaseNotes" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ QString http_part = line.first().stripWhiteSpace() + ":";
+ line.pop_front();
+ QString complete_url = http_part + line.first().stripWhiteSpace();
+ entry->release_notes_url = new KURL( complete_url );
+ }
+ }
+
+ else if( QString::compare( first, QString( "UpgradeTool" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ QString http_part = line.first().stripWhiteSpace() + ":";
+ line.pop_front();
+ QString complete_url = http_part + line.first().stripWhiteSpace();
+ entry->upgrade_tool_url = new KURL( complete_url );
+ }
+ }
+
+ else if( QString::compare( first, QString( "UpgradeToolSignature" ) ) == 0 ) {
+ if( entry != NULL ) {
+ line.pop_front();
+ QString http_part = line.first().stripWhiteSpace() + ":";
+ line.pop_front();
+ QString complete_url = http_part + line.first().stripWhiteSpace();
+ entry->upgrade_tool_sig_url = new KURL( complete_url );
+ }
+ }
+ }
+
+
+ }
+ // add the last one
+ // if this entry is for the current version we are running,
+ // then add it at the start of the list
+ if( QString::compare( *entry->dist_field, my_distro_name ) == 0 ) {
+ current_dist = entry;
+ metafile_entries->prepend( entry );
+ } else {
+ metafile_entries->append( entry );
+ }
+
+ return metafile_entries;
+}
+
+// ** SLOTS ** //
+
+void UpgradeWizard::receiveDistroName( KProcess*, char *buffer, int buflen ) {
+ distro_name = QString::fromAscii( buffer, buflen-1 );
+}
+
+void UpgradeWizard::launchDistUpdater() {
+ QDir dir;
+ dir.mkdir(upgrade_tool_location+"-extract");
+
+ KTar tarFile(upgrade_tool_location, QString("application/x-gzip"));
+ tarFile.open(IO_ReadOnly);
+ //KArchiveDirectory* tarDirectory = tarFile.directory();
+ //tarDirectory->copyTo(upgrade_tool_location+"-extract");
+ tarFile.directory()->copyTo(upgrade_tool_location+"-extract", true);
+
+ KProcess *proc = new KProcess;
+ proc->setWorkingDirectory(upgrade_tool_location+"-extract");
+ *proc << "python" << upgrade_tool_location+"-extract/dist-upgrade.py";
+ *proc << "--frontend" << "DistUpgradeViewKDE";
+ proc->start( KProcess::DontCare );
+
+ // don't kill adept, it stops the app from running
+ // parentWidget()->close();
+}
+
+void UpgradeWizard::fetchReleaseAnnounce() {
+ QString temp_file_location;
+ bool result = false;
+
+ if (upgrade_dist->release_notes_url == NULL) {
+ kdDebug() << "No release notes URL, so I'm skipping the fetch." << endl;
+ } else {
+ KURL my_url(*upgrade_dist->release_notes_url);
+ result = KIO::NetAccess::download(my_url, temp_file_location, NULL );
+ }
+
+ if( result ) {
+ emit killErrorDialog();
+ err_dlg = NULL;
+ textBrowser1->mimeSourceFactory()->setExtensionType( QString("tmp"), "text/plain" );
+ textBrowser1->setSource( temp_file_location );
+ QWidget *p = page( pageCount()-2 );
+ setNextEnabled( p, true );
+ } else {
+ if(err_dlg == NULL ) {
+ err_dlg = new ErrorDialog( this, i18n( "Could not download the release announcement. Please check that your Internet connection is active." ), 0, 1 );
+ connect( err_dlg->retryButton, SIGNAL( clicked() ), this, SLOT( fetchReleaseAnnounce() ) );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), err_dlg, SLOT( close() ) );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), this, SLOT( close() ) );
+ connect( this, SIGNAL( killErrorDialog() ), err_dlg, SLOT( close() ) );
+ err_dlg->show();
+ }
+ }
+}
+
+void UpgradeWizard::fetchUpgradeTool() {
+ // download the upgrade tool
+ KURL my_url(*upgrade_dist->upgrade_tool_url);
+ bool result = KIO::NetAccess::download( my_url, upgrade_tool_location, NULL );
+ // uncomment this to use for testing if you don't want to d/l the file every time
+ //bool result = KIO::NetAccess::download( "/home/vladi/edgy.tar.gz", upgrade_tool_location, NULL );
+ if( result ) {
+ emit killErrorDialog();
+ err_dlg = NULL;
+ fetchUpgradeToolSig();
+ } else {
+ if(err_dlg == NULL ) {
+ err_dlg = new ErrorDialog( this, i18n( "Could not download the upgrade tool. Please check that your Internet connection is active." ), 0, 1 );
+ connect( err_dlg->retryButton, SIGNAL( clicked() ), this, SLOT( fetchUpgradeTool() ) );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), err_dlg, SLOT( close() ) );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), this, SLOT( close() ) );
+ connect( this, SIGNAL( killErrorDialog() ), err_dlg, SLOT( close() ) );
+ err_dlg->show();
+ }
+ }
+}
+
+void UpgradeWizard::fetchUpgradeToolSig() {
+ bool result = KIO::NetAccess::download( *upgrade_dist->upgrade_tool_sig_url, upgrade_tool_sig_location, NULL );
+ if( result) {
+ emit killErrorDialog();
+ err_dlg = NULL;
+ verifyUpgradeTool();
+ } else {
+ if(err_dlg == NULL ) {
+ err_dlg = new ErrorDialog( this, i18n( "Could not download the upgrade tool's GPG signature. Please check that your Internet connection is active." ), 0, 1 );
+ connect( err_dlg->retryButton, SIGNAL( clicked() ), this, SLOT( fetchUpgradeToolSig() ) );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), err_dlg, SLOT( close() ) );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), this, SLOT( close() ) );
+ connect( this, SIGNAL( killErrorDialog() ), err_dlg, SLOT( close() ) );
+ err_dlg->show();
+ }
+ }
+}
+
+void UpgradeWizard::verifyUpgradeTool() {
+ // spawn a process to call gpg and verify the signature
+ KProcess *proc = new KProcess;
+ *proc << "gpg";
+ *proc << "--keyring" << "/etc/apt/trusted.gpg" << "--verify" << upgrade_tool_sig_location << upgrade_tool_location;
+
+ proc->start( KProcess::Block, KProcess::Stdout );
+ // signature verification successful if gpg exist status = 0
+ if( proc->exitStatus() == 0 ) {
+ emit killErrorDialog();
+ err_dlg = NULL;
+ // remove the signature file
+ KIO::file_delete( KURL( upgrade_tool_sig_location ), false );
+ QWidget *p = page( pageCount()-1 );
+ setFinishEnabled( p, true );
+ textLabel3->show();
+ } else {
+ if(err_dlg == NULL ) {
+ err_dlg = new ErrorDialog( this, i18n( "Could not verify the integrity of the upgrader application. This program will now exit." ), 0, 1 );
+ //connect( err_dlg->retryButton, SIGNAL( clicked() ), this, SLOT( verify_upgrade_tool() ) );
+ err_dlg->retryButton->setEnabled( false );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), err_dlg, SLOT( close() ) );
+ connect( err_dlg->exitButton, SIGNAL( clicked() ), this, SLOT( close() ) );
+ connect( this, SIGNAL( killErrorDialog() ), err_dlg, SLOT( close() ) );
+ err_dlg->show();
+ }
+ }
+}
+
+void UpgradeWizard::back()
+{
+ QWizard::back();
+}
+
+void UpgradeWizard::next()
+{
+ QWizard::next();
+
+ // page 1: d/l release announcement
+ // and display it on page1
+ if( indexOf( currentPage() ) == 1 ) {
+ fetchReleaseAnnounce();
+ }
+ else if( indexOf( currentPage() ) == 2 ) {
+ // remove the temp file used to store the release announcement
+ KIO::file_delete( KURL( textBrowser1->source() ), false );
+
+ // download the tool, its signature, and verify
+ fetchUpgradeTool();
+ }
+}
+
+
+
+
+#include "upgradewizard.moc"
+
diff --git a/adept/kubuntu_upgrader/upgradewizard.h b/adept/kubuntu_upgrader/upgradewizard.h
new file mode 100644
index 0000000..21b3f3c
--- /dev/null
+++ b/adept/kubuntu_upgrader/upgradewizard.h
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Vladimir Stefan *
+ * vstefan85@gmail.com *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef UPGRADEWIZARD_H
+#define UPGRADEWIZARD_H
+
+#include <adept/kubuntu_upgrader/upgradewizardbase.h>
+
+class QString;
+class QTextIStream;
+class QDateTime;
+class KProcess;
+class KURL;
+class ErrorDialog;
+
+// ** Represents an entry in the metafile ** //
+class DistroEntry {
+ public:
+ DistroEntry(QString *d_field);
+ ~DistroEntry();
+ QString *dist_field;
+ QString *name_field;
+ QString *version_field;
+ QDateTime *date_field;
+ bool supported_field;
+ QString *desc_field;
+ KURL *release_file_url;
+ KURL *release_notes_url;
+ KURL *upgrade_tool_url;
+ KURL *upgrade_tool_sig_url;
+};
+
+class UpgradeWizard : public UpgradeWizardDlg
+{
+ Q_OBJECT
+
+public:
+ UpgradeWizard(QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~UpgradeWizard();
+
+ /*$PUBLIC_FUNCTIONS$*/
+ bool checkForDistUpgrade(bool skipIntrepid=true, QString url=QString(""), bool developmentVersion = false);
+ QPtrList<DistroEntry> *parseMetafile( QTextIStream *text_stream,
+ QString my_distro_name );
+
+public slots:
+ /*$PUBLIC_SLOTS$*/
+ void receiveDistroName( KProcess* p, char *buffer, int buflen );
+ void launchDistUpdater();
+ void fetchReleaseAnnounce();
+ void fetchUpgradeTool();
+ void fetchUpgradeToolSig();
+ void verifyUpgradeTool();
+
+
+ signals:
+ void killErrorDialog();
+
+protected:
+ /*$PROTECTED_FUNCTIONS$*/
+ void removeOldUpgradeTool();
+ void removeDirectory(QString directoryName);
+
+protected slots:
+ /*$PROTECTED_SLOTS$*/
+ virtual void back();
+ virtual void next();
+
+private:
+ QString upgrade_tool_location;
+ QString upgrade_tool_sig_location;
+ QString distro_name;
+ DistroEntry* upgrade_dist;
+ DistroEntry* current_dist;
+ ErrorDialog* err_dlg;
+};
+
+#endif
+
diff --git a/adept/kubuntu_upgrader/upgradewizardbase.ui b/adept/kubuntu_upgrader/upgradewizardbase.ui
new file mode 100644
index 0000000..c2d1eee
--- /dev/null
+++ b/adept/kubuntu_upgrader/upgradewizardbase.ui
@@ -0,0 +1,143 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>UpgradeWizardDlg</class>
+<author>Vladimir Stefan</author>
+<widget class="QWizard">
+ <property name="name">
+ <cstring>upgrade_wizard</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>584</width>
+ <height>446</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Upgrade Wizard</string>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>WizardPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Upgrade Wizard</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>A new distribution version is available! Click next if you wish to upgrade now.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>271</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>WizardPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Upgrade Wizard</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Release Announcement:</string>
+ </property>
+ </widget>
+ <widget class="QTextBrowser" row="1" column="0">
+ <property name="name">
+ <cstring>textBrowser1</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>WizardPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Upgrade Wizard</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Downloading and verifying the upgrade tool ...</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Ready to upgrade! Click finish to close the Adept Package Manager and launch the distribution upgrade tool.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>231</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/libadept/Makefile.am b/adept/libadept/Makefile.am
new file mode 100644
index 0000000..810f516
--- /dev/null
+++ b/adept/libadept/Makefile.am
@@ -0,0 +1,33 @@
+noinst_LTLIBRARIES = libadept.la
+libadept_la_SOURCES = \
+ acqprogresswidgetui.ui acqprogress.cpp \
+ tagchooser.cpp filtersidebarui.ui filtersidebar.cpp \
+ application.cpp \
+ tagfilterui.ui tagfilter.cpp taglist.cpp \
+ packageinfoui.ui packageinfo.cpp \
+ commitprogressui.ui commitprogress.cpp \
+ progress.cpp \
+ sourceseditorui.ui sourceseditor.cpp \
+ acqprogresswidget.cpp dpkgpm.cpp \
+ dpkgpm-gui.cpp \
+ extendablelist.cpp \
+ desktopentryui.ui desktoplist.cpp \
+ groupeddesktopselector.cpp \
+ packagedetailsui.ui packagedetails.cpp view.cpp \
+ listerextenderui.ui lister.cpp filterlist.cpp \
+ filterwidget.cpp \
+ quickfilterui.ui quickfilter.cpp \
+ statefilterui.ui statefilter.cpp \
+ easytagfilterui.ui easytagfilter.cpp \
+ actor.h threadutils.cpp \
+ installerviewui.ui installerview.cpp
+libadept_la_LDFLAGS = -L/usr/lib/debug $(all_libraries)
+libadept_la_LIBADD = -lapt-front -ltagcoll
+
+INCLUDES = -I$(srcdir)/.. -I.. $(all_includes) $(LIBTAGCOLL2_CFLAGS) $(LIBAPT_FRONT_CFLAGS)
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII -DDEFAULT_KONSOLE_HIDDEN=true
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/libadept.pot
diff --git a/adept/libadept/acqprogress.cpp b/adept/libadept/acqprogress.cpp
new file mode 100644
index 0000000..4b0643f
--- /dev/null
+++ b/adept/libadept/acqprogress.cpp
@@ -0,0 +1,295 @@
+// -*- C++ -*-
+
+#include <qprogressbar.h>
+#include <klistview.h>
+#include <kapplication.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "acqprogress.h"
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/acquire-worker.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/configuration.h>
+
+#include <adept/utils.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <iostream>
+
+#define _(a...) (a) // XXX
+
+using namespace std;
+
+namespace adept {
+
+AcqStatus::Item::Item (KListView *parent, pkgAcquire::ItemDesc &item, bool hit)
+: KListViewItem( parent )
+{
+ m_pbcol = 0;
+ m_prog = new ItemProgress( 0, 0 );
+ m_prog->setStatus( "waiting" );
+ m_prog->setTotalSteps( 100 );
+ m_item = item;
+ m_id = m_item.Owner->ID;
+ /* if (item.Owner->FileSize > 0)
+ setText( 1, SizeToStr( item.Owner->FileSize ).c_str() + QString( "B" ) ); */
+ setText( 1, u8( item.Description ) );
+ // cerr << "create: id = " << item . Owner -> ID << ", myId = " << m_item . Owner -> ID << endl;
+ if (hit) {
+ m_prog->setStatus( "hit" );
+ } else
+ m_prog->setStatus( "waiting" );
+ // QString (SizeToStr (Itm.Owner -> FileSize) . c_str ()) + QString ("B"),
+ // /* QString (Itm . Owner -> ID) + */ QString (Itm.Description . c_str ()));
+}
+
+AcqStatus::Item::~Item ()
+{
+ delete m_prog;
+}
+
+int AcqStatus::Item::compare (QListViewItem *i, int /*col*/, bool /*ascend*/) const
+{
+ int id1 = m_id;
+ int id2 = ((Item *) i) -> m_id;
+ return (id2 >= id1) - (id2 <= id1);
+}
+
+void AcqStatus::Item::pulse (pkgAcquire::Worker *w)
+{
+ if (w) {
+ if (w->TotalSize)
+ setStatus( "progress", long( double(
+ w -> CurrentSize * 100.0)
+ / double( w->TotalSize ) ) );
+ else
+ setStatus( "downloading", 0 );
+ }
+}
+
+void AcqStatus::Item::setStatus( const std::string &s, int i )
+{
+ m_prog->setStatus( s, i );
+}
+
+void AcqStatus::Item::paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+
+ if ( column == m_pbcol ) {
+ const QRect bar = QRect( 0, 0, width, height() );
+ m_prog->resize( width, height() );
+ QPixmap pm = QPixmap::grabWidget( m_prog );
+ // p->fillRect( bar, listView()->paletteBackgroundColor() );
+ p->drawPixmap( bar.x(), bar.y(), pm );
+ } else {
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ _cg.setColor( QColorGroup::Text, c );
+ KListViewItem::paintCell( &_p, _cg, column, width, alignment );
+ p->drawPixmap( 0, 0, pm );
+ }
+}
+
+AcqStatus::Item *AcqStatus::findItem (pkgAcquire::ItemDesc &Itm)
+{
+ if ( Itm.Owner->ID < m_idOffset )
+ return 0;
+ if ( Itm.Owner->ID - m_idOffset >= m_items.size() )
+ return 0;
+ return m_items[ Itm.Owner->ID - m_idOffset ];
+}
+
+AcqStatus::AcqStatus(QWidget *parent, const char *name)
+ : KListView (parent, name), m_idOffset( 0 ), m_continue( true )
+{
+ // m_lastItem = 0;
+ addColumn( i18n( "Progress" ) );
+ addColumn( i18n( "Description" ) );
+ setSorting (1);
+ setColumnWidth (0, 220);
+ setColumnWidth (1, 300);
+ setResizeMode (LastColumn);
+ ID = 0;
+}
+
+void AcqStatus::Done (pkgAcquire::ItemDesc &Itm)
+{
+ Item *i = findItem (Itm);
+ if (i) {
+ i->setStatus( "done" );
+ }
+ emit statusChanged( StWaiting );
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+}
+
+void AcqStatus::clear()
+{
+ KListView::clear();
+ m_idOffset += m_items.size();
+ m_items.clear(); // got deleted by klistview already
+}
+
+void AcqStatus::Start()
+{
+ clear();
+ pkgAcquireStatus::Start();
+ kdDebug() << "AcqStatus::Start ()" << endl;
+ _config -> Set ("APT::Fetcher::Select-Timeout-Usec", 100000);
+ emit statusChanged( StWaiting );
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+}
+
+void AcqStatus::IMSHit(pkgAcquire::ItemDesc &Itm)
+{
+ Itm.Owner->ID = ID++;
+ Item *i = new Item( this, Itm, true );
+ // ensureItemVisible( i );
+ i->setStatus( "hit" );
+ m_items.push_back( i );
+
+ kdDebug() << "imshit called on ID = " << ID - 1 << " i = " << (void *)i << endl;
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+};
+
+void AcqStatus::Fetch(pkgAcquire::ItemDesc &Itm)
+ // an item started to download
+{
+ Update = true;
+ if (Itm.Owner->Complete == true) // XXX?
+ return;
+
+ Itm.Owner->ID = ID++;
+
+ Item *i = new Item( this, Itm );
+ // ensureItemVisible( i );
+ m_items.push_back( i );
+
+ kdDebug() << "fetch called on ID = " << ID - 1 << " i = " << (void *)i << endl;
+ emit statusChanged( StDownloading );
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+};
+
+void AcqStatus::Fail(pkgAcquire::ItemDesc &Itm)
+ // item failed to download
+{
+ kdDebug() << "fail, status = " << Itm.Owner->Status
+ << " ID = " << Itm.Owner->ID << endl;
+ // Ignore certain kinds of transient failures (bad code)
+ if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) {
+ kdDebug() << "fail with StatIdle, ignoring" << endl;
+ return;
+ }
+
+ Item *i = findItem (Itm);
+ kdDebug() << "fail, i = " << i << endl;
+ if (! i)
+ return;
+ if (Itm.Owner->Status == pkgAcquire::Item::StatDone) {
+ i->setStatus( "ignored" );
+ } else {
+ i->setStatus( "error" );
+ }
+
+ triggerUpdate();
+ KApplication::kApplication()->processEvents();
+};
+
+void AcqStatus::Stop()
+{
+ pkgAcquireStatus::Stop();
+ emit statusChanged( StDone );
+ triggerUpdate ();
+ KApplication::kApplication()->processEvents();
+}
+
+bool AcqStatus::Pulse(pkgAcquire *Owner)
+{
+ pkgAcquireStatus::Pulse(Owner);
+
+ for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
+ I = Owner->WorkerStep(I)) {
+ if (I -> CurrentItem) {
+ Item *i = findItem (* (I -> CurrentItem));
+ if (i)
+ i -> pulse (I);
+ }
+ }
+
+ triggerUpdate ();
+ // repaint ();
+
+ if (TotalBytes > 0)
+ emit totalProgress(
+ long( double(
+ (CurrentBytes +
+ CurrentItems)*100.0)/double(TotalBytes+TotalItems) ) );
+ else
+ emit totalProgress (-1);
+ KApplication::kApplication () -> processEvents ();
+
+ if ( m_continue )
+ return true;
+
+ m_continue = true;
+ return false;
+}
+
+bool AcqStatus::MediaChange(string Media,string Drive)
+{
+ int res = KMessageBox::warningContinueCancel(
+ this, i18n( "Please insert the disc "
+ "labeled '%1' in the drive "
+ "'%2' and press enter" ).arg(
+ u8( Media ) ).arg( u8( Drive ) ),
+ i18n( "Media Change" ) );
+ if ( res == KMessageBox::Cancel )
+ cancel();
+ return true;
+}
+
+void AcqStatus::cancel()
+{
+ m_continue = false;
+}
+
+AcqStatusDialog::AcqStatusDialog (QWidget *parent, const char *name, bool modal)
+ : KDialogBase( parent, name, modal,
+ u8( "progress dialog (FIXME: waiting for headers, done)" ),
+ Ok|Cancel, Cancel, true )
+{
+ m_status = new AcqStatus (this, "");
+ setMainWidget( m_status.data() );
+ enableButton (Ok, false);
+ connect (m_status.data(), SIGNAL (statusChanged (AcqStatus::Status)),
+ this, SLOT (statusChange (AcqStatus::Status)));
+}
+
+void AcqStatusDialog::statusChange (AcqStatus::Status st)
+{
+ if (st == AcqStatus::StDownloading || st == AcqStatus::StWaiting) {
+ enableButton (Ok, false);
+ // XXX: cancel should be true; but needs implementation first
+ enableButton (Cancel, false);
+ } else if (st == AcqStatus::StDone) {
+ enableButton (Ok, true);
+ enableButton (Cancel, false);
+ }
+}
+
+}
+
+#include "acqprogress.moc"
diff --git a/adept/libadept/acqprogress.h b/adept/libadept/acqprogress.h
new file mode 100644
index 0000000..9510825
--- /dev/null
+++ b/adept/libadept/acqprogress.h
@@ -0,0 +1,127 @@
+/** -*- C++ -*-
+ @file adept/acqprogress.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#ifndef ACQPROGRESS_H
+#define ACQPROGRESS_H
+
+#include <klocale.h>
+#include <kdialogbase.h>
+#include <klistview.h>
+#include <kprogress.h>
+
+#include <vector>
+#include <apt-pkg/acquire.h>
+#include <apt-front/progresscallback.h>
+
+class AcqStatus;
+class QLabel;
+class QProgressBar;
+class QSpacer;
+class QGridLayout;
+
+namespace adept {
+
+class AcqStatus : public KListView, public aptFront::ProgressCallback
+{
+ Q_OBJECT
+protected:
+ class ItemProgress: public KProgress {
+ public:
+ ItemProgress( QWidget *parent, const char *name = 0 )
+ : KProgress( parent, name ), m_spin( 0 ) {}
+ void setStatus( const std::string &s,
+ int prog = 0 ) {
+ m_status = s;
+ if (m_status == "hit"
+ || m_status == "ignored"
+ || m_status == "done")
+ prog = 100;
+ if (m_status == "waiting") {
+ prog = 0;
+ }
+ if (m_status == "progress" && prog != 100)
+ setFormat( i18n( "downloading (%p%)" ) );
+ else if (prog == 100) // who cares about hit/ignore anyway?
+ setFormat( i18n( "done (%p%)" ) );
+ else
+ setFormat( m_status );
+ setProgress( prog );
+ }
+ protected:
+ std::string m_status;
+ int m_spin;
+ };
+ class Item : public KListViewItem {
+ protected:
+ ItemProgress *m_prog;
+ int m_pbcol;
+ unsigned long m_id;
+ pkgAcquire::ItemDesc m_item;
+
+ public:
+ Item (KListView *parent, pkgAcquire::ItemDesc &item,
+ bool hit = false);
+ virtual ~Item ();
+
+ virtual void paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment);
+
+ void setProgress (int);
+ virtual int compare (QListViewItem *i, int col, bool ascend) const;
+ virtual void pulse (pkgAcquire::Worker *);
+ void setStatus( const std::string &, int = 0 );
+
+ void setup() {
+ KListViewItem::setup();
+ setHeight( height() + 6 );
+ }
+ };
+ unsigned long ID;
+ unsigned long m_idOffset;
+ std::vector <Item *> m_items;
+ bool m_continue;
+
+public:
+
+ enum Status { StWaiting, StDownloading, StDone };
+
+ AcqStatus (QWidget *parent, const char *name);
+ Item *findItem (pkgAcquire::ItemDesc &Itm);
+
+ virtual bool MediaChange (string Media,string Drive);
+ virtual void IMSHit (pkgAcquire::ItemDesc &Itm);
+ virtual void Fetch (pkgAcquire::ItemDesc &Itm);
+ virtual void Done (pkgAcquire::ItemDesc &Itm);
+ virtual void Fail (pkgAcquire::ItemDesc &Itm);
+ virtual void Start ();
+ virtual void Stop ();
+ void addLine (QWidget *l, QWidget *s, QWidget *prog);
+ void clear();
+
+ bool Pulse (pkgAcquire *Owner);
+
+public slots:
+ void cancel();
+
+signals:
+ void statusChanged (AcqStatus::Status st);
+ void totalProgress (int percent);
+
+ //AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet);
+};
+
+class AcqStatusDialog : public KDialogBase
+{
+ Q_OBJECT
+protected:
+ aptFront::SharedPtr<AcqStatus> m_status;
+public:
+ aptFront::SharedPtr<aptFront::ProgressCallback> callback() { return m_status.data(); };
+ AcqStatusDialog (QWidget *parent, const char *name, bool modal);
+public slots:
+ void statusChange (AcqStatus::Status st);
+};
+}
+#endif
diff --git a/adept/libadept/acqprogresswidget.cpp b/adept/libadept/acqprogresswidget.cpp
new file mode 100644
index 0000000..dd02f03
--- /dev/null
+++ b/adept/libadept/acqprogresswidget.cpp
@@ -0,0 +1,53 @@
+#include <kprogress.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include "acqprogresswidget.h"
+#include "acqprogress.h"
+
+using namespace adept;
+
+AcqProgressWidget::AcqProgressWidget( QWidget *parent, const char *name )
+ : AcqProgressWidgetUi( parent, name )
+{
+ m_statusRef = m_status;
+ m_progress->setTotalSteps( 100 );
+ m_progress->setProgress( 0 );
+ connect(m_status, SIGNAL( totalProgress( int ) ),
+ this, SLOT( setProgress( int ) ) );
+ connect(m_status, SIGNAL( statusChanged( AcqStatus::Status ) ),
+ this, SLOT( statusChange( AcqStatus::Status ) ) );
+ connect( m_cancel, SIGNAL( clicked() ),
+ m_status, SLOT( cancel() ) );
+}
+
+void AcqProgressWidget::statusChange( AcqStatus::Status s )
+{
+ QString t;
+ switch (s) {
+ case AcqStatus::StWaiting:
+ t = i18n( "Waiting for headers (%p%)" );
+ break;
+ case AcqStatus::StDownloading:
+ t = i18n( "Downloading (%p%)" );
+ break;
+ case AcqStatus::StDone:
+ t = i18n( "Done (%p%)" );
+ m_progress->setProgress( 100 );
+ break;
+ }
+ m_progress->setFormat( t );
+}
+
+void AcqProgressWidget::setProgress( int p )
+{
+ if (p < 0) {
+ m_progress->setTotalSteps( 0 );
+ m_progress->setProgress( m_progress->progress() + 1 );
+ } else {
+ m_progress->setTotalSteps( 100 );
+ m_progress->setProgress( p );
+ }
+}
+
+#include "acqprogresswidget.moc"
diff --git a/adept/libadept/acqprogresswidget.h b/adept/libadept/acqprogresswidget.h
new file mode 100644
index 0000000..54359c7
--- /dev/null
+++ b/adept/libadept/acqprogresswidget.h
@@ -0,0 +1,30 @@
+/** -*- C++ -*-
+ @file adept/acqprogresswidget.h
+ @author Peter Rockai <me@mornfall.net>
+ @todo Close button!
+*/
+
+#ifndef PROGRESSWIDGET_H
+# define PROGRESSWIDGET_H
+
+#include <adept/acqprogresswidgetui.h>
+#include <adept/acqprogress.h>
+
+namespace adept {
+
+class AcqProgressWidget : public AcqProgressWidgetUi {
+ Q_OBJECT
+public:
+ AcqProgressWidget (QWidget *parent = 0, const char *name = 0);
+ aptFront::SharedPtr<aptFront::ProgressCallback> callback() { return m_statusRef.data(); };
+public slots:
+ void statusChange( AcqStatus::Status );
+ void setProgress( int );
+protected:
+ aptFront::SharedPtr<AcqStatus> m_statusRef;
+};
+
+}
+
+#endif /* ifndef PROGRESSWIDGET_H */
+
diff --git a/adept/libadept/acqprogresswidgetui.ui b/adept/libadept/acqprogresswidgetui.ui
new file mode 100644
index 0000000..26baa21
--- /dev/null
+++ b/adept/libadept/acqprogresswidgetui.ui
@@ -0,0 +1,79 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::AcqProgressWidgetUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>adept::AcqProgressWidgetUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>705</width>
+ <height>289</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Download Progress</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::AcqStatus" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_status</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>150</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="KProgress" row="1" column="0">
+ <property name="name">
+ <cstring>m_progress</cstring>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>m_cancel</cstring>
+ </property>
+ <property name="text">
+ <string>Cancel Download</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::AcqStatus</class>
+ <header location="global">acqprogress.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/acqprogress.h</includehint>
+ <includehint>kprogress.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/actor.h b/adept/libadept/actor.h
new file mode 100644
index 0000000..115b202
--- /dev/null
+++ b/adept/libadept/actor.h
@@ -0,0 +1,43 @@
+/** -*- C++ -*-
+ @file adept/actor.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qobject.h>
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/actor.h>
+
+#ifndef EPT_ACTOR_H
+#define EPT_ACTOR_H
+
+namespace adept {
+
+using namespace aptFront;
+
+class EntityActor : public QObject
+{
+ Q_OBJECT
+public:
+ EntityActor( actor::Bound< cache::entity::Entity > a )
+ : m_actor( a ), m_dead( false )
+ {}
+ actor::Bound< cache::entity::Entity > actor() const {
+ return m_actor;
+ }
+public slots:
+ void act() { m_actor(); }
+ void destructiveAct() {
+ // in case we don't get deleted soon enough
+ if ( m_dead ) return;
+ m_dead = true;
+ act();
+ deleteLater();
+ }
+protected:
+ actor::Bound< cache::entity::Entity > m_actor;
+ bool m_dead;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/application.cpp b/adept/libadept/application.cpp
new file mode 100644
index 0000000..8388fa2
--- /dev/null
+++ b/adept/libadept/application.cpp
@@ -0,0 +1,197 @@
+/** -*- C++ -*-
+ @file adept/application.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kstatusbar.h>
+
+#include <apt-front/init.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/component/state.h>
+
+#include <adept/commitprogress.h>
+#include <adept/application.h>
+#include <adept/packageinfo.h>
+#include <adept/progress.h>
+#include <adept/utils.h>
+
+namespace adept {
+using namespace cache;
+
+/* void WaitForLister::waiting()
+{
+ kdDebug() << "WaitForLister::waiting()" << endl;
+ bool done = true;
+ for ( Vector::iterator i = listers.begin(); i != listers.end(); ++i ) {
+ if ( (*i)->busy() ) {
+ done = false;
+ break;
+ }
+ }
+ if ( listers.empty() ) done = false;
+ if ( done ) {
+ QTimer::singleShot( 0, app, slot );
+ deleteLater();
+ } else {
+ QTimer::singleShot( 100, this, SLOT( waiting() ) );
+ }
+ } */
+
+Application::Application()
+ : m_acceptReadOnly( false ), m_main( 0 ), m_history( 0 ), m_statusBar( 0 )
+{
+}
+
+void Application::openCache( unsigned flags )
+{
+ bool ro = m_acceptReadOnly;
+ bool root = ::getuid() == 0 || ::geteuid() == 0;
+ try {
+ cache::Global::get().open( flags );
+ } catch (...) {
+ try {
+ cache::Global::get().open( flags | Cache::OpenReadOnly );
+ if ( ro && root ) {
+ KMessageBox::information(
+ m_main, i18n(
+ "You will not be able to change your system settings "
+ "in any way (install, remove or upgrade software), "
+ "because another process is using the packaging system database "
+ "(probably some other Adept application or apt-get or "
+ "aptitude). Please close the other application before "
+ "using this one." ),
+ i18n( "Read Only mode: Database Locked" ) );
+ } else if ( !root && ro ) {
+ KMessageBox::information(
+ m_main, i18n(
+ "You will not be able to change your system settings "
+ "in any way (install, remove or upgrade software), "
+ "because this application needs special administrator "
+ "(root) privileges. Please run it as root or "
+ "through kdesu or sudo programs to be able to perform "
+ "these actions" ),
+ i18n( "Read Only mode: Need root privileges" ) );
+ } else if ( root && !ro ) {
+ KMessageBox::information(
+ m_main, i18n(
+ "Another process is using the packaging system database "
+ "(probably some other Adept application or apt-get or "
+ "aptitude). Please close the other application before "
+ "using this one." ),
+ i18n( "Database Locked" ) );
+ } else if ( !root && !ro ) {
+ KMessageBox::information(
+ m_main, i18n( "This application needs special administrator "
+ "(root) privileges. Please run it as root or "
+ "through kdesu or sudo programs" ),
+ i18n( "Need root privileges" ) );
+ }
+ if ( !ro ) {
+ kdDebug() << "cannot continue, exiting" << endl;
+ exit( 1 );
+ }
+ } catch (...) {
+ KMessageBox::sorry(
+ m_main, i18n(
+ "The APT Database could not be opened!"
+ " This may be caused by incorrect APT configuration"
+ " or some similar problem. Try running apt-setup and"
+ " apt-get update in terminal and see if it helps"
+ " to resolve the problem." ), i18n( "Could not open cache" ) );
+ exit( 1 );
+ }
+ }
+}
+
+void Application::initHistory() {
+ cache::Global::get().addComponent(
+ m_history = new History() );
+}
+
+void Application::initKDEDebconf()
+{
+ // xxx unhardcode the package name somehow?
+ if (cache::Global::get().packages()
+ .packageByName( "libqt-perl" ).isInstalled())
+ putenv( "DEBIAN_FRONTEND=kde" );
+}
+
+void Application::initialize()
+{
+ CommitProgress::initSystem();
+ aptFront::init();
+ openCache();
+ initKDEDebconf();
+ initHistory();
+ observeComponent< component::State >();
+}
+
+void Application::checkpoint() {
+ if ( !history() ) return;
+ setHistoryEnabled( false );
+ history()->checkpoint();
+ setHistoryEnabled( true );
+}
+
+void Application::undo() {
+ if ( !history() ) return;
+ setHistoryEnabled( false );
+ history()->undo();
+ setHistoryEnabled( true );
+}
+
+void Application::redo() {
+ if ( !history() ) return;
+ setHistoryEnabled( false );
+ history()->redo();
+ setHistoryEnabled( true );
+}
+
+QString Application::changeString() {
+ component::State &s = cache().state();
+ return i18n( " Install %1, upgrade %2, remove %3 " )
+ .arg( s.newInstallCount() ).arg( s.upgradeCount() )
+ .arg( s.removeCount() );
+}
+
+QString Application::statusString() {
+ component::State &s = cache().state();
+ return i18n( " %1 installed, %2 upgradable, %3 available " )
+ .arg( s.installedCount() ).arg( s.upgradableCount() )
+ .arg( s.availableCount() );
+}
+
+QString Application::sizesString() {
+ QString dl = cache().state().downloadSizeString();
+ QString inst = cache().state().installSizeString();
+ return i18n( " download: %1, installation: %2 " ).arg( dl ).arg( inst );
+}
+
+void Application::setStatusBar( KStatusBar *s ) {
+ m_statusBar = s;
+ if ( s ) {
+ s->message( i18n( "Initializing..." ) );
+ s->insertItem( u8( "" ), 0 );
+ s->insertItem( u8( "" ), 1 );
+ s->insertItem( u8( "" ), 2 );
+ adjustFontSize( s, -1 );
+
+ adept::Progress *pr = new adept::Progress();
+ pr->setStatusBar( s );
+ cache::Global::get().setProgress( pr );
+ }
+}
+
+void Application::notifyPostChange( component::Base * )
+{
+ if ( m_statusBar ) {
+ m_statusBar->changeItem( changeString(), 0 );
+ m_statusBar->changeItem( statusString(), 1 );
+ m_statusBar->changeItem( sizesString(), 2 );
+ }
+}
+
+}
diff --git a/adept/libadept/application.h b/adept/libadept/application.h
new file mode 100644
index 0000000..74e9506
--- /dev/null
+++ b/adept/libadept/application.h
@@ -0,0 +1,75 @@
+/** -*- C++ -*-
+ @file adept/application.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <vector>
+
+#include <qobject.h>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+
+#ifndef EPT_APPLICATION_H
+#define EPT_APPLICATION_H
+
+class KStatusBar;
+
+namespace adept {
+using namespace aptFront;
+using cache::Cache;
+
+class Lister;
+
+struct Application : cache::Observer {
+ Application();
+ void setAcceptReadOnly( bool ro ) { m_acceptReadOnly = ro; }
+ bool writeable() { return cache::Global::get().writeable(); }
+ Cache &cache() { return cache::Global::get(); }
+ void openCache( unsigned flags = Cache::OpenDefault | Cache::OpenDebtags );
+ void initialize();
+ void initKDEDebconf();
+ void initHistory();
+ void setMainWidget( QWidget *w ) { m_main = w; }
+ void setStatusBar( KStatusBar *s );
+ virtual void checkpoint();
+ virtual void undo();
+ virtual void redo();
+
+ virtual void notifyPostChange( cache::component::Base * );
+
+ QString changeString();
+ QString statusString();
+ QString sizesString();
+protected:
+ virtual void setHistoryEnabled( bool ) {}
+ typedef cache::component::History< cache::component::State > History;
+ virtual History *history() { return m_history; }
+ bool m_acceptReadOnly;
+ QWidget *m_main;
+ KStatusBar *m_statusBar;
+ History *m_history;
+};
+
+/* class WaitForLister : public QObject {
+ Q_OBJECT
+public:
+ WaitForLister( QObject *a, const char *s )
+ : obj( a ), slot( s )
+ {
+ waiting();
+ }
+ void addLister( Lister *l ) { listers.push_back( l ); }
+protected slots:
+ void waiting();
+protected:
+ QObject *obj;
+ const char *slot;
+ typedef std::vector< Lister * > Vector;
+ Vector listers;
+ }; */
+
+}
+
+#endif
diff --git a/adept/libadept/commitprogress.cpp b/adept/libadept/commitprogress.cpp
new file mode 100644
index 0000000..9100d9b
--- /dev/null
+++ b/adept/libadept/commitprogress.cpp
@@ -0,0 +1,115 @@
+#include <cassert>
+
+#include <qwidgetstack.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <kprogress.h>
+#include <qlayout.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <ktrader.h>
+#include <klibloader.h>
+
+#include <apt-front/init.h>
+#include <adept/commitprogress.h>
+#include <adept/utils.h>
+
+using namespace adept;
+using namespace aptFront;
+
+PkgSystem *CommitProgress::s_system = 0;
+
+void CommitProgress::initSystem() {
+ CommitProgress::s_system = new PkgSystem();
+}
+
+CommitProgress::CommitProgress( QWidget *p, const char *n )
+ : CommitProgressUi( p, n )
+{
+ assert( s_system );
+ m_konsoleFrame->installEventFilter( this );
+ loadKonsole();
+ connect( s_system, SIGNAL( statusChanged( int, QString ) ),
+ this, SLOT( updateProgress( int, QString ) ) );
+ connect( m_details, SIGNAL( clicked() ),
+ this, SLOT( toggleDetails() ) );
+ m_progress->setTotalSteps( 100 );
+}
+
+bool CommitProgress::eventFilter( QObject *o, QEvent *e ) {
+ // o == m_konsoleFrame
+ if ( e->type() == QEvent::Resize ) {
+ QResizeEvent *re = dynamic_cast< QResizeEvent * >( e );
+ if ( !re ) return false;
+ m_konsole->widget()->setGeometry( 0, 0, re->size().width(), re->size().height() );
+ m_occlude->setGeometry( 0, 0, re->size().width(), re->size().height() );
+ }
+ return false;
+};
+
+void CommitProgress::toggleDetails()
+{
+ if ( !m_occlude->isVisible() ) {
+ // if ( m_stack->visibleWidget() == m_konsole->widget() ) { // hide
+ // m_stack->raiseWidget( m_emptyPage );
+ m_occlude->show();
+ m_bottomSpace->changeSize( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding );
+ m_details->setText( i18n( "Show Details" ) );
+ } else { // show
+ m_occlude->hide();
+ // m_stack->raiseWidget( m_konsole->widget() );
+ m_bottomSpace->changeSize( 10, 10, QSizePolicy::Fixed, QSizePolicy::Fixed );
+ m_details->setText( i18n( "Hide Details" ) );
+ }
+}
+
+void CommitProgress::updateProgress( int p, QString msg )
+{
+ m_operation->setText( msg );
+ m_progress->setProgress( p );
+}
+
+void CommitProgress::loadKonsole()
+{
+ if ( s_system->terminal() )
+ kdDebug() << "WARNING: Hijacking PkgSystem terminal" << endl;
+
+ KLibFactory* factory = KLibLoader::self()->factory( "libsanekonsolepart" );
+ if (!factory)
+ factory = KLibLoader::self()->factory( "libkonsolepart" );
+
+ assert( factory );
+
+ delete m_occlude;
+ m_konsole = static_cast<KParts::Part*>(
+ factory->create( m_konsoleFrame, "konsolepart", "QObject",
+ u8( "KParts::ReadOnlyPart" ) ) );
+ // m_konsole->widget()->setGeometry( QRect( 0, 0, 40, 40 ) );
+
+ m_occlude = new QFrame( m_konsoleFrame, "m_occlude" );
+ // m_occlude->setGeometry( QRect( 0, 0, 10, 10 ) );
+ m_occlude->setFrameShape( QFrame::NoFrame );
+
+ assert( terminal() );
+
+ terminal()->setAutoDestroy( false );
+ terminal()->setAutoStartShell( false );
+ // m_stack->addWidget( m_konsole->widget() );
+
+ QStrList l; l.append( "echo" ); l.append( "-n" );
+ terminal()->startProgram( u8( "/bin/echo" ), l );
+
+ s_system->setTerminal( m_konsole );
+
+ // m_stack->raiseWidget( m_konsole->widget() );
+ // m_konsole->widget()->show();
+ // m_stack->raiseWidget( m_emptyPage );
+ m_operation->setText( i18n( "Idle" ) );
+ QTimer::singleShot( 0, this, SLOT( toggleDetails() ) );
+ if ( DEFAULT_KONSOLE_HIDDEN )
+ QTimer::singleShot( 0, this, SLOT( toggleDetails() ) );
+ QTimer::singleShot( 0, this, SLOT( hide() ) );
+}
+
diff --git a/adept/libadept/commitprogress.h b/adept/libadept/commitprogress.h
new file mode 100644
index 0000000..ed557d7
--- /dev/null
+++ b/adept/libadept/commitprogress.h
@@ -0,0 +1,41 @@
+/* -*- C++ -*- file adept/commitprogress.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <kde_terminal_interface.h>
+#include <adept/dpkgpm-gui.h>
+#include <adept/commitprogressui.h>
+#include <kparts/part.h>
+
+#ifndef EPT_COMMITPROGRESS_H
+#define EPT_COMMITPROGRESS_H
+
+namespace adept {
+
+class CommitProgress : public CommitProgressUi
+{
+ Q_OBJECT
+public:
+ CommitProgress( QWidget *p = 0, const char *n = 0 );
+
+ ExtTerminalInterface *terminal() {
+ return static_cast<ExtTerminalInterface*>(
+ m_konsole->qt_cast( "ExtTerminalInterface" ) );
+ }
+
+ // needs to be called before aptFront::init() :'((
+ static void initSystem();
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+public slots:
+ void updateProgress( int p, QString msg );
+ void toggleDetails();
+protected:
+ void loadKonsole();
+ KParts::Part *m_konsole;
+ static adept::PkgSystem *s_system; // bla...
+};
+
+}
+
+
+#endif
diff --git a/adept/libadept/commitprogressui.ui b/adept/libadept/commitprogressui.ui
new file mode 100644
index 0000000..5ccecbf
--- /dev/null
+++ b/adept/libadept/commitprogressui.ui
@@ -0,0 +1,197 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::CommitProgressUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CommitProgressUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>542</width>
+ <height>303</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>1</number>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>m_konsoleFrame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>m_occlude</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>40</x>
+ <y>10</y>
+ <width>460</width>
+ <height>60</height>
+ </rect>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ </widget>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>m_details</cstring>
+ </property>
+ <property name="text">
+ <string>(details)</string>
+ </property>
+ </widget>
+ <widget class="KProgress" row="1" column="0">
+ <property name="name">
+ <cstring>m_progress</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_operation</cstring>
+ </property>
+ <property name="text">
+ <string>Preparing...</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>m_bottomSpace</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>80</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>32</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kprogress.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/desktopentryui.ui b/adept/libadept/desktopentryui.ui
new file mode 100644
index 0000000..a40c766
--- /dev/null
+++ b/adept/libadept/desktopentryui.ui
@@ -0,0 +1,116 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::DesktopEntryUi</class>
+<widget class="adept::ItemExtender">
+ <property name="name">
+ <cstring>DesktopEntryUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>509</width>
+ <height>52</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>6</number>
+ </property>
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <widget class="QLabel" row="0" column="1" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>m_icon</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>m_check</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="3">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="text">
+ <string>(name)</string>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="3">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="text">
+ <string>(description)</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer row="0" column="2" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>6</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/extendablelist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/libadept/desktoplist.cpp b/adept/libadept/desktoplist.cpp
new file mode 100644
index 0000000..de64f11
--- /dev/null
+++ b/adept/libadept/desktoplist.cpp
@@ -0,0 +1,194 @@
+/** -*- C++ -*-
+ @file adept/desktoplist.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qimage.h>
+#include <qlabel.h>
+#include <qcursor.h>
+#include <qcheckbox.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <adept/desktoplist.h>
+#include <adept/utils.h>
+
+namespace adept {
+
+DesktopEntry::DesktopEntry( QWidget *p, const char *n )
+ : DesktopEntryUi( p, n )
+{
+ adjustFontSize( m_description, -1 );
+}
+
+void DesktopEntry::resize( int w, int h )
+{
+ // kdDebug() << "DesktopEntry::resize( " << w << ", " << h << " )" << endl;
+ int margin = layout()->margin() + layout()->spacing() * 2
+ + 6 /* spacer */ + m_icon->width() + m_check->width();
+ if ( m_check->isVisible() ) margin += m_check->width() + layout()->spacing();
+ int hFW1 = m_name->heightForWidth( w - margin );
+ int hFW2 = m_description->heightForWidth( w - margin );
+ /* kdDebug() << "margin = " << margin << ", hFW1 = " << hFW1 << ", hFW2 = "
+ << hFW2 << endl; */
+ int height = 2 * layout()->margin() + layout()->spacing() + hFW1 + hFW2;
+ if ( height < 32 + 2*layout()->margin() /* icon size + margin */ )
+ height = 32 + 2*layout()->margin();
+ // m_description->resize( w - margin, m_description->heightForWidth( w - margin ) );
+ QWidget::resize( w, height );
+}
+
+void DesktopEntry::setItem( ExtendableItem *i ) {
+ m_polished = false;
+ ItemExtender::setItem( i );
+ m_name->setText( u8( "<b>" ) + u8( entity().name() ) + u8( "</b>" ) );
+ m_description->setText( u8( entity().description() ) );
+ if ( !item()->list()->displayCheckboxes() ) {
+ m_check->hide();
+ }
+ if ( !package().valid() || !package().hasVersion() ) {
+ setEnabled( false );
+ } else {
+ connect( m_check, SIGNAL( toggled( bool ) ),
+ this, SLOT( toggled() ) );
+ notifyPostChange();
+ }
+}
+
+void DesktopEntry::mousePressEvent( QMouseEvent *e ) {
+ kdDebug() << "DesktopEntry::mousePressEvent" << endl;
+ e->ignore();
+}
+
+void DesktopEntry::mouseReleaseEvent( QMouseEvent *e ) {
+ kdDebug() << "DesktopEntry::mouseReleaseEvent" << endl;
+ e->ignore();
+}
+
+void DesktopEntry::showEvent( QShowEvent *e ) {
+ DesktopEntryUi::showEvent( e );
+ // DesktopEntryUi::polish();
+ if ( m_polished ) return;
+ item()->list()->polishing();
+ kdDebug() << "polish for " << entity().name() << endl;
+ QImage icon( KGlobal::iconLoader()->iconPath( entity().icon(), -32, true ) );
+ if ( icon.isNull() ) {
+ icon = QImage( KGlobal::dirs()->findResource( "desktopicon", entity().icon() ) );
+ }
+ m_icon->setPixmap( icon.isNull() ? item()->list()->emptyIcon() :
+ QPixmap( icon.smoothScale( 32, 32, QImage::ScaleMin ) ) );
+ item()->list()->polished();
+ m_polished = true;
+}
+
+void DesktopEntry::toggled() {
+ /* if ( package().isInstalled() ) {
+ if ( package().markedRemove() )
+ package().markKeep();
+ else
+ package().markRemove();
+ } else if ( package().markedInstall() )
+ package().markKeep();
+ else
+ package().markInstall(); */
+
+ if ( package().isInstalled() ) {
+ if ( package().markedRemove() )
+ item()->list()->fireRequest( package(), component::State::AKeep );
+ else
+ item()->list()->fireRequest( package(), component::State::ARemove );
+ } else if ( package().markedInstall() )
+ item()->list()->fireRequest( package(), component::State::AKeep );
+ else
+ item()->list()->fireRequest( package(), component::State::AInstall );
+ notifyPostChange();
+}
+
+void DesktopList::polishing() {
+ if ( m_polishing == 0 )
+ QApplication::setOverrideCursor( QCursor( Qt::BusyCursor ) );
+ m_polishing++;
+ if ( m_polishing % 10 == 0 )
+ kapp->processEvents();
+}
+
+void DesktopList::polished() {
+ if ( m_polishing == childCount() )
+ QApplication::restoreOverrideCursor();
+}
+
+void DesktopList::notifyPostChange( component::Base * ) {
+ utils::Range< ExtendableItem * > r = extenders();
+ for ( ; r != r.end(); ++r ) {
+ dynamic_cast< DesktopEntry * >( (*r)->extender() )->notifyPostChange();
+ }
+}
+
+void DesktopEntry::notifyPostChange() {
+ if ( !package().valid() || !package().hasVersion() )
+ return;
+
+ m_check->blockSignals( true );
+ m_check->setChecked( ( package().isInstalled()
+ || entity().package().markedInstall() )
+ && !entity().package().markedRemove() );
+ m_check->blockSignals( false );
+}
+
+DesktopList::DesktopList( QWidget *parent, const char *name )
+ : ExtendableList( parent, name ), m_polishing( 0 ), m_displayCheckboxes( true )
+{
+ observeComponent< component::State >();
+ addColumn( i18n( "Application" ) );
+ setResizeMode( LastColumn );
+ setToggleColumn( -1 ); // no toggling, thanks
+ setExtenderHighlight( true );
+ m_emptyIcon = QPixmap(
+ QImage(
+ KGlobal::iconLoader()->iconPath( u8( "exec" ), -32, false )
+ ).smoothScale( 32, 32, QImage::ScaleMin ) );
+ connect( this, SIGNAL( clicked( QListViewItem *, const QPoint &, int ) ),
+ this, SLOT( processClick( QListViewItem *, const QPoint &, int ) ) );
+}
+
+void DesktopList::processClick( QListViewItem *it, const QPoint &, int ) {
+ kdDebug() << "DesktopList::processClick..." << endl;
+ DesktopItem *i = dynamic_cast< DesktopItem * >( it );
+ if ( !i ) return;
+ emit showDescription( i->entity() );
+}
+
+void DesktopList::insertRange( Range r ) {
+ m_range = r;
+ DesktopItem *last = 0;
+ int i = 0;
+ QApplication::setOverrideCursor( QCursor( Qt::BusyCursor ) );
+ for( ; r != r.end(); r.advance() ) {
+ if ( i % 20 == 0 )
+ kapp->processEvents();
+ if ( !r->package( entity::Package() ).valid() )
+ continue;
+ DesktopItem *i = last ? new DesktopItem( this, last ) : new DesktopItem( this );
+ last = i;
+ i->setEntity( *r );
+ ++ i;
+ }
+ QApplication::restoreOverrideCursor();
+}
+
+ItemExtender *DesktopItem::createExtender() {
+ return new DesktopEntry();
+}
+
+DesktopItem *DesktopEntry::item() const {
+ return dynamic_cast< DesktopItem * >( m_item );
+}
+
+entity::Desktop DesktopEntry::entity() const {
+ return item()->entity();
+}
+
+}
diff --git a/adept/libadept/desktoplist.h b/adept/libadept/desktoplist.h
new file mode 100644
index 0000000..207b9a7
--- /dev/null
+++ b/adept/libadept/desktoplist.h
@@ -0,0 +1,117 @@
+/** -*- C++ -*-
+ @file adept/desktoplist.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qimage.h>
+#include <klocale.h>
+
+#include <apt-front/cache/entity/desktop.h>
+#include <adept/extendablelist.h>
+#include <adept/desktopentryui.h>
+
+#ifndef EPT_DESKTOPLIST_H
+#define EPT_DESKTOPLIST_H
+
+class QPopupMenu;
+
+namespace adept {
+using namespace aptFront;
+using namespace aptFront::cache;
+
+class DesktopItem;
+
+class DesktopList : public ExtendableList, public cache::Observer
+{
+ Q_OBJECT
+public:
+ typedef utils::Range< entity::Desktop > Range;
+ DesktopList( QWidget *parent = 0, const char *name = 0 );
+ void insertRange( Range );
+ QPixmap emptyIcon() { return m_emptyIcon; }
+ void polishing();
+ void polished();
+
+ void setTitle( QString s ) {
+ setColumnText( 0, i18n( "Application (" ) + s + i18n( ")" ) );
+ }
+
+ void setDisplayCheckboxes( bool d ) { m_displayCheckboxes = d; }
+ bool displayCheckboxes() { return m_displayCheckboxes; }
+ virtual void notifyPostChange( cache::component::Base * );
+ void fireRequest( entity::Package p, component::State::Action a ) {
+ emit request( p, a );
+ }
+protected slots:
+ void processClick( QListViewItem *, const QPoint &, int );
+signals:
+ void request( cache::entity::Package, cache::component::State::Action );
+ void showDescription( cache::entity::Desktop );
+protected:
+ Range m_range;
+ QPixmap m_emptyIcon;
+ int m_polishing;
+ bool m_displayCheckboxes;
+};
+
+class DesktopEntry : public DesktopEntryUi
+{
+ Q_OBJECT
+public:
+ DesktopEntry( QWidget * = 0, const char * = 0 );
+ DesktopItem *item() const;
+ entity::Desktop entity() const;
+ void setItem( ExtendableItem * );
+ entity::Package package() { return entity().package(); }
+ virtual void notifyPostChange();
+ virtual void resize( int, int );
+ // virtual void polish();
+public slots:
+ void toggled();
+protected:
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent *e );
+ virtual void showEvent( QShowEvent * );
+ bool m_polished;
+};
+
+class DesktopItem : public ExtendableItem
+{
+public:
+ ItemExtender *createExtender();
+ DesktopItem( DesktopList *l )
+ : ExtendableItem( l ), m_delayedDone( false )
+ {
+ }
+ DesktopItem( DesktopList *v, DesktopItem *i )
+ : ExtendableItem( v, i ), m_delayedDone( false )
+ {
+ }
+
+ void setup() {
+ ExtendableItem::setup();
+ if (m_delayedDone)
+ return;
+ m_delayedDone = true;
+ showExtender();
+ }
+
+ DesktopList *list() { return dynamic_cast< DesktopList * >( listView() ); }
+
+ QString text( int ) const { return QString( "you shouldn't see this" ); }
+ entity::Desktop entity() const { return m_entity; }
+ void setEntity( entity::Desktop e ) { m_entity = e; }
+
+ virtual bool less( const ExtendableItem *other ) const {
+ const DesktopItem *o = dynamic_cast< const DesktopItem * >( other );
+ return entity() < o->entity();
+ }
+
+protected:
+ entity::Desktop m_entity;
+ bool m_delayedDone:1;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/dpkgpm-gui.cpp b/adept/libadept/dpkgpm-gui.cpp
new file mode 100644
index 0000000..828d18f
--- /dev/null
+++ b/adept/libadept/dpkgpm-gui.cpp
@@ -0,0 +1,258 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm-gui.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <fcntl.h>
+#include <iostream>
+
+#include <qstrlist.h>
+#include <kapplication.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <kparts/part.h>
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/entity/package.h>
+
+#include <adept/dpkgpm-gui.h>
+#include <adept/utils.h>
+
+using namespace aptFront;
+using namespace cache;
+
+namespace adept {
+
+PkgSystem::PkgSystem()
+ : m_terminalPart( 0 )
+{
+ std::cerr << "kapture::PkgSystem::PkgSystem()" << std::endl;
+ Label = "adeptDPkgSystem";
+}
+
+void PkgSystem::setTerminal( KParts::Part *t )
+{
+ m_terminalPart = t;
+}
+
+pkgPackageManager *PkgSystem::CreatePM( pkgDepCache *c ) const
+{
+ std::cerr << "kapture::PkgSystem::CreatePM()" << std::endl;
+ adept::DPkgPM *pm = new adept::DPkgPM( c, m_terminalPart );
+ connect( pm, SIGNAL( statusChanged( int, QString ) ),
+ this, SIGNAL( statusChanged( int, QString ) ) );
+ return pm;
+}
+
+DPkgPM::DPkgPM( pkgDepCache *cache, KParts::Part *t )
+ : aptFront::DPkgPM (cache), m_terminalPart (t)
+{
+}
+
+bool DPkgPM::forkDpkg( char *const argv[] )
+{
+ bool ok = true;
+ std::cerr << "adept::DPkgPM::forkDpkg ()" << std::endl;
+ QStrList l;
+ for (int i = 0; argv[i]; i ++)
+ l.append( argv[i] );
+
+ m_processRunning = true;
+ connect( m_terminalPart, SIGNAL( processExited( KProcess * ) ),
+ this, SLOT( processExit( KProcess * ) ) );
+ connect( m_terminalPart, SIGNAL( processExited( const KProcess * ) ),
+ this, SLOT( processExitC( const KProcess * ) ) );
+ connect( m_terminalPart, SIGNAL( forkedChild() ),
+ this, SLOT( setupDpkgChild() ) );
+
+ terminal()->startProgram( u8( argv[0] ), l );
+
+ ::close( m_dpkgPipe[1] );
+ ::fcntl( m_dpkgPipe[0], F_SETFL, O_NONBLOCK );
+
+ while (m_processRunning) {
+ dpkgMonitor();
+ usleep( 50000 );
+ }
+
+ if (m_exitedProcess->normalExit()) {
+ if (m_exitedProcess->exitStatus() != 0) {
+ ok = _error->Error( "Child for %s exited with error %d",
+ argv [0], m_exitedProcess->exitStatus());
+ }
+ } else {
+ ok = _error->Error( "Child for %s was killed by signal %d",
+ argv [0], m_exitedProcess->exitSignal());
+ }
+
+ if (ok) // do we run scripts in case dpkg died???
+ ok = runScripts ("DPkg::Post-Invoke", false);
+
+ return ok;
+}
+
+ExtTerminalInterface *DPkgPM::terminal() {
+ return static_cast<ExtTerminalInterface *>(
+ m_terminalPart->qt_cast( "ExtTerminalInterface" ) );
+}
+
+bool DPkgPM::forkScript (const char *cmd, bool fP)
+{
+ std::cerr << "adept::DPkgPM::forkScript(\"" << cmd << "\")" << std::endl;
+ if (fP) {
+ if (pipe( m_scriptPipe ) != 0)
+ return _error->Errno(
+ "pipe","Failed to create IPC pipe to subprocess");
+ SetCloseExec (m_scriptPipe[0], true);
+ SetCloseExec (m_scriptPipe[1], true);
+ }
+ QStrList l;
+ l.append ("/bin/sh");
+ l.append ("-c");
+ l.append (cmd);
+ if (fP) {
+ connect( m_terminalPart, SIGNAL( forkedChild() ),
+ this, SLOT( setupScriptPipe() ) );
+ }
+
+ connect( m_terminalPart, SIGNAL( processExited( KProcess * ) ),
+ this, SLOT( processExit( KProcess * ) ) );
+ connect( m_terminalPart, SIGNAL( processExited( const KProcess * ) ),
+ this, SLOT( processExitC( const KProcess * ) ) );
+
+ m_processRunning = true;
+ terminal()->startProgram( u8( "/bin/sh" ), l);
+
+ if (fP) {
+ if (!feedPackages())
+ return _error->Error("Failed feeding packages to script");
+ }
+
+ while (m_processRunning) {
+ kapp->processEvents();
+ usleep(50000);
+ }
+
+ std::cerr << "END: adept::DPkgPM::forkScript(\""
+ << cmd << "\")" << std::endl;
+
+ if (m_exitedProcess->normalExit()) {
+ if (m_exitedProcess->exitStatus() != 0) {
+ return _error -> Error("Child for %s exited with error %d",
+ cmd, m_exitedProcess->exitStatus());
+ } else {
+ return true;
+ }
+ } else {
+ return _error->Error("Child for %s was killed by signal %d",
+ cmd, m_exitedProcess->exitSignal());
+ }
+}
+
+void DPkgPM::processExit(KProcess *p) {
+ processExitC( p );
+}
+
+void DPkgPM::processExitC(const KProcess *p)
+{
+ std::cerr << "a process exited!" << std::endl;
+ m_processRunning = false;
+ m_exitedProcess = p;
+}
+
+void DPkgPM::setupScriptPipe()
+{
+ // setupScript();
+ // std::cerr << "setupScriptPipe()" << std::endl;
+ dup2 (m_scriptPipe[0], STDIN_FILENO);
+}
+
+void DPkgPM::setupDpkgChild()
+{
+ // setupScript();
+ // std::cerr << "setupDpkgChild()" << std::endl;
+ setupChild();
+}
+
+bool DPkgPM::Go( int )
+{
+ std::cerr << "kapture::DPkgPM::Go ()" << std::endl;
+ statusChanged( 0, i18n( "Preparing..." ) );
+ bool ret = aptFront::DPkgPM::Go(-1);
+ QStrList l;
+ l.append("echo");
+ l.append("dpkg run finished!");
+ terminal()->startProgram( u8( "echo" ), l );
+ statusChanged( 100, i18n( "Done" ) );
+ return ret;
+}
+
+void DPkgPM::dpkgMonitor ()
+{
+ aptFront::DPkgPM::dpkgMonitor();
+ kapp->processEvents();
+}
+
+void DPkgPM::updateStatus( std::string pkg, std::string ev, std::string r )
+{
+ std::string op, msg;
+ aptFront::DPkgPM::updateStatus( pkg, ev, r );
+ entity::Package p = cache::Global::get().packages().packageByName( pkg );
+
+ if ( m_currentOp == OInstall ) {
+ if ( p.markedNewInstall() ) {
+ if ( ev == "half-installed" )
+ msg = u8( i18n( "Preparing installation of %1..." ) );
+ else if ( ev == "unpacked" )
+ msg = u8( i18n( "Unpacking %1..." ) );
+ } else if ( p.markedUpgrade() ) {
+ if ( ev == "half-installed" )
+ msg = u8( i18n( "Preparing upgrade of %1..." ) );
+ else if ( ev == "unpacked" || ev == "half-configured" )
+ msg = u8( i18n( "Replacing %1 with new version..." ) );
+ }
+ } else if ( m_currentOp == OConfigure ) {
+ if ( p.markedNewInstall() ) {
+ if ( ev == "unpacked" )
+ msg = u8( i18n( "Preparing to configure %1..." ) );
+ else if ( ev == "half-configured" )
+ msg = u8( i18n( "Configuring %1..." ) );
+ else if ( ev == "installed" )
+ msg = u8( i18n( "Installed %1" ) );
+ } else if ( p.markedUpgrade() ) {
+ if ( ev == "unpacked" )
+ msg = u8( i18n( "Preparing to configure new version of %1..." ) );
+ else if ( ev == "half-configured" )
+ msg = u8( i18n( "Configuring new version of %1..." ) );
+ else if ( ev == "installed" )
+ msg = u8( i18n( "Upgraded %1" ) );
+ }
+ } else if ( m_currentOp == ORemove ) {
+ if ( ev == "installed" )
+ msg = u8( i18n( "Preparing to remove %1..." ) );
+ else if ( ev == "half-configured" || ev == "half-installed" )
+ msg = u8( i18n( "Removing %1..." ) );
+ else if ( ev == "config-files" || ev == "not-installed" )
+ msg = u8( i18n( "Removed %1" ) );
+ } else if ( m_currentOp == OPurge ) {
+ if ( ev == "config-files" )
+ msg = u8( i18n( "Preparing to purge %1..." ) );
+ else if ( ev == "not-installed" )
+ msg = u8( i18n( "Purged %1" ) );
+ }
+
+ std::cerr << "updateStatus( " << pkg << ", " << ev << ", " << r << ")" << std::endl;
+ std::cerr << "updateStatus: msg = " << msg << std::endl;
+ std::cerr << "updateStatus: seen = " << m_seenOpCount
+ << ", total = " << m_totalOpCount << std::endl;
+ statusChanged( ( m_seenOpCount * 100 ) / m_totalOpCount,
+ u8( msg ).arg( pkg ) + ( ( r == "") ? "" : (" (" + r + ")") ) );
+}
+
+}
+
+#include "dpkgpm-gui.moc"
diff --git a/adept/libadept/dpkgpm-gui.h b/adept/libadept/dpkgpm-gui.h
new file mode 100644
index 0000000..435ee7f
--- /dev/null
+++ b/adept/libadept/dpkgpm-gui.h
@@ -0,0 +1,68 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm-gui.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#ifndef EPT_DPKGPM_H
+# define EPT_DPKGPM_H
+
+#include <apt-pkg/debsystem.h>
+#include <adept/dpkgpm.h>
+#include <kde_terminal_interface.h>
+#include <kprocess.h>
+#include <kdialogbase.h>
+
+class KListBox;
+namespace KParts {
+class Part;
+}
+
+namespace adept {
+
+class PkgSystem : public QObject, public debSystem
+{
+ Q_OBJECT
+public:
+ PkgSystem ();
+ virtual pkgPackageManager *CreatePM( pkgDepCache *Cache ) const;
+ virtual void setTerminal( KParts::Part *t );
+ KParts::Part *terminal() { return m_terminalPart; }
+ virtual int Score( Configuration const &Cnf ) {
+ return debSystem::Score (Cnf) + 2; };
+protected:
+ KParts::Part *m_terminalPart;
+signals:
+ void statusChanged( int p, QString m );
+};
+
+class DPkgPM : public QObject, public aptFront::DPkgPM
+{
+ Q_OBJECT
+public:
+ DPkgPM (pkgDepCache *c, KParts::Part *t);
+ virtual bool forkDpkg (char *const argv[]);
+ virtual void dpkgMonitor (void);
+ virtual bool Go (int);
+ virtual bool forkScript (const char *, bool);
+ ExtTerminalInterface *terminal();
+ virtual void updateStatus( std::string pkg, std::string ev, std::string r );
+
+public slots:
+ void processExitC(const KProcess *p);
+ void processExit(KProcess *p);
+ void setupScriptPipe();
+ void setupDpkgChild();
+
+signals:
+ void statusChanged( int p, QString m );
+
+protected:
+ KParts::Part *m_terminalPart;
+ // DPkgProgress *m_prog;
+ bool m_processRunning:1;
+ const KProcess *m_exitedProcess;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/dpkgpm.cpp b/adept/libadept/dpkgpm.cpp
new file mode 100644
index 0000000..b38b5fb
--- /dev/null
+++ b/adept/libadept/dpkgpm.cpp
@@ -0,0 +1,451 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include "dpkgpm.h"
+#include <signal.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/entity/package.h>
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+using namespace aptFront;
+using namespace cache;
+
+/* === PkgSystem === */
+DPkgPM::DPkgPM (pkgDepCache *C)
+ : pkgDPkgPM (C), m_seenOpCount( 0 ), m_totalOpCount( 0 )
+{
+}
+
+bool DPkgPM::Go( int )
+{
+ cerr << "DPkgPM::Go()" << endl;
+ computeTotals();
+ if (runScripts ("DPkg::Pre-Invoke", false) == false)
+ return false;
+ if (runScripts ("DPkg::Pre-Install-Pkgs", true) == false)
+ return false;
+
+ for (vector<Item>::iterator I = List.begin(); I != List.end();) {
+ char *const *argv;
+ if (! setupArgs (&argv, I))
+ return false;
+
+ cerr << "running '";
+ for (unsigned int k = 0; argv [k]; k++)
+ cerr << argv[k] << ' ';
+ cerr << "'" << endl;
+ if (_config->FindB("Debug::pkgDPkgPM",false) == true)
+ {
+ for (unsigned int k = 0; argv [k]; k++)
+ cerr << argv[k] << ' ';
+ cerr << endl;
+ continue;
+ }
+
+ if (! forkDpkg (argv))
+ return false;
+ delete[] argv;
+ if (! runScripts ("DPkg::Post-Invoke", false))
+ return false;
+ }
+ return true;
+}
+
+void DPkgPM::computeTotals()
+{
+ m_totalOpCount = 0;
+ for (vector<Item>::iterator I = List.begin(); I != List.end();I++)
+ {
+ entity::Package p = cache::Global::get().packages().packageByName(
+ I->Pkg.Name() );
+ int x = 0;
+ switch ( I->Op ) {
+ case Item::Remove: x = 4; break;
+ case Item::Install: p.markedUpgrade() ? x = 3 : x = 2; break;
+ case Item::Purge: x = 2; break;
+ case Item::Configure: x = 3; break;
+ }
+ m_totalOpCount += x;
+ }
+}
+
+bool DPkgPM::forkDpkg (char *const argv[])
+{
+ cerr << "DPkgPM::forkDpkg ()" << endl;
+ cout << flush;
+ clog << flush;
+ cerr << flush;
+
+ /* Mask off sig int/quit. We do this because dpkg also does when
+ it forks scripts. What happens is that when you hit ctrl-c it sends
+ it to all processes in the group. Since dpkg ignores the signal
+ it doesn't die but we do! So we must also ignore it */
+ sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN);
+ sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
+
+ // Fork dpkg
+ pid_t Child = ExecFork();
+ if (Child == 0) {
+ if (! setupChild ()) {
+ cerr << "Error in dpkg post-fork setup!" << endl;
+ _exit (100);
+ }
+ execvp (argv [0], argv);
+ cerr << "Error executing dpkg!" << endl;
+ _exit (100);
+ }
+
+ close( m_dpkgPipe[1] );
+ fcntl( m_dpkgPipe[0], F_SETFL, O_NONBLOCK );
+
+ int Status = 0;
+ int ret = 0;
+ while ((ret = waitpid (Child, &Status, WNOHANG)) != Child) {
+ if (errno == EINTR || ret == 0) {
+ dpkgMonitor ();
+ usleep (200000); // 0.2 second hang
+ continue;
+ }
+ runScripts ("DPkg::Post-Invoke", false);
+
+ signal(SIGQUIT,old_SIGQUIT);
+ signal(SIGINT,old_SIGINT);
+ return _error -> Errno ("waitpid","Couldn't wait for subprocess");
+ }
+
+ signal(SIGQUIT,old_SIGQUIT);
+ signal(SIGINT,old_SIGINT);
+
+ // Check for an error code.
+ if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
+ {
+ runScripts ("DPkg::Post-Invoke", false);
+ if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
+ return _error->Error("Sub-process %s received a segmentation fault.", argv [0]);
+
+ if (WIFEXITED(Status) != 0)
+ return _error->Error("Sub-process %s returned an error code (%u)", argv[0], WEXITSTATUS(Status));
+
+ return _error->Error("Sub-process %s exited unexpectedly", argv[0]);
+ }
+
+ return true;
+}
+
+bool DPkgPM::setupArgs (char *const**a, std::vector<Item>::iterator &I)
+{
+ cerr << "DPkgPM::setupArgs ()" << endl;
+ unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",350);
+ unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",8192);
+
+ vector<Item>::iterator J = I;
+ for (; J != List.end() && J->Op == I->Op; J++);
+
+ // Generate the argument list
+ const char **Args = new const char *[MaxArgs + 50];
+ if (J - I > (signed)MaxArgs)
+ J = I + MaxArgs;
+
+ unsigned int n = 0;
+ unsigned long Size = 0;
+ string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
+ Args[n++] = Tmp.c_str();
+ Size += strlen(Args[n-1]);
+
+ // Stick in any custom dpkg options
+ Configuration::Item const *Opts = _config->Tree("DPkg::Options");
+ if (Opts != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ Args[n++] = Opts->Value.c_str();
+ Size += Opts->Value.length();
+ }
+ }
+
+ pipe( m_dpkgPipe );
+ stringstream fds;
+ fds << m_dpkgPipe[1];
+ std::cerr << "reading end of the pipe: " << m_dpkgPipe[0] << std::endl;
+
+ Args[n++] = "--status-fd";
+ Size += strlen(Args[n-1]);
+ // bah, we leak a string every time we run dpkg... silly eh
+ Args[n++] = ( new string( fds.str() ) )->c_str();
+ Size += strlen(Args[n-1]);
+
+ switch (I->Op)
+ {
+ case Item::Remove:
+ Args[n++] = "--force-depends";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--force-remove-essential";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--remove";
+ Size += strlen(Args[n-1]);
+ m_currentOp = ORemove;
+ break;
+
+ case Item::Purge:
+ Args[n++] = "--force-depends";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--force-remove-essential";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--purge";
+ Size += strlen(Args[n-1]);
+ m_currentOp = OPurge;
+ break;
+
+ case Item::Configure:
+ Args[n++] = "--configure";
+ Size += strlen(Args[n-1]);
+ m_currentOp = OConfigure;
+ break;
+
+ case Item::Install:
+ Args[n++] = "--unpack";
+ Size += strlen(Args[n-1]);
+ m_currentOp = OInstall;
+ break;
+ }
+
+ // Write in the file or package names
+ if (I->Op == Item::Install)
+ {
+ for (;I != J && Size < MaxArgBytes; I++)
+ {
+ if (I->File[0] != '/')
+ return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str());
+ Args[n++] = I->File.c_str();
+ Size += strlen(Args[n-1]);
+ }
+ }
+ else
+ {
+ for (;I != J && Size < MaxArgBytes; I++)
+ {
+ Args[n++] = I->Pkg.Name();
+ Size += strlen(Args[n-1]);
+ }
+ }
+ Args[n] = 0;
+ J = I;
+ *a = (char *const *)Args;
+ return true;
+}
+
+bool DPkgPM::setupChild ()
+{
+ // cerr << "DPkgPM::setupChild ()" << endl;
+ if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
+ return false;
+
+ if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO))
+ {
+ int Flags,dummy;
+ if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
+ return false;
+
+ // Discard everything in stdin before forking dpkg
+ if (fcntl(STDIN_FILENO,F_SETFL,Flags | O_NONBLOCK) < 0)
+ return false;
+
+ while (read(STDIN_FILENO,&dummy,1) == 1);
+
+ if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
+ return false;
+ }
+
+ /* No Job Control Stop Env is a magic dpkg var that prevents it
+ from using sigstop */
+ putenv("DPKG_NO_TSTP=yes");
+ close( m_dpkgPipe[0] );
+
+ return true;
+}
+
+void DPkgPM::dpkgMonitor ()
+{
+ char buf[1024];
+ int r = read( m_dpkgPipe[0], buf, 1023 );
+
+ if ( r > 0 ) {
+ buf[r] = 0;
+ std::string b( buf );
+
+ // parse status updates from dpkg
+ while ( true ) {
+ std::string::size_type colon, nl = b.find( '\n' );
+ m_statusBuffer.append( string( b, 0, nl ) );
+ if ( nl == std::string::npos )
+ break;
+
+ // cerr << "dpkg status completed line: " << m_statusBuffer << endl;
+ colon = m_statusBuffer.find( ": " );
+ string l( m_statusBuffer, 0, colon );
+ string r( m_statusBuffer, colon + 2, string::npos );
+
+ if ( l == "status" ) {
+ colon = r.find( ": " );
+ std::string p( r, 0, colon );
+ r = string( r, colon + 2, string::npos );
+
+ colon = r.find( ": " );
+ std::string e( r, 0, colon );
+ if ( colon == string::npos )
+ r = "";
+ else
+ r = string( r, colon + 2, string::npos );
+ updateStatus( p, e, r );
+ }
+
+ b = string( b, nl + 1, string::npos );
+ m_statusBuffer = string();
+ nl = b.find( '\n' );
+ }
+ }
+}
+
+void DPkgPM::updateStatus( std::string pkg, std::string ev, std::string r )
+{
+ OpAndStatus os = std::make_pair( m_currentOp, ev );
+ if ( m_seenOps[ std::make_pair( os, pkg ) ] == 0 ) {
+ m_seenOpCount++;
+ m_seenOps[ std::make_pair( os, pkg ) ] = 1;
+ }
+}
+
+bool DPkgPM::runScripts (const char *Cnf, bool sP)
+{
+ cerr << "DPkgPM::runScripts ('" << Cnf << "', " << sP << ")" << endl;
+ Configuration::Item const *Opts = _config->Tree(Cnf);
+ if (Opts == 0 || Opts->Child == 0)
+ return true;
+ Opts = Opts->Child;
+
+ unsigned int Count = 1;
+ for (; Opts != 0; Opts = Opts->Next, Count++)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+
+ // Determine the protocol version
+ string OptSec = Opts->Value;
+ string::size_type Pos;
+ if ((Pos = OptSec.find(' ')) == string::npos || Pos == 0)
+ Pos = OptSec.length();
+ OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos);
+
+ m_version = _config->FindI (OptSec + "::Version", 1);
+
+ // Purified Fork for running the script
+ // pid_t Process = ExecFork();
+ forkScript (Opts->Value.c_str(), sP);
+ }
+
+ return true;
+}
+
+bool DPkgPM::SendV1Pkgs (FILE *F)
+{
+ bool Die = false;
+ for (vector<Item>::iterator I = List.begin(); I != List.end(); ++I)
+ {
+ // Only deal with packages to be installed from .deb
+ if (I->Op != Item::Install)
+ continue;
+
+ // No errors here..
+ if (I->File[0] != '/')
+ continue;
+
+ /* Feed the filename of each package that is pending install
+ into the pipe. */
+ fprintf(F,"%s\n",I->File.c_str());
+ if (ferror(F) != 0)
+ {
+ Die = true;
+ break;
+ }
+ }
+ return ! Die;
+}
+
+bool DPkgPM::forkScript (const char *cmd, bool fP)
+{
+ cerr << "DPkgPM::forkScript ()" << endl;
+ if (fP) {
+ if (pipe( m_scriptPipe ) != 0)
+ return _error -> Errno("pipe", "Failed to create IPC pipe to subprocess");
+ SetCloseExec( m_scriptPipe[ 0 ], true );
+ SetCloseExec( m_scriptPipe[ 1 ], true );
+ }
+ pid_t Process = ExecFork ();
+ if (Process == 0)
+ {
+ setupScript (cmd, fP);
+
+ const char *Args[4];
+ Args[0] = "/bin/sh";
+ Args[1] = "-c";
+ Args[2] = cmd;
+ Args[3] = 0;
+ execv(Args[0],(char **)Args);
+ _exit(100);
+ }
+
+ if (fP) {
+ if (! feedPackages ())
+ return _error -> Error ("Failed feeding packages to script");
+ }
+
+ // Clean up the sub process
+ if (ExecWait (Process, cmd) == false)
+ return _error -> Error("Failure running script %s", cmd);
+}
+
+void DPkgPM::setupScript (const char * /*cmd*/, bool fP)
+{
+ cerr << "DPkgPM::setupScript ()" << endl;
+ if (fP) {
+ dup2 (m_scriptPipe [0], STDIN_FILENO);
+ SetCloseExec(STDOUT_FILENO, false);
+ SetCloseExec(STDIN_FILENO, false);
+ SetCloseExec(STDERR_FILENO, false);
+ }
+}
+
+bool DPkgPM::feedPackages ()
+{
+ close(m_scriptPipe[ 0 ]);
+
+ FILE *F = fdopen(m_scriptPipe[ 1 ], "w");
+ if (F == 0)
+ return _error->Errno("fdopen","Faild to open new FD");
+
+ // Feed it the filenames.
+ bool Die = false;
+ if (m_version <= 1)
+ Die = !SendV1Pkgs (F);
+ else
+ Die = !SendV2Pkgs(F);
+
+ fclose(F);
+ return ! Die;
+}
diff --git a/adept/libadept/dpkgpm.h b/adept/libadept/dpkgpm.h
new file mode 100644
index 0000000..b899693
--- /dev/null
+++ b/adept/libadept/dpkgpm.h
@@ -0,0 +1,49 @@
+/** -*- C++ -*-
+ @file adept/dpkgpm.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-pkg/dpkgpm.h>
+#include <string>
+#include <vector>
+#include <map>
+
+#ifndef DPKGPM_H
+# define DPKGPM_H
+
+namespace aptFront {
+
+class DPkgPM : public pkgDPkgPM {
+protected:
+ enum Op { ORemove, OPurge, OConfigure, OInstall };
+ Op m_currentOp;
+ int m_dpkgPipe[2];
+ int m_scriptPipe[2];
+ unsigned m_version;
+ std::string m_statusBuffer;
+ typedef std::pair< Op, std::string > OpAndStatus;
+ typedef std::map< std::pair< OpAndStatus, std::string >, int > SeenOps;
+ SeenOps m_seenOps;
+ int m_totalOpCount;
+ int m_seenOpCount;
+public:
+ DPkgPM (pkgDepCache *C);
+ virtual bool Go ( int );
+ virtual void computeTotals();
+ virtual bool setupArgs (char *const **a, std::vector<Item>::iterator &I);
+ virtual bool forkDpkg (char *const argv[]);
+ virtual bool forkScript (const char *, bool);
+ virtual bool runScripts (const char *, bool);
+ virtual bool setupChild ();
+ virtual void setupScript (const char *, bool);
+ virtual void dpkgMonitor (void);
+ virtual bool SendV1Pkgs (FILE *);
+ virtual bool feedPackages (void);
+ virtual void updateStatus( std::string pkg, std::string ev, std::string r );
+};
+
+}
+
+
+#endif /* ifndef DPKGPM_H */
+
diff --git a/adept/libadept/easytagfilter.cpp b/adept/libadept/easytagfilter.cpp
new file mode 100644
index 0000000..4fa593b
--- /dev/null
+++ b/adept/libadept/easytagfilter.cpp
@@ -0,0 +1,82 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include "easytagfilter.h"
+
+using namespace aptFront;
+using namespace adept;
+using namespace Tagcoll;
+
+static void fillCombo( QComboBox *c, const std::string f ) {
+ Cache &cache = cache::Global::get(); // FIXME?
+ OpSet< entity::Tag > t;
+ t = cache.tags().tags( f );
+ for (OpSet< entity::Tag >::iterator i = t.begin(); i != t.end(); ++ i) {
+ c->insertItem( i->name() );
+ }
+}
+
+EasyTagFilterWidget::EasyTagFilterWidget( QWidget *parent, const char *name )
+ : EasyTagFilterUi( parent, name )
+{
+ fillCombo( m_use, "use" );
+ fillCombo( m_interface, "interface" );
+ fillCombo( m_worksWith, "works-with" );
+ fillCombo( m_role, "role" );
+ connect( m_use, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_interface, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_worksWith, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_role, SIGNAL( activated( int ) ),
+ this, SLOT( widgetsChanged() ) );
+ connect( m_reset, SIGNAL( clicked() ),
+ this, SLOT( reset() ) );
+}
+
+static void setFacet( QComboBox *c, const std::string fac,
+ EasyTagFilter< entity::Package > &f )
+{
+ if (c->currentItem())
+ f.set( fac, c->currentText() );
+}
+
+EasyTagFilterWidget::Predicate EasyTagFilterWidget::predicate()
+{
+ EasyTagFilter< entity::Package > f;
+ setFacet( m_use, "use", f );
+ setFacet( m_interface, "interface", f );
+ setFacet( m_worksWith, "works-with", f );
+ setFacet( m_role, "role", f );
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void setCombo( QComboBox *c, const std::string &t ) {
+ c->blockSignals( true );
+ if (t == "")
+ c->setCurrentItem( 0 );
+ else
+ c->setCurrentText( t );
+ c->blockSignals( false );
+}
+
+void EasyTagFilterWidget::predicateChanged() {
+ typedef EasyTagFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ setCombo( m_use, f.get( "use" ) );
+ setCombo( m_interface, f.get( "interface" ) );
+ setCombo( m_role, f.get( "role" ) );
+ setCombo( m_worksWith, f.get( "works-with" ) );
+}
+
+void EasyTagFilterWidget::reset() {
+ setCombo( m_use, "" );
+ setCombo( m_interface, "" );
+ setCombo( m_role, "" );
+ setCombo( m_worksWith, "" );
+ emit widgetsChanged();
+}
diff --git a/adept/libadept/easytagfilter.h b/adept/libadept/easytagfilter.h
new file mode 100644
index 0000000..edbe8b5
--- /dev/null
+++ b/adept/libadept/easytagfilter.h
@@ -0,0 +1,93 @@
+/** -*- C++ -*-
+ @file adept/quickfilter.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <kdebug.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/component/tags.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/easytagfilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+
+#ifndef EPT_EASYTAGFILTER_H
+#define EPT_EASYTAGFILTER_H
+
+namespace adept {
+
+template< typename T >
+struct EasyTagFilter : predicate::Implementation< T, EasyTagFilter< T > >,
+ InterfacingPredicate
+{
+ typedef std::map< std::string, std::string > Tags;
+
+ EasyTagFilter() {
+ setupPredicate();
+ }
+
+ void setupPredicate() {
+ Cache &cache = cache::Global::get(); // FIXME?
+ m_op = predicate::True< T >();
+ for (Tags::iterator i = m_tags.begin(); i != m_tags.end(); ++i ) {
+ m_op = m_op and predicate::Factory< T >::tag(
+ cache.tags().tagByName( i->first + "::" + i->second ) );
+ // kdDebug() << t.summary() << endl;
+ }
+ }
+
+ std::string summary() const {
+ std::string r( i18n( "EasyTag filter: " ).local8Bit() );
+ for (Tags::const_iterator j, i = m_tags.begin();
+ i != m_tags.end(); ++i ) {
+ j = i; ++j;
+ r += i->first + ": " + i->second;
+ if (j != m_tags.end())
+ r += ", ";
+ }
+ return r;
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const EasyTagFilter &o ) const {
+ return o.m_tags == m_tags;
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ void set( const std::string &f, const std::string &t ) {
+ m_tags[f] = t;
+ setupPredicate();
+ }
+
+ std::string get( const std::string &f ) {
+ return m_tags[ f ];
+ }
+
+protected:
+ Tags m_tags;
+ predicate::Predicate< T > m_op;
+};
+
+class EasyTagFilterWidget : public EasyTagFilterUi
+{
+ Q_OBJECT
+public:
+ EasyTagFilterWidget( QWidget *parent, const char *name = 0 );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+ void reset();
+};
+
+}
+
+#endif
diff --git a/adept/libadept/easytagfilterui.ui b/adept/libadept/easytagfilterui.ui
new file mode 100644
index 0000000..998bf2b
--- /dev/null
+++ b/adept/libadept/easytagfilterui.ui
@@ -0,0 +1,201 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::EasyTagFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>EasyTagFilterUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>611</width>
+ <height>116</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>QuickFilterUi</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Easy Tag Filter&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Works With:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Role:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="3">
+ <item>
+ <property name="text">
+ <string>Anything</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_worksWith</cstring>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="4">
+ <property name="name">
+ <cstring>m_reset</cstring>
+ </property>
+ <property name="text">
+ <string>Reset Filter</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="3">
+ <item>
+ <property name="text">
+ <string>Any</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_interface</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Use:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Any</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_use</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Any</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_role</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Interface:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>130</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/libadept/extendablelist.cpp b/adept/libadept/extendablelist.cpp
new file mode 100644
index 0000000..55d1013
--- /dev/null
+++ b/adept/libadept/extendablelist.cpp
@@ -0,0 +1,332 @@
+#include <kdebug.h>
+#include <qtimer.h>
+#include <qobjectlist.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <kiconeffect.h>
+#include <kiconloader.h>
+
+#include <adept/extendablelist.h>
+#include <adept/utils.h>
+
+using namespace adept;
+
+ExtendableList::ExtendableList( QWidget *p, const char *n )
+ : KListView( p, n ),
+ m_toggleColumn( 0 ), m_inDtor( false ),
+ m_extenderUpdateScheduled( false ),
+ m_needSort( false ),
+ m_extenderHighlight( false )
+{
+ // kdDebug() << "connecting processClick har har" << endl;
+ connect( this, SIGNAL( clicked( QListViewItem *,
+ const QPoint &, int ) ),
+ this, SLOT( processClick( QListViewItem *,
+ const QPoint &, int ) ) );
+ connect( this, SIGNAL( moved() ),
+ this, SLOT( delayedUpdateExtenders() ) );
+ connect( this, SIGNAL( collapsed( QListViewItem * ) ),
+ this, SLOT( delayedUpdateExtenders() ) );
+ connect( this, SIGNAL( expanded( QListViewItem * ) ),
+ this, SLOT( delayedUpdateExtenders() ) );
+ setTreeStepSize( 15 );
+
+ m_baseIcon = SmallIcon( u8( "extender_closed" ) );
+ m_extendedIcon = SmallIcon( u8( "extender_opened" ) );
+ QImage img;
+ img = m_baseIcon;
+ KIconEffect::toGray( img, 1.0 );
+ m_unextendableIcon = QPixmap( img );
+}
+
+void ExtendableList::keyPressEvent( QKeyEvent *e ) {
+ ExtendableItem *item = dynamic_cast< ExtendableItem* >( currentItem() );
+ if ( item && item->extendable() ) {
+ if ( item->extender() && e->key() == Qt::Key_Left ) {
+ return item->hideExtender();
+ } else if ( !item->extender() && e->key() == Qt::Key_Right ) {
+ return item->showExtender();
+ }
+ }
+ return KListView::keyPressEvent( e );
+}
+
+void ExtendableList::openToplevel() {
+ QListViewItem *i;
+ for ( i = firstChild(); i != 0; i = i->nextSibling() ) {
+ i->setOpen( true );
+ }
+}
+
+int ExtendableList::extenderOffset( ExtendableItem *i )
+{
+ int c = 0, x = 0;
+
+ while( c < m_toggleColumn ) {
+ x += columnWidth( c );
+ c ++;
+ }
+
+ if ( m_toggleColumn >= 0 ) {
+ // *sigh*
+ if ( i->pixmap( m_toggleColumn ) )
+ x += i->pixmap( m_toggleColumn )->width();
+ if ( rootIsDecorated() )
+ x += treeStepSize();
+ if ( i->parent() )
+ x += treeStepSize();
+ }
+
+ return x;
+}
+
+void ExtendableList::updateExtender( ExtendableItem *i )
+{
+ // setUpdatesEnabled( false );
+
+ // since updateGeometries is private, we use this dirty trick to
+ // get at it (since setContentsPos in QListView calls it
+ setContentsPos( contentsX(), contentsY() );
+
+ if ( !i->isVisible() || ( i->parent() && !i->parent()->isOpen() ) ) {
+ kdDebug() << "hiding invisible item's extender" << endl;
+ i->hideExtender();
+ return;
+ }
+
+ // QRect rect = itemRect( i );
+ addChild( i->extender(), extenderOffset( i ), itemPos( i ) );
+ // addChild( i->extender(), x, rect.y() );
+ i->extender()->show();
+ i->extender()->resize( visibleWidth() - extenderOffset( i ),
+ i->extender()->height() );
+ if ( i->height() != i->extender()->frameSize().height() ) {
+ i->setHeight( i->extender()->frameSize().height() );
+ delayedUpdateExtenders(); // re-update since we broke layout
+ }
+
+ i->extender()->setupColors();
+
+ // setUpdatesEnabled( true );
+ // addChild( i->extender(), x, itemPos( i ) );
+ // QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) );
+ // QTimer::singleShot( 0, i->extender(), SLOT( setupColors() ) );
+}
+
+void ExtendableList::delayedUpdateExtenders()
+{
+ if ( m_extenderUpdateScheduled )
+ return;
+ m_extenderUpdateScheduled = true;
+ // kdDebug() << "ExtendableList::delayedUpdateExtenders()" << endl;
+ QTimer::singleShot( 0, this, SLOT( updateExtenders() ) );
+}
+
+void ExtendableList::clear()
+{
+ kdDebug() << "ExtendableList::clear()" << endl;
+ KListView::clear();
+ kdDebug() << "end of ExtendableList::clear()" << endl;
+}
+
+void ExtendableList::show()
+{
+ KListView::show();
+ updateExtenders();
+}
+
+void ExtendableList::showEvent( QShowEvent *e )
+{
+ KListView::showEvent( e );
+ updateExtenders();
+}
+
+void ExtendableList::resizeEvent( QResizeEvent *e )
+{
+ KListView::resizeEvent( e );
+ updateExtenders();
+ // delayedUpdateExtenders();
+}
+
+void ExtendableList::updateExtenders()
+{
+ m_extenderUpdateScheduled = false;
+ setUpdatesEnabled( false );
+ // updateGeometries();
+ // since updateGeometries is private, we use this dirty trick to
+ // get at it (since setContentsPos in QListView calls it
+ setContentsPos( contentsX(), contentsY() );
+ extendersChanged();
+ kdDebug() << "ExtendableList::updateExtenders(); count = "
+ << m_extenders.size() << endl;
+ if ( m_needSort ) {
+ std::sort( m_extenders.begin(), m_extenders.end(), ExtendableItem::s_less );
+ m_needSort = false;
+ }
+
+ std::for_each( m_extenders.begin(), m_extenders.end(),
+ std::bind1st( std::mem_fun( &ExtendableList::updateExtender ),
+ this ) );
+
+ setUpdatesEnabled( true );
+ // triggerUpdate();
+ if ( !m_extenderUpdateScheduled )
+ QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) );
+ /* if ( m_extenders.empty() )
+ QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) ); */
+ // QTimer::singleShot( 0, this, SIGNAL( extendersChanged() ) );
+}
+
+void ExtendableList::addExtender( ExtendableItem *item )
+{
+ m_extenders.push_back( item );
+ m_needSort = true;
+ // std::sort( m_extenders.begin(), m_extenders.end(), ExtendableItem::s_less );
+ // updateExtender( item );
+ delayedUpdateExtenders();
+}
+
+void ExtendableList::removeExtender( ExtendableItem *i )
+{
+ kdDebug() << "ExtendableList::removeExtender( " << i << " )" << endl;
+ m_extenders.erase( std::remove( m_extenders.begin(),
+ m_extenders.end(), i ),
+ m_extenders.end() );
+ // the above retains ordering so no need to re-sort
+ if (!m_inDtor)
+ delayedUpdateExtenders();
+}
+
+void ExtendableList::processClick( QListViewItem *it,
+ const QPoint &pt, int c )
+{
+ // if (! it) return;
+ ExtendableItem *item = dynamic_cast< ExtendableItem* >( it );
+ if (!item) return;
+ kdDebug() << "ExtendableList::processClick (a real item)" << endl;
+
+ if (c == m_toggleColumn)
+ item->toggleExtender();
+ if ( item->extender() )
+ item->extender()->setupColors();
+ delayedUpdateExtenders();
+ /* if (item->extender()) {
+ if (c == m_toggleColumn)
+ item->toggleExtender();
+ } else
+ item->toggleExtender(); */
+}
+
+ExtendableList::~ExtendableList() {
+}
+
+ExtendableList *ExtendableItem::list()
+{
+ return dynamic_cast< ExtendableList * >( listView() );
+}
+
+bool ExtendableItem::s_less(
+ const ExtendableItem *a, const ExtendableItem *b )
+{
+ return a->less( b );
+}
+
+int ExtendableItem::compare( QListViewItem *i, int c, bool asc ) const
+{
+ ExtendableItem *o = dynamic_cast< ExtendableItem * >( i );
+ return int( o->less( this ) ) - int( less( o ) );
+}
+
+void ExtendableItem::updateIcon() {
+ QPixmap p;
+ if ( !extender() ) {
+ p = list()->baseIcon();
+ if ( !extendable() && !firstChild() ) {
+ p = list()->unextendableIcon();
+ }
+ } else {
+ p = list()->extendedIcon();
+ }
+ setPixmap( list()->toggleColumn(), p );
+
+ // umm hack
+ if ( dynamic_cast< ExtendableItem * >( parent() ) )
+ dynamic_cast< ExtendableItem * >( parent() )->updateIcon();
+}
+
+
+void ExtendableItem::toggleExtender()
+{
+ if (m_extender) {
+ setup();
+ if( list() ) // this could as well be 0... bah
+ list()->removeExtender( this );
+ delete m_extender;
+ m_extender = 0;
+ } else {
+ m_extender = createExtender();
+ if (m_extender) {
+ m_extender->setItem( this );
+ list()->addExtender( this );
+ }
+ if ( !m_extender && firstChild() ) {
+ setOpen( !isOpen() );
+ }
+ }
+ updateIcon();
+}
+
+void ExtendableItem::paintBranches( QPainter *p,
+ const QColorGroup &cg, int w, int y, int h )
+{
+ /* if (!isAlternate())
+ p->setBackgroundColor(
+ KGlobalSettings::alternateBackgroundColor() );
+ p->eraseRect( 0, y, w, h ); */
+ p->eraseRect( 0, 0, w, h );
+}
+
+/* void ExtendableItem::paintCell( QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ KListViewItem::paintCell( &_p, cg, column, width, alignment );
+ p->drawPixmap( 0, 0, pm );
+ } */
+
+
+static void setcolor( QWidget *w, ExtendableItem *i ) {
+ if ( i->isSelected() && i->list()->extenderHighlight() )
+ w->setPaletteBackgroundColor( w->colorGroup().highlight() );
+ else if ( i->isAlternate() )
+ w->setPaletteBackgroundColor(
+ KGlobalSettings::alternateBackgroundColor() );
+ else
+ w->setPaletteBackgroundColor( w->colorGroup().base() );
+ // w->setBackgroundMode( QWidget::PaletteBase );
+}
+void ItemExtender::setupColors()
+{
+ if ( !item() ) return;
+ setcolor( this, item() );
+ QObjectList *chld = queryList( "QWidget" );
+ QObjectListIt it( *chld );
+ QWidget *o;
+ while ((o = dynamic_cast< QWidget * >( it.current() )) != 0) {
+ setcolor( o, item() );
+ ++it;
+ }
+}
+
+ExtendableItem::~ExtendableItem()
+{
+ // kdDebug() << "~ExtendableList; list = " << list() << endl;
+ // kdDebug() << "extender() = " << extender() << endl;
+ while ( firstChild() )
+ delete firstChild(); // har har
+ if( extender() && list() ) // list() could be 0...
+ list()->removeExtender( this );
+ if (extender())
+ extender()->deleteLater();
+}
diff --git a/adept/libadept/extendablelist.h b/adept/libadept/extendablelist.h
new file mode 100644
index 0000000..53a901b
--- /dev/null
+++ b/adept/libadept/extendablelist.h
@@ -0,0 +1,165 @@
+// -*- C++ -*-
+#include <klistview.h>
+#include <qpixmap.h>
+#include <qlayout.h>
+#include <kglobalsettings.h>
+#include <vector>
+
+#include <apt-front/utils/range.h>
+
+#ifndef EPT_EXTENDABLELIST_H
+#define EPT_EXTENDABLELIST_H
+namespace adept {
+
+using namespace aptFront;
+
+class ExtendableItem;
+class ExtendableList;
+class ItemExtender;
+
+class ExtendableList : public KListView {
+ Q_OBJECT
+public:
+ typedef bool(*ItemCompare)( const ExtendableItem *,
+ const ExtendableItem * );
+ ExtendableList( QWidget *p = 0, const char *n = 0 );
+ virtual ~ExtendableList();
+ QPixmap extendedIcon() { return m_extendedIcon; }
+ QPixmap baseIcon() { return m_baseIcon; }
+ QPixmap unextendableIcon() { return m_unextendableIcon; }
+ int extenderOffset( ExtendableItem *i );
+ void setExtenderHighlight( bool e ) { m_extenderHighlight = e; }
+ bool extenderHighlight() { return m_extenderHighlight; }
+public slots:
+ void addExtender( ExtendableItem *i );
+ void removeExtender( ExtendableItem *i );
+ void updateExtender( ExtendableItem *i );
+ void delayedUpdateExtenders();
+ void updateExtenders();
+ void setToggleColumn( int c ) {
+ m_toggleColumn = c;
+ }
+ unsigned toggleColumn() { return m_toggleColumn; }
+ virtual void show();
+ virtual void clear();
+ utils::Range< ExtendableItem * > extenders() {
+ return utils::range( m_extenders.begin(), m_extenders.end() ); }
+ void openToplevel();
+protected slots:
+ void processClick( QListViewItem *, const QPoint &, int );
+signals:
+ void extendersChanged();
+protected:
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void showEvent( QShowEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+ std::vector< ExtendableItem * > m_extenders;
+ QPixmap m_extendedIcon;
+ QPixmap m_baseIcon;
+ QPixmap m_unextendableIcon;
+ int m_toggleColumn;
+ bool m_inDtor:1;
+ bool m_extenderUpdateScheduled:1;
+ bool m_needSort:1;
+ bool m_extenderHighlight:1;
+};
+
+class ExtendableItem : public KListViewItem {
+public:
+
+ ExtendableItem( ExtendableList *l )
+ : KListViewItem( l ), m_extender( 0 ) {
+ }
+
+ ExtendableItem( ExtendableList *l, ExtendableItem *prev )
+ : KListViewItem( l, prev ), m_extender( 0 ) {
+ }
+
+ ExtendableItem( ExtendableItem *p, ExtendableItem *prev )
+ : KListViewItem( p, prev ), m_extender( 0 ) {
+ }
+
+ ExtendableItem( ExtendableItem *p )
+ : KListViewItem( p ), m_extender( 0 ) {
+ }
+
+ virtual void setup() {
+ KListViewItem::setup();
+ updateIcon();
+ }
+ void toggleExtender();
+
+ void hideExtender() {
+ if (extender())
+ toggleExtender();
+ }
+
+ void showExtender() {
+ if (!extender())
+ toggleExtender();
+ }
+
+ ItemExtender *extender() { return m_extender; }
+
+ static bool s_less( const ExtendableItem *a, const ExtendableItem *b );
+
+ ExtendableList *list();
+
+ virtual void updateIcon();
+
+ virtual void paintBranches( QPainter *, const QColorGroup &, int, int, int );
+
+ virtual ItemExtender *createExtender() = 0;
+ virtual bool extendable() const { return false; }
+ virtual bool less( const ExtendableItem * ) const = 0;
+ virtual int compare( QListViewItem *other, int col, bool ascending ) const;
+
+ virtual ~ExtendableItem();
+ virtual void setHeight( int h ) { KListViewItem::setHeight( h ); }
+protected:
+ ItemExtender *m_extender;
+};
+
+class ItemExtender : public QWidget {
+ Q_OBJECT
+public:
+ // ItemExtender( ExtendableItem *item );
+ ItemExtender( QWidget *parent, const char *n )
+ : QWidget( parent, n ), m_item( 0 )
+ {}
+
+ virtual void setItem( ExtendableItem *i ) {
+ m_item = i;
+ }
+
+ virtual void polish() {
+ setupColors();
+ }
+
+ ExtendableItem *item() {
+ return m_item;
+ }
+
+ void resize( int w, int h ) {
+ setUpdatesEnabled( false );
+ QWidget::resize( w, h );
+ setUpdatesEnabled( true );
+ QWidget::resize( w, layout()->minimumSize().height() );
+ }
+
+ void resize( const QSize &s ) {
+ resize( s.width(), s.height() );
+ }
+
+public slots:
+ void setupColors();
+protected:
+ virtual void mouseReleaseEvent( QMouseEvent *e ) {
+ e->accept();
+ } // throw away mouse clicks :-)
+ ExtendableItem *m_item;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/filterlist.cpp b/adept/libadept/filterlist.cpp
new file mode 100644
index 0000000..7d4a1b0
--- /dev/null
+++ b/adept/libadept/filterlist.cpp
@@ -0,0 +1,231 @@
+#include <kdebug.h>
+#include <qpopupmenu.h>
+#include <qheader.h>
+#include <klineedit.h>
+
+#include <tagcoll/InputMerger.h>
+
+#include <apt-front/cache/component/tags.h>
+#include <apt-front/cache/entity/package.h>
+
+#include <adept/lister.h>
+#include <adept/filterlist.h>
+#include <adept/quickfilter.h>
+#include <adept/statefilter.h>
+#include <adept/easytagfilter.h>
+#include <adept/tagfilter.h>
+
+
+using namespace adept;
+using namespace Tagcoll;
+
+// TODO: Beat enrico till this lands in some of our libs...
+template< typename PKG, typename TAG >
+class TagcollConsumerAdaptor :
+ public utils::ConsumerImpl< PKG,TagcollConsumerAdaptor<PKG, TAG> >
+{
+protected:
+ Consumer<PKG, TAG>& m_out;
+
+public:
+ TagcollConsumerAdaptor( Consumer<PKG, TAG>& out) : m_out( out ) {}
+ virtual void consume( const PKG& a ) {
+ if (a != PKG())
+ m_out.consume(a, a.tags());
+ }
+};
+
+PredicateInterface::PredicateInterface( QWidget *w, const char *n )
+ : ItemExtender( w, n )
+{
+}
+
+void PredicateInterface::widgetsChanged() {
+ kdDebug() << "PredicateInterface::widgetsChanged()" << endl;
+ emit predicateDrop( m_pred );
+ m_pred = predicate();
+ emit predicateAdd( m_pred );
+ downcast< FilterItem >( item() ).setPredicate( m_pred );
+}
+
+FilterList::FilterList( QWidget *parent, const char *name )
+ : ExtendableList( parent, name ),
+ m_pred( predicate::True< entity::Entity >() ),
+ m_hidden( predicate::True< entity::Entity >() )
+{
+ m_itemsSeen = 0;
+ // addColumn( " ", 20 );
+ addColumn( i18n( "Active filters" ), 240 );
+ // setSortColumn( -1 );
+ /* setItemsMovable( true );
+ setDragEnabled( true );
+ setAcceptDrops( true ); */
+ setResizeMode( LastColumn );
+ setAllColumnsShowFocus (true);
+
+ resize( 240, 180 );
+ connect( this, SIGNAL(
+ contextMenuRequested( QListViewItem *, const QPoint
+ &, int ) ),
+ this, SLOT( contextMenu( QListViewItem *, const
+ QPoint &, int) ) );
+ connect( this, SIGNAL( extendersChanged() ),
+ this, SLOT( updateHeight() ) );
+}
+
+void FilterList::emitPredicateChanged() {
+ predicateChanged( m_hidden and m_pred );
+}
+
+void FilterList::updateHeight() {
+ int h = header()->height() + 4;
+ for ( QListViewItem *i = firstChild(); i != 0; i = i->nextSibling() ) {
+ h += i->totalHeight();
+ }
+ // int h = contentsHeight() + header()->height() + 4; // magic constant
+ setMinimumHeight( h );
+ setMaximumHeight( h );
+}
+
+void FilterList::drawContents( QPainter *p, int a, int b, int c, int d ) {
+ if ( m_itemsSeen != childCount() ) {
+ m_itemsSeen = childCount();
+ updateHeight();
+ } // hmm, doesn't work... bah :p
+ KListView::drawContents( p, a, b, c, d );
+}
+
+void FilterList::plugLister( Lister *l ) {
+ m_lister = l;
+ connect( this, SIGNAL( predicateChanged( ListerPredicate ) ),
+ l, SLOT( baseSet( ListerPredicate ) ) );
+}
+
+void FilterList::setPredicate( Predicate p ) {
+ clear();
+ m_pred = p;
+ appendPredicate( p );
+ emitPredicateChanged();
+}
+
+void FilterList::setHiddenPredicate( Predicate p ) {
+ m_hidden = p;
+ emitPredicateChanged();
+}
+
+void FilterList::editorPredicateDrop( Predicate p ) {
+ m_pred = predicate::remove( m_pred, p );
+ emitPredicateChanged();
+}
+
+void FilterList::editorPredicateAdd( Predicate p ) {
+ kdDebug() << "FilterList::editorPredicateAdd" << endl;
+ m_pred = m_pred and p;
+ emitPredicateChanged();
+}
+
+void FilterList::appendPredicate( Predicate p ) {
+ if (p.is< And >()) {
+ And a = p;
+ for (utils::Range< Predicate > r = a.parts();
+ r != r.end(); ++r )
+ appendPredicate( *r );
+ } else if (p.is< predicate::True< entity::Entity > >() ) {
+ // we generally ignore truth
+ } else {
+ m_pred = m_pred and p;
+ // kdDebug() << p.serialize() << endl;
+ // kdDebug() << p.prettyPrint() << endl;
+ FilterItem *i;
+ i = new FilterItem( this );
+ i->setPredicate( p );
+ }
+}
+
+void FilterList::contextMenu( QListViewItem *it, const QPoint &pt, int /*c*/ )
+{
+ std::cerr << "FilterList::contextMenu(p);" << std::endl;
+ FilterItem *i = dynamic_cast< FilterItem * >( it );
+ if (! i)
+ return;
+ QPopupMenu *m = new QPopupMenu( this );
+ m->insertItem( i18n( "Reset Filter" ), 1 );
+ m->insertItem( i18n( "Remove Filter" ), 0 );
+ m->insertSeparator();
+ m->insertItem( i18n( "Add Quick Filter" ), 8 );
+ m->insertItem( i18n( "Add State Filter" ), 9 );
+ m->insertItem( i18n( "Add Tag Filter" ), 10 );
+ m->insertItem( i18n( "Add Easy Tag Filter" ), 11 );
+ // m->insertItem( "Add Tag Filter", tagMenu() );
+ m_context = i;
+ connect(m, SIGNAL(activated(int)), this, SLOT(contextActivated(int)));
+ m->exec(pt);
+ delete m;
+}
+
+
+void FilterList::contextActivated( int i )
+{
+ predicate::Predicate< entity::Entity > p;
+ switch (i) {
+ case 0:
+ m_pred = predicate::remove( m_pred, m_context->predicate() );
+ delete m_context;
+ emitPredicateChanged();
+ return;
+ case 1:
+ m_context->reset();
+ return;
+ case 8:
+ p = predicate::adapt< entity::Entity >(
+ QuickFilter< entity::Package >() );
+ break;
+ case 9:
+ p = predicate::adapt< entity::Entity >(
+ StateFilter< entity::Package >() );
+ break;
+ case 10:
+ p = predicate::adapt< entity::Entity >(
+ TagFilter< entity::Package >() );
+ break;
+ case 11:
+ p = predicate::adapt< entity::Entity >(
+ EasyTagFilter< entity::Package >() );
+ break;
+ }
+ if (p.impl()) {
+ kdDebug() << "summary: " <<
+ downcast< InterfacingPredicate >( p ).summary() << endl;
+ appendPredicate( p );
+ emitPredicateChanged();
+ }
+}
+
+ItemExtender *FilterItem::createExtender()
+{
+ PredicateInterface *o = 0;
+ if (m_pred.is< QuickFilter< entity::Package > >()) {
+ o = new QuickFilterWidget( list(), 0 );
+ } else if (m_pred.is< StateFilter< entity::Package > >()) {
+ o = new StateFilterWidget( list(), 0 );
+ } else if (m_pred.is< EasyTagFilter< entity::Package > >()) {
+ o = new EasyTagFilterWidget( list(), 0 );
+ } else if (m_pred.is< TagFilter< entity::Package > >()) {
+ o = new TagFilterWidget( list(), 0 );
+ }
+ if (o) {
+ o->setPredicate( m_pred );
+ QObject::connect( o, SIGNAL( predicateAdd( Predicate ) ),
+ list(), SLOT( editorPredicateAdd( Predicate ) ) );
+ QObject::connect( o, SIGNAL( predicateDrop( Predicate ) ),
+ list(), SLOT( editorPredicateDrop( Predicate ) ) );
+ }
+ return o;
+}
+
+QString FilterItem::text( int c ) const {
+ InterfacingPredicate &ip = downcast< InterfacingPredicate >( m_pred.impl() );
+ if (c == 0)
+ return ip.summary();
+ return u8( "" );
+}
diff --git a/adept/libadept/filterlist.h b/adept/libadept/filterlist.h
new file mode 100644
index 0000000..f904bc7
--- /dev/null
+++ b/adept/libadept/filterlist.h
@@ -0,0 +1,149 @@
+/** -*- C++ -*-
+ @file adept/filterlist.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qtooltip.h>
+#include <kdebug.h>
+
+#include <apt-front/predicate/matchers.h>
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/component/packagetags.h>
+#include <apt-front/cache/component/tags.h>
+
+#include <adept/listerpredicate.h>
+#include <adept/extendablelist.h>
+
+#ifndef EPT_FILTERLIST_H
+#define EPT_FILTERLIST_H
+
+class QPopupMenu;
+
+namespace adept {
+using namespace aptFront;
+using namespace aptFront::cache;
+class Lister;
+
+struct InterfacingPredicate
+{
+public:
+ virtual std::string summary() const = 0;
+ virtual void reset() {}
+signals:
+ void changed();
+};
+
+
+class PredicateInterface: public ItemExtender
+{
+ Q_OBJECT
+public:
+ typedef predicate::Predicate< entity::Entity > Predicate;
+ PredicateInterface( QWidget *w = 0, const char *n = 0 );
+ virtual Predicate predicate() = 0;
+signals:
+ void predicateAdd( Predicate );
+ void predicateDrop( Predicate );
+public slots:
+ virtual void setPredicate( const Predicate &p ) {
+ m_pred = p;
+ predicateChanged();
+ }
+ virtual void widgetsChanged();
+ virtual void predicateChanged() = 0;
+protected:
+ predicate::Predicate< entity::Entity > m_pred;
+};
+
+class FilterItem;
+
+class FilterList : public ExtendableList
+{
+ Q_OBJECT
+public:
+ friend class FilterItem;
+ typedef predicate::Predicate< entity::Entity > Predicate;
+ // typedef std::map< KListViewItem *, Predicate > Map;
+ FilterList( QWidget *parent = 0, const char *name = 0 );
+ typedef predicate::And< entity::Entity > And;
+ void appendPredicate( Predicate p );
+ void plugLister( Lister *l );
+ void emitPredicateChanged();
+signals:
+ void predicateChanged( ListerPredicate p );
+public slots:
+ void setPredicate( Predicate p );
+ void setHiddenPredicate( Predicate p );
+protected slots:
+ void editorPredicateDrop( Predicate );
+ void editorPredicateAdd( Predicate );
+ void contextMenu( QListViewItem *, const QPoint &, int );
+ // QPopupMenu *tagMenu();
+ void contextActivated( int );
+ // void tagMenuActivated( int );
+ void updateHeight();
+protected:
+ void drawContents( QPainter *, int, int, int, int );
+ Predicate m_pred;
+ Predicate m_hidden;
+ FilterItem *m_context;
+ bool m_changed;
+ Lister *m_lister;
+ int m_itemsSeen;
+ std::vector< entity::Tag > m_tagMenuMap;
+};
+
+class FilterItem : public ExtendableItem
+{
+public:
+ ItemExtender *createExtender();
+ FilterItem( FilterList *l )
+ : ExtendableItem( l ), m_delayedDone( false )
+ {
+ }
+ void setup() {
+ ExtendableItem::setup();
+ if (m_delayedDone)
+ return;
+ m_delayedDone = true;
+ showExtender();
+ }
+
+ QString text( int ) const;
+
+ virtual bool less( const ExtendableItem *other ) const {
+ const FilterItem *o = dynamic_cast< const FilterItem * >( other );
+ return downcast< InterfacingPredicate >( m_pred ).summary() <
+ downcast< InterfacingPredicate >( o->m_pred ).summary();
+ }
+
+ void setPredicate( predicate::Predicate< entity::Entity > p ) {
+ m_pred = p;
+ }
+
+ FilterList::Predicate predicate() const {
+ return m_pred;
+ }
+
+ FilterList *filterList() { return dynamic_cast< FilterList * >( list() ); }
+
+ void reset() {
+ filterList()->editorPredicateDrop( m_pred );
+ downcast< InterfacingPredicate >( m_pred ).reset();
+ if ( extender() ) {
+ downcast< PredicateInterface >( extender() ).setPredicate( m_pred );
+ extender()->setFocus();
+ }
+ filterList()->editorPredicateAdd( m_pred );
+ }
+
+protected:
+ predicate::Predicate< entity::Entity > m_pred;
+ bool m_delayedDone:1;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/filtersidebar.cpp b/adept/libadept/filtersidebar.cpp
new file mode 100644
index 0000000..52d909e
--- /dev/null
+++ b/adept/libadept/filtersidebar.cpp
@@ -0,0 +1,71 @@
+#include <functional>
+#include <ext/functional>
+#include <algorithm>
+#include <cmath>
+#include <apt-front/cache/entity/tag.h>
+#include <apt-front/cache/component/tags.h>
+#include <adept/filtersidebar.h>
+#include <adept/tagchooser.h>
+
+using namespace adept;
+using namespace aptFront;
+using namespace std;
+using namespace __gnu_cxx;
+
+template< typename H, typename G1, typename G2 >
+struct _compose2_binary {
+ _compose2_binary( H _h, G1 _g1, G2 _g2 )
+ : h( _h ), g1( _g1 ), g2( _g2 )
+ {}
+
+ typename H::result_type operator()(
+ typename G1::argument_type a,
+ typename G2::argument_type b )
+ {
+ return h( g1( a ), g2( b ) );
+ }
+
+ H h;
+ G1 g1;
+ G2 g2;
+};
+
+template< typename H, typename G1, typename G2 >
+_compose2_binary< H, G1, G2 > compose2_binary( H h, G1 g1, G2 g2 ) {
+ return _compose2_binary< H, G1, G2 >( h, g1, g2 );
+}
+
+void FilterSidebar::setCardinality( const Lister::Cardinality &c )
+{
+ cache::entity::Tag::Set all, smart;
+
+ kdDebug() << "FilterSidebar::setCardinality" << endl;
+ Lister::Cardinality cprime;
+ remove_copy_if( c.begin(), c.end(), inserter( cprime, cprime.begin() ),
+ compose1( bind1st( equal_to< int >(), 0 ),
+ select2nd<
+ Lister::Cardinality::value_type >() ) );
+ transform( cprime.begin(), cprime.end(), inserter( all, all.begin() ),
+ select1st< Lister::Cardinality::value_type >() );
+ m_all->setTags( all );
+ cache::component::Tags &t = cache::Global().get().tags();
+ m_easy->setTags( all ^ ( t.facetByName( "interface" ).tags()
+ + t.facetByName( "works-with" ).tags()
+ + t.facetByName( "use" ).tags()
+ + t.facetByName( "role" ).tags() ) );
+
+ typedef vector< pair< cache::entity::Tag, int > > Vec;
+ Vec vec;
+ copy( cprime.begin(), cprime.end(), back_inserter( vec ) );
+ sort( vec.begin(), vec.end(),
+ compose2_binary( less< int >(),
+ select2nd< Vec::value_type >(),
+ select2nd< Vec::value_type >() ) );
+ Vec::reverse_iterator end = vec.rbegin();
+ advance( end, vec.size() < 10 ? vec.size() : 10 );
+ transform( vec.rbegin(), end, inserter( smart, smart.begin() ),
+ select1st< Vec::value_type >() );
+
+ m_smart->setTags( smart );
+ m_smart->openToplevel();
+}
diff --git a/adept/libadept/filtersidebar.h b/adept/libadept/filtersidebar.h
new file mode 100644
index 0000000..0fac201
--- /dev/null
+++ b/adept/libadept/filtersidebar.h
@@ -0,0 +1,26 @@
+/* -*- C++ -*- file adept/filtersidebar.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <adept/filtersidebarui.h>
+#include <adept/lister.h>
+
+#ifndef EPT_FILTERSIDEBAR_H
+#define EPT_FILTERSIDEBAR_H
+
+namespace adept {
+
+// using namespace aptFront;
+
+class FilterSidebar : public FilterSidebarUi {
+ Q_OBJECT
+public:
+ FilterSidebar( QWidget *p = 0, const char *n = 0 )
+ : FilterSidebarUi( p, n )
+ {}
+public slots:
+ void setCardinality( const Lister::Cardinality & );
+};
+
+}
+
+#endif
diff --git a/adept/libadept/filtersidebarui.ui b/adept/libadept/filtersidebarui.ui
new file mode 100644
index 0000000..0f2efb4
--- /dev/null
+++ b/adept/libadept/filtersidebarui.ui
@@ -0,0 +1,119 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::FilterSidebarUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>adept::FilterSidebarUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>227</width>
+ <height>469</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form2</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>m_tabs</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab0</cstring>
+ </property>
+ <attribute name="title">
+ <string>Smart</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::TagChooser" row="0" column="0">
+ <property name="name">
+ <cstring>m_smart</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab1</cstring>
+ </property>
+ <attribute name="title">
+ <string>Simple</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::TagChooser" row="0" column="0">
+ <property name="name">
+ <cstring>m_easy</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab2</cstring>
+ </property>
+ <attribute name="title">
+ <string>All</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::TagChooser" row="0" column="0">
+ <property name="name">
+ <cstring>m_all</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::TagChooser</class>
+ <header location="global">adept/tagchooser.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </customwidget>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/tagchooser.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/filterwidget.cpp b/adept/libadept/filterwidget.cpp
new file mode 100644
index 0000000..f294327
--- /dev/null
+++ b/adept/libadept/filterwidget.cpp
@@ -0,0 +1,36 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include "filterwidget.h"
+
+using namespace aptFront;
+using namespace adept;
+
+void FilterWidget::connectLister( Lister *l ) {
+ connect( this, SIGNAL( drop( ListerPredicate ) ),
+ l, SLOT( interactiveDrop( ListerPredicate ) ) );
+ connect( this, SIGNAL( changed( ListerPredicate ) ),
+ l, SLOT( interactiveAnd( ListerPredicate ) ) );
+ connect( this, SIGNAL( apply( ListerPredicate ) ),
+ l, SLOT( baseAnd( ListerPredicate ) ) );
+
+}
+
+void FilterWidget::changedInternal() {
+ setEnabled( false );
+ emit drop( m_old );
+ emit changed( m_old = predicate() );
+ setEnabled( true );
+ setFocus();
+}
+
+void FilterWidget::applyInternal() {
+ // check for emptiness?
+ setEnabled( false );
+ emit drop( m_old );
+ emit apply( m_old = predicate() );
+ reset();
+ setEnabled( true );
+ setFocus();
+}
diff --git a/adept/libadept/filterwidget.h b/adept/libadept/filterwidget.h
new file mode 100644
index 0000000..78b0c38
--- /dev/null
+++ b/adept/libadept/filterwidget.h
@@ -0,0 +1,39 @@
+/** -*- C++ -*-
+ @file adept/filterwidgets.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <adept/lister.h>
+
+#ifndef EPT_FILTERWIDGET_H
+#define EPT_FILTERWIDGET_H
+
+class KLineEdit;
+
+namespace adept {
+
+class FilterWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ FilterWidget( QWidget *parent = 0, const char *n = 0 )
+ : QWidget( parent, n ) {}
+ virtual ListerPredicate predicate() = 0;
+ void connectLister( Lister *l );
+protected slots:
+ void changedInternal();
+ void applyInternal();
+ virtual void reset() = 0;
+signals:
+ void changed( ListerPredicate op );
+ void apply( ListerPredicate op );
+ void drop( ListerPredicate op );
+protected:
+ ListerPredicate m_old;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/groupeddesktopselector.cpp b/adept/libadept/groupeddesktopselector.cpp
new file mode 100644
index 0000000..68afa98
--- /dev/null
+++ b/adept/libadept/groupeddesktopselector.cpp
@@ -0,0 +1,137 @@
+/** -*- C++ -*-
+ @file adept/groupeddestkopselector.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qobjectlist.h>
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kseparator.h>
+#include <kapplication.h>
+
+#include <apt-front/cache/component/desktop.h>
+#include <adept/groupeddesktopselector.h>
+#include <adept/desktoplist.h>
+#include <adept/utils.h>
+
+using namespace aptFront;
+using namespace cache;
+
+namespace adept {
+
+GroupedDesktopSelector::GroupedDesktopSelector( QWidget *p, const char *n )
+ : KJanusWidget( p, n, IconList ), m_policy( 0 )
+{
+ observeComponent< cache::component::Packages >();
+ m_pages.push_back( addPage( QString( "Initializing..." ) ) );
+ QObjectList *chld = queryList( "QWidget" );
+ QObjectListIt it( *chld ); QWidget *o;
+ while ((o = dynamic_cast< QWidget * >( it.current() )) != 0) {
+ if ( dynamic_cast< QLabel * >( o ) != 0 )
+ o->hide();
+ if ( dynamic_cast< KSeparator * >( o ) != 0 )
+ o->hide();
+ ++it;
+ } // *hack*
+
+ // AAAA hack
+ QLayoutIterator li = layout()->iterator();
+ QHBoxLayout *hbox = 0;
+ while ( li.current() != 0 ) {
+ hbox = dynamic_cast< QHBoxLayout * >( li.current() );
+ if ( hbox ) break;
+ ++li;
+ }
+ kdDebug() << "hacking hbox = " << hbox << endl;
+ if ( hbox ) {
+ li = hbox->iterator();
+ while ( li.current() != 0 ) {
+ QSpacerItem *spacer = dynamic_cast< QSpacerItem * >( li.current() );
+ if ( spacer ) {
+ hbox->removeItem( spacer );
+ delete spacer;
+ }
+ ++li;
+ }
+ }
+}
+
+void GroupedDesktopSelector::notifyPreRebuild( component::Base * ) {
+ clear();
+}
+
+void GroupedDesktopSelector::notifyPostRebuild( component::Base * ) {
+ // QTimer::singleShot( 0, this, SLOT( fill() ) );
+}
+
+void GroupedDesktopSelector::clear()
+{
+ if ( !m_pages.empty() )
+ showPage( m_pages.front() );
+ while ( !m_pages.empty() ) {
+ removePage( m_pages.back() );
+ delete m_pages.back();
+ m_pages.pop_back();
+ }
+}
+
+void GroupedDesktopSelector::fill()
+{
+ component::Desktop &d = cache::Global::get().component< component::Desktop >();
+ fill( d.entries() );
+}
+
+void GroupedDesktopSelector::fill( component::Desktop::EntityRange r )
+{
+ component::Desktop &d = cache::Global::get().component< component::Desktop >();
+ utils::Range< std::string > gr;
+ QString last = pageTitle( activePageIndex() );
+
+ clear();
+
+ bool shown = false;
+
+ for ( gr = d.availableGroups( r ); gr != gr.end(); gr.advance() ) {
+
+ component::Desktop::EntityRange cr = d.group( *gr );
+ QString name = u8( *gr );
+ std::cerr << "group for " << cr->name() << ": " << r->group() << std::endl;
+ name = ( name != u8( "" ) ? name : u8( "Legacy" ) );
+
+ QPixmap icon( KGlobal::iconLoader()->iconPath(
+ policy() ? policy()->iconForGroup( name ) : u8( "" ), -32 ) );
+
+ QVBox *b = addVBoxPage( name, name, icon );
+ m_pages.push_back( b );
+ std::cerr << "creating list for " << *gr << std::endl;
+
+ DesktopList *l = new DesktopList( b );
+ l->setTitle( name );
+ connect( l, SIGNAL( request( cache::entity::Package,
+ cache::component::State::Action ) ),
+ this, SIGNAL( request( cache::entity::Package,
+ cache::component::State::Action ) ) );
+ connect( l, SIGNAL( showDescription( cache::entity::Desktop ) ),
+ this, SIGNAL( showDescription( cache::entity::Desktop ) ) );
+
+ l->insertRange( intersectionRange( r, cr ) );
+ // l->insertRange( cr );
+
+ std::cerr << "created list for " << *gr << std::endl;
+ if ( name == last ) {
+ showPage( b );
+ shown = true;
+ }
+ kapp->processEvents();
+ }
+
+ if ( m_pages.empty() )
+ m_pages.push_back( addPage( QString( "No Results" ) ) );
+ if ( !shown )
+ showPage( pageIndex( m_pages.front() ) );
+}
+
+}
diff --git a/adept/libadept/groupeddesktopselector.h b/adept/libadept/groupeddesktopselector.h
new file mode 100644
index 0000000..a54f7aa
--- /dev/null
+++ b/adept/libadept/groupeddesktopselector.h
@@ -0,0 +1,39 @@
+/** -*- C++ -*-
+ @file adept/groupeddestkopselector.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <kjanuswidget.h>
+#include <apt-front/cache/entity/desktop.h>
+
+namespace adept {
+using namespace aptFront;
+using namespace aptFront::cache;
+
+// XXX needs fixing
+class GroupedDesktopSelector : public KJanusWidget, cache::Observer
+{
+ Q_OBJECT
+public:
+ struct IconPolicy {
+ virtual QString iconForGroup( QString group ) { return group; }
+ };
+ GroupedDesktopSelector( QWidget *p = 0, const char *n = 0 );
+ void fill( component::Desktop::EntityRange r );
+ void setPolicy( IconPolicy *p ) { m_policy = p; }
+ IconPolicy *policy() { return m_policy; }
+ virtual void notifyPreRebuild( cache::component::Base * );
+ virtual void notifyPostRebuild( cache::component::Base * );
+public slots:
+ void clear();
+ void fill();
+signals:
+ void request( cache::entity::Package, cache::component::State::Action );
+ void showDescription( cache::entity::Desktop );
+protected:
+ IconPolicy *m_policy;
+ std::vector< QWidget * > m_pages;
+ // IconPolicy m_defaultPolicy;
+};
+
+}
diff --git a/adept/libadept/installerview.cpp b/adept/libadept/installerview.cpp
new file mode 100644
index 0000000..eac9dc7
--- /dev/null
+++ b/adept/libadept/installerview.cpp
@@ -0,0 +1,88 @@
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qtextbrowser.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+#include <apt-front/cache/entity/desktop.h>
+#include <apt-front/predicate/factory.h>
+#include <apt-front/cache/component/tags.h>
+#include <adept/installerview.h>
+#include <adept/packageinfo.h>
+#include <adept/utils.h>
+
+using namespace adept;
+using namespace aptFront;
+using namespace cache;
+
+void InstallerView::rebuild()
+{
+ typedef predicate::Factory< entity::Desktop > Factory;
+ if ( m_inRebuild ) {
+ QTimer::singleShot( 500, this, SLOT( rebuild() ) );
+ return;
+ }
+ m_inRebuild = true;
+
+ component::Desktop &d = cache::Global::get().component< component::Desktop >();
+ component::Tags &t =
+ cache::Global::get().component< component::Tags >();
+
+ Predicate p = predicate::True< entity::Desktop >();
+ if ( m_search->text() != u8( "" ) ) {
+ Predicate tmp = Factory::name( u8( m_search->text() ) )
+ or Factory::description( u8( m_search->text() ) );
+ p = p and tmp;
+ }
+
+ std::string st = "";
+ int si = m_suite->currentItem();
+
+ if ( si == 0 ) st = "suite::kde";
+ if ( si == 1 ) st = "suite::gnome";
+
+ if ( st != "" )
+ p = p and Factory::tag( t.tagByName( st ) );
+
+ if ( !m_unsupported->isChecked() ) {
+ p = p and not Factory::sectionSubstring( "contrib" )
+ and not Factory::sectionSubstring( "universe" )
+ and not Factory::sectionSubstring( "multiverse" );
+ }
+
+ if ( !m_nonfree->isChecked() ) {
+ p = p and not Factory::sectionSubstring( "non-free" )
+ and not Factory::sectionSubstring( "multiverse" )
+ and not Factory::sectionSubstring( "restricted" );
+ }
+
+ selector()->fill( filteredRange( d.entries(), p ) );
+
+ m_inRebuild = false;
+}
+
+InstallerView::InstallerView( QWidget *p , const char *n )
+ : InstallerViewUi( p, n ), m_inRebuild( false )
+{
+ connect( m_search, SIGNAL( textChanged( const QString & ) ),
+ this, SLOT( textChanged() ) );
+ connect( &timer, SIGNAL( timeout() ), this, SLOT( rebuild() ) );
+ connect( m_suite, SIGNAL( activated( int ) ), this, SLOT( rebuild() ) );
+ connect( m_unsupported, SIGNAL( toggled( bool ) ), this, SLOT( rebuild() ) );
+ connect( m_nonfree, SIGNAL( toggled( bool ) ), this, SLOT( rebuild() ) );
+ connect( selector(), SIGNAL( showDescription( cache::entity::Desktop ) ),
+ this, SLOT( showDescription( cache::entity::Desktop ) ) );
+}
+
+void InstallerView::textChanged() {
+ timer.start( 1000, true );
+}
+
+void InstallerView::showDescription( entity::Desktop e )
+{
+ kdDebug() << "InstallerView::showDescription..." << endl;
+ m_description->setText( u8( "<b>" ) + e.name() + u8( "</b>" )
+ + i18n( "<br><b>Package:</b> " ) + e.package().name()
+ + formatLongDescription(
+ e.package().longDescription( std::string( "" ) ) ) );
+}
diff --git a/adept/libadept/installerview.h b/adept/libadept/installerview.h
new file mode 100644
index 0000000..ed955dc
--- /dev/null
+++ b/adept/libadept/installerview.h
@@ -0,0 +1,33 @@
+/** -*- C++ -*-
+ @file adept/installerview.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qtimer.h>
+#include <adept/installerviewui.h>
+#include <adept/groupeddesktopselector.h>
+
+#ifndef EPT_INSTALLERVIEW_H
+#define EPT_INSTALLERVIEW_H
+
+namespace adept {
+class InstallerView : public InstallerViewUi
+{
+ Q_OBJECT
+public:
+ typedef predicate::Predicate< entity::Desktop > Predicate;
+ InstallerView( QWidget *p = 0, const char *n = 0 );
+ GroupedDesktopSelector *selector() { return m_selector; }
+protected slots:
+ void textChanged();
+ void showDescription( cache::entity::Desktop );
+public slots:
+ void rebuild();
+protected:
+ bool m_inRebuild;
+ QTimer timer;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/installerviewui.ui b/adept/libadept/installerviewui.ui
new file mode 100644
index 0000000..6f8b5d7
--- /dev/null
+++ b/adept/libadept/installerviewui.ui
@@ -0,0 +1,194 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>InstallerViewUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>InstallerViewUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>666</width>
+ <height>314</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>4</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Search:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_search</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>KDE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>GNOME</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Any Suite</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_suite</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Show:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_unsupported</cstring>
+ </property>
+ <property name="text">
+ <string>unsupported,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_nonfree</cstring>
+ </property>
+ <property name="text">
+ <string>proprietary software.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="adept::GroupedDesktopSelector" row="1" column="0">
+ <property name="name">
+ <cstring>m_selector</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>6</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QTextBrowser" row="1" column="1">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::GroupedDesktopSelector</class>
+ <header location="local">adept/groupeddesktopselector.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1122">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042949444154388db5954d6c545514c77ff7de37eff1a6a550da994e5ba798868f948fc847a2a2911816c436b0a02ed0083161a1981877ee10d90aa94656063491882c5cd4c4b8103f20cd806909a98604da8482341de80cb69de9bcd799799d79efba980f1da3a80b4f727273939bdff99f9b93f3175a6b6a21849080020c4002a29a8f0a5dcd002803bed63a1035f0d0d0504b6f6fef51d7758fa4d3e98d8ee3fc03af128ee3303939399548242eb8aefb09300f78464de9f0f0f0d148cc7caf3d5424de97a7ec17104220242805520a44557bbd4b21f083801d33e63a6d1bc7bf19c6064e0319a35a58b9ae7ba43d54e4d7c54b64dc097c7f09d30ef04b36736983cc7c11b4456b9b492c5e20dc54a6540e00896a8268a7017010f8bcae1830d2e9f4c69ebe3c197782b2ce60d94ddc9b30f9feeb45ae5d7181c5ead35636ef08d3ffe26a76ee3208b4031a56d80aa00768fda362e9380e25bf80ef3b587613d7afc099533380a4b5dda46fcb5aa42998b9eb7173dce5e6788e434763ec7fc942532008ea436003660d2caa7f8d69c3bd8910674e4d033e83877ad8d36fb0aa4d6058658ac5358c5df6383bf480f31fdda5a3632bbbfb6da4ccd5c00a10b2012cc12fd97cfb5516f0187c25cee0619396480ec3ca909d0f3372d1e5f9fe66de3ad605587c712ec55256a2540d5519d19ae24a29057329839f7ecc138944d833102290f3184ae1e6d6f0e98739c61229e6d21eafbed1c9c8c5558c8f3ee4ceed76946a1c43d97091828585223e2eebfbc295f60d45de89707628cb58224577bc85a79e5d4d786581cddb9b0148259711b20145836221400416e0232d1f6595c9ce4538773ac7b54406f0b15784e8e80aa1ac2594190220d021e49f2437960156b70ba095e95f96f18acd8c263cc6122962b1167a7ba34cdd7ec8c977a699bed546722a8fc2a02b6e2185fff78ab586ce78894ddb9ab9f5738ed14b1e030756929d8ff2e4ae5544632b38f96e89a99b298ebd6950cc2d12ed0eb3618b26f520788462ad09877df60db600f0f1fb49c646f21c7ebd836dcf94e9d9b4c0db27d6d3bd36c6426a96bce731703046d7da129a4670836284a054869d4f1b1c7e2dca67676ef3c1898091ef5ad8bc358c3205c93bf7c9a40ad4c660f4728edd7bbb3142ea2fc1da711cfc200011e08b45f6bd1c261adbce9717928c5f9d63fc6a19f0014567773303073790f8214bd6f5282dfbb8b9fa1f6b40d7c1939393533b92e63ad9240990484aec7e41b27d579cbb531e0f67023492d86316ebb768ba1e0f786e6f37e56550c62237aee7011e54abd7c1412291b8a06de378b4d3c0b215da9708e5a3a442192085404a83d4accfecac067c0c43e13a70e3fa12e96409e0325000966bbb354465339d04a6f9dd15fe6dde07ce030780278088d05ad72cc9a6b2f2daaaa74d75a1f0e8d0d5f60b40868a8364ead6248430000b0857a126ffcdf396abf03ce089ffcb4c7f033046c6b4a995e7a00000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/groupeddesktopselector.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/lister.cpp b/adept/libadept/lister.cpp
new file mode 100644
index 0000000..85142c3
--- /dev/null
+++ b/adept/libadept/lister.cpp
@@ -0,0 +1,707 @@
+// -*- Mode: C++; c-basic-offset: 4; -*-
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qpushbutton.h>
+#include <qthread.h>
+#include <qtextbrowser.h>
+
+#include <kpopupmenu.h>
+#include <kdebug.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+
+#include <functional>
+#include <iostream>
+
+#include <apt-front/cache/cache.h>
+#include <apt-front/actor.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/utils.h>
+#include <adept/lister.h>
+#include <adept/packageinfo.h>
+
+using namespace aptFront;
+using namespace aptFront::predicate;
+using namespace aptFront::cache;
+using namespace aptFront::utils;
+using namespace adept;
+
+Lister::Lister( QWidget *parent, const char *name )
+ : ExtendableList( parent, name ),
+ m_rangeProvider( 0 ),
+ m_baseF( predicate::True< entity::Entity >() ),
+ m_interactiveF( True<entity::Entity>() ), m_itemCount( -1 ),
+ m_rebuildScheduled( false ), m_inRebuild( false ), m_cancelRebuild( false ),
+ m_openToplevel( false ), m_rebuildMutex( true )
+{
+ observeComponent< component::State >();
+ observeComponent< component::Packages >();
+ observeComponent< component::PackageTags >();
+ setRootIsDecorated( false );
+ setSelectionModeExt( Extended );
+ setAllColumnsShowFocus (true);
+
+ m_icons[ u8( "package-install" ) ] = u8( "adept_install" );
+ m_icons[ u8( "package-remove" ) ] = u8( "adept_remove" );
+ m_icons[ u8( "package-upgrade" ) ] = u8( "adept_upgrade" );
+ m_icons[ u8( "package-keep" )] = u8( "adept_keep" );
+ m_icons[ u8( "package-reinstall" )] = u8( "adept_reinstall" );
+ m_icons[ u8( "package-purge" )] = u8( "adept_purge" );
+
+ setSorting( -1 );
+ // addColumn(" ", 40);
+ // addColumn(" ", 18);
+ addColumn( i18n( "Package" ), 180);
+ addColumn( i18n( "Status" ), 110);
+ addColumn( i18n( "Requested" ), 90);
+ addColumn( i18n( "Description" ), 300);
+ setToggleColumn( 0 );
+
+ setResizeMode (LastColumn);
+ connect( this, SIGNAL( selectionChanged() ), SLOT( updateActions() ) );
+ connect( this,
+ SIGNAL( contextMenuRequested( QListViewItem *,
+ const QPoint &, int ) ),
+ this, SLOT(
+ contextMenu( QListViewItem *, const QPoint &, int) ) );
+ m_tip = 0;
+ // m_tip = new ListerTooltip( viewport(), this );
+}
+
+Lister::~Lister()
+{
+ delete m_tip;
+}
+
+void Lister::scheduleRebuild()
+{
+ if (!m_rebuildScheduled) {
+ // kdDebug() << "Lister scheduling rebuild" << endl;
+ QTimer::singleShot( 0, this, SLOT( rebuild() ) );
+ }
+ m_rebuildScheduled = true;
+}
+
+void Lister::updateActions()
+{
+ emit actionsChanged( this );
+}
+
+void Lister::notifyPostChange( component::Base * )
+{
+ kdDebug() << "notifyRefresh()" << endl;
+ updateActions();
+ triggerUpdate();
+}
+
+void Lister::notifyPreRebuild( component::Base *b )
+{
+ kdDebug() << "Lister::notifyPreRebuild( " << b << " )" << endl;
+ Cache &c = cache::Global::get( m_cache );
+ setEnabled( false );
+ if ( dynamic_cast< component::PackageTags * >( b ) != 0 ) {
+ kdDebug() << "clearing cardinality" << endl;
+ m_cardinality.clear();
+ }
+ if ( dynamic_cast< component::Packages * >( b ) != 0 ) {
+ kdDebug() << "clearing lister" << endl;
+ clear();
+ m_items.clear();
+ m_cardinality.clear();
+ }
+}
+
+void Lister::notifyPostRebuild( component::Base *b )
+{
+ kdDebug() << "Lister::notifyPostRebuild( " << b << " )" << endl;
+ scheduleRebuild();
+ if ( dynamic_cast< component::State * >( b ) != 0 ) {
+ setEnabled( true );
+ }
+}
+
+bool lessByName( const entity::Entity &e1, const entity::Entity &e2 )
+{
+ if ( e1.is< entity::Named >() && e2.is< entity::Named >() ) {
+ entity::Named &n1 = downcast< entity::Named >( e1 ),
+ &n2 = downcast< entity::Named >( e2 );
+ return n1.name() < n2.name();
+ }
+ return e1 < e2;
+}
+
+bool Lister::cancelRebuild() {
+ // kdDebug() << "cancel rebuild: " << m_inRebuild << ", " << m_cancelRebuild << endl;
+ if ( m_inRebuild ) {
+ m_rebuildScheduled = false;
+ m_cancelRebuild = true;
+ }
+ if ( !cache::Global::get( m_cache ).isOpen() ) {
+ m_rebuildScheduled = false;
+ return true;
+ }
+ return m_cancelRebuild;
+}
+
+void Lister::cleanRebuild()
+{
+ scheduleRebuild();
+}
+
+Lister::CreateItem::CreateItem( Lister *_l, ListerItem *p )
+ : l( _l ), time( 0 ), items( 0 ), last( 0 ), parent( p )
+{
+}
+
+Lister::CreateItem::~CreateItem()
+{
+ // delete timer;
+}
+
+Lister::Map::value_type Lister::CreateItem::operator()( entity::Entity e )
+{
+ items ++;
+ if ( l->m_cancelRebuild ) throw 0; // XXX proper exception please
+ // kdDebug() << "trying to acquire mutex" << endl;
+ l->m_rebuildMutex.lock();
+ // kdDebug() << "mutex acquired" << endl;
+
+ // count tags
+ if ( e.is< entity::Package >() ) {
+ const entity::Tag::Set &tags = downcast< entity::Package >( e ).tags();
+ for (entity::Tag::Set::iterator i = tags.begin(); i != tags.end(); ++ i )
+ l->m_cardinality[ *i ] ++;
+ }
+
+ if ( last ) {
+ if ( parent )
+ last = new ListerItem( parent, last, e );
+ else
+ last = new ListerItem( l, last, e );
+ } else {
+ if ( parent )
+ last = new ListerItem( parent, e );
+ else
+ last = new ListerItem( l, e );
+ }
+ l->m_rebuildMutex.unlock();
+ if ( e.is< entity::Relation >() )
+ // this should be safe because the parent thread is waiting
+ // for us and ensures that universe (libapt-front) is kept
+ // unchanged while we run
+ l->insertRangeInternal( InsertRangePair(
+ last, downcast< entity::Relation >( e ).targetPackages() ) );
+ // we may want to use recursive async call instead? why?
+ /* Threads::enqueue(
+ asyncCall( std::bind2nd( std::mem_fun( &Lister::insertRangeInternal ),
+ InsertRangePair(
+ last,
+ downcast< entity::Relation >( e ).targetPackages() ) ),
+ l ), &(l->m_rebuildMutex) );
+ */
+ return std::make_pair( e, last );
+}
+
+void Lister::reallyUpdate()
+{
+ bool en = isUpdatesEnabled();
+ setUpdatesEnabled( true );
+ triggerUpdate();
+ setUpdatesEnabled( en );
+}
+
+void Lister::insertRange( Range r ) {
+ insertRangeInternal( InsertRangePair( 0, r ) );
+}
+void Lister::insertRangeInternal( InsertRangePair a )
+{
+ // kdDebug() << "insertRange running..." << endl;
+ try {
+ std::transform( a.second, a.second.end(),
+ inserter( m_items, m_items.begin() ),
+ CreateItem( this, a.first ) );
+ } catch ( ... ) {}
+ m_itemCount = m_items.size();
+}
+
+/* void Lister::rebuildInsertRange( Range r ) {
+ insertRange( 0, r );
+ } */
+
+void Lister::rebuild()
+{
+ Cache &c = cache::Global::get( m_cache );
+ if ( cancelRebuild() ) {
+ scheduleRebuild();
+ return;
+ }
+
+ m_inRebuild = true;
+ m_rebuildMutex.lock();
+
+ emit rebuildStarted();
+
+ c.progress().OverallProgress( 0, 0, 0, i18n( "Filtering" ) );
+ kdDebug() << "rebuild running" << endl;
+ clock_t _c = clock(), C;
+ for ( Cardinality::iterator i = m_cardinality.begin();
+ i != m_cardinality.end(); ++i )
+ i->second = 0;
+
+ kdDebug() << "querying m_rangeProvider " << m_rangeProvider << "..." << endl;
+
+ Range r = filteredRange( m_rangeProvider ?
+ m_rangeProvider->listerRange() : range( VectorRange() ),
+ m_baseF );
+ C = (clock() - _c) / 1000; _c = clock();
+
+ setUpdatesEnabled( false );
+ kdDebug() << "clearing..." << endl;
+ clear();
+ m_items.clear();
+
+ kdDebug() << "asyncCall to rebuildInsertRange..." << endl;
+ QThread *t = asyncCall( std::bind2nd(
+ std::mem_fun( &Lister::insertRangeInternal ),
+ InsertRangePair( 0, r ) ),
+ this );
+
+ kdDebug() << "starting the thread..." << endl;
+
+ QTimer timer;
+ connect( &timer, SIGNAL( timeout() ),
+ this, SLOT( reallyUpdate() ) );
+ timer.start( 0 );
+
+ m_rebuildMutex.unlock();
+ Threads::enqueue( t, &m_rebuildMutex );
+ Threads::wait();
+
+ timer.stop();
+
+ kdDebug() << "thread finished..." << endl;
+ C = (clock() - _c) / 1000; _c = clock();
+ kdDebug() << m_items.size() << " entities synced, time = " << C << endl;
+
+ setUpdatesEnabled( true );
+ c.progress().Done();
+ if ( m_openToplevel ) openToplevel();
+ triggerUpdate();
+
+ if ( !m_cancelRebuild ) {
+ for ( Cardinality::iterator i = m_cardinality.begin();
+ i != m_cardinality.end(); ++i )
+ if ( i->second == m_itemCount )
+ i->second = -1;
+ emit cardinalityChanged( m_cardinality );
+ }
+
+ m_inRebuild = false;
+ m_rebuildScheduled = false;
+ m_cancelRebuild = false;
+ emit rebuildFinished();
+}
+
+void Lister::baseAnd( Predicate o )
+{
+ m_baseF = predicate::predicate( m_baseF and o );
+ // emit filterChanged( m_baseF );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+void Lister::baseSet( Predicate o )
+{
+ m_baseF = o;
+ // emit filterChanged( m_baseF );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+void Lister::interactiveAnd( Predicate o )
+{
+ m_interactiveF = predicate::predicate( m_interactiveF and o );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+void Lister::interactiveDrop( Predicate o )
+{
+ m_interactiveF = predicate::remove( m_interactiveF, o );
+ cancelRebuild();
+ scheduleRebuild();
+}
+
+bool Lister::itemSelected( Map::value_type i )
+{
+ return not i.second->isSelected();
+}
+
+entity::Entity Lister::extractKey( Map::value_type i )
+{
+ return i.first;
+}
+
+Lister::VectorRange Lister::selection()
+{
+ VectorRange ret;
+ Map m;
+ std::remove_copy_if( m_items.begin(), m_items.end(),
+ inserter( m, m.begin() ),
+ itemSelected );
+ std::transform( m.begin(), m.end(),
+ consumer( ret ),
+ extractKey );
+ return ret;
+}
+
+Lister::VectorRange Lister::content()
+{
+ VectorRange ret;
+ std::transform( m_items.begin(), m_items.end(),
+ consumer( ret ),
+ extractKey );
+ return ret;
+}
+
+QString ListerItem::text( int column ) const
+{
+ // if (column == 0) return ""; // until we redo paintcell for the col
+ if (entity().is<entity::Package>()) {
+ entity::Package p = entity();
+ switch (column) {
+ case 0: return u8( p.name( u8( i18n( "n/a" ) ) ) );
+ case 1: return u8( p.statusString( u8( i18n( "n/a" ) ) ) );
+ case 2: return u8( p.actionString( u8( i18n( "n/a" ) ) ) );
+ case 3: return u8( p.shortDescription( u8( i18n( "n/a" ) ) ) );
+ // case 2: return p.candidateVersion().versionString();
+ }
+ }
+ if ( entity().is< entity::Relation >() && column == 0 )
+ return downcast< entity::Relation >( entity() ).format();
+ return u8( "" );
+}
+
+void ListerItem::paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ if ( width <= 0 )
+ return;
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ if (entity().is<entity::Package>()) {
+ entity::Package p = entity();
+ if (column == 1)
+ c = statusColor( p );
+ if (column == 2)
+ c = actionColor( p );
+ }
+ _cg.setColor( QColorGroup::Text, c );
+ KListViewItem::paintCell( &_p, _cg, column, width, AlignTop );
+ p->drawPixmap( 0, 0, pm );
+}
+
+void Lister::contextMenu( QListViewItem *it, const QPoint &pt, int /*c*/ )
+{
+ if (! it) // check for actor when we have one...
+ return;
+ m_context = dynamic_cast< ListerItem * >( it );
+ VectorRange sel = selection();
+ // entity::Package p = (dynamic_cast<ListerItem *>(it)->entity());
+ KPopupMenu *m = new KPopupMenu (this);
+ utils::Range< Actor > r = actor::Global< entity::Package >::list();
+ int id = 8;
+ try {
+ for (; r != r.end(); ++r) {
+ m->insertItem( SmallIconSet( m_icons[ u8( r->name() ) ] ),
+ r->prettyName(), id );
+ m->setItemEnabled(
+ id, r->possible( utils::upcastRange< entity::Package >( sel ) ) );
+ ++id;
+ }
+ } catch ( std::bad_cast ) {} // ignore (this is broken, but
+ // easiest fix)
+ bool open = m_context->extender();
+ m->insertItem( open ? i18n( "Hide details" ) :
+ i18n( "Show details" ), open ? 1 : 0 );
+ connect(m, SIGNAL(activated(int)), this, SLOT(contextActivated(int)));
+ m->exec(pt);
+ delete m;
+}
+
+void Lister::contextActivated( int id )
+{
+ VectorRange sel = selection();
+ try {
+ if (id >= 8) {
+ utils::Range< Actor > r = actor::Global< entity::Package >::list();
+ std::advance( r, id - 8 );
+ (*r)( utils::upcastRange< entity::Package >( sel ) );
+ updateActions();
+ }
+ if (id < 8) {
+ VectorRange i = sel.begin();
+ while (i != i.end()) {
+ if (id == 0)
+ m_items[*i]->showExtender();
+ if (id == 1)
+ m_items[*i]->hideExtender();
+ ++ i;
+ }
+ }
+ } catch ( std::bad_cast ) {} // ignore (this is broken, but
+}
+
+ListerItemExtender::~ListerItemExtender()
+{
+}
+
+ListerItemExtender::ListerItemExtender( QWidget *parent, const char * n)
+ : ListerItemExtenderUi( parent, n )
+{
+ observeComponent< component::State >();
+ adjustFontSize( m_description, -1 );
+ connect( m_details, SIGNAL( clicked() ),
+ this, SLOT( detailsClicked() ) );
+
+ m_packageInfo->adjustFontSize( -1 );
+ m_packageInfo->hideStatus();
+}
+
+void ListerItemExtender::detailsClicked() {
+ detailsRequested( m_entity );
+}
+
+ListerItem *ListerItemExtender::item()
+{
+ return dynamic_cast< ListerItem * >( m_item );
+}
+
+void ListerItemExtender::mouseReleaseEvent( QMouseEvent *e ) {
+ e->ignore();
+ if ( childAt( e->pos() ) != static_cast< QWidget * >( m_name ) )
+ e->accept();
+}
+void ListerItemExtender::setItem( ExtendableItem *i )
+{
+ ItemExtender::setItem( i );
+ m_entity = item()->entity();
+ // setupColors();
+
+ kdDebug() << "ListerItemExtender::setItem connecting" << endl;
+ connect( this, SIGNAL( detailsRequested( Lister::Entity ) ),
+ item()->list(), SIGNAL( detailsRequested( Lister::Entity ) ) );
+
+ entity::Version v;
+ entity::Package p;
+
+ if ( m_entity.is< entity::Version >() ) {
+ v = m_entity;
+ p = v.package();
+ }
+
+ if ( m_entity.is< entity::Package >() ) {
+ p = m_entity;
+ v = p.anyVersion();
+ }
+
+ if ( !v.valid() ) {
+ m_logical->setText( i18n( "Immutable" ) );
+ m_logical->setEnabled( false );
+ m_details->setEnabled( false );
+ return;
+ }
+
+ m_name->setText( /* QString( "<b>" ) + */
+ v.package().name( std::string( "oops" ) ) /* + "</b>" */ );
+ QString l = u8( v.longDescription(
+ u8( i18n( "No long description available" ) ) ) );
+
+ m_description->setText( QString( "<qt>" )
+ + formatLongDescription( l ) + "</qt>" );
+ m_description->adjustSize();
+ m_description->installEventFilter( this );
+
+ m_packageInfo->setVersion( v, m_entity.is< entity::Version >() );
+
+ notifyPostChange( 0 );
+}
+
+void ListerItemExtender::notifyPostRebuild( component::Base *b )
+{ // need to catch undo/redo effects
+ return notifyPostChange( b );
+}
+
+void ListerItemExtender::notifyPostChange( component::Base * )
+{
+ // without the timer to break it, there could be a loop where
+ // we connect the clicked() signal to a slot which would be
+ // invoked right away when we return -> evil
+ QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
+}
+
+void ListerItemExtender::updateLogical() {
+ entity::Package pkg = entity();
+ EntityActor *a = 0;
+
+ m_status->setText( colorify(
+ statusColor( pkg ),
+ u8( pkg.statusString( u8( i18n( "Unknown" ) ) ) ) ) );
+ m_change->setText( colorify(
+ actionColor( pkg ),
+ u8( pkg.actionString( u8( i18n( "Unknown" ) ) ) ) ) );
+
+
+ m_logical->setEnabled( true );
+ if (pkg.canUpgrade()) {
+ a = new EntityActor( pkg.upgrade() );
+ } else if (pkg.canInstall()) {
+ a = new EntityActor( pkg.install() );
+ } else if (pkg.canKeep()) {
+ a = new EntityActor( pkg.keep() );
+ } else if (pkg.canRemove()) {
+ a = new EntityActor( pkg.remove() );
+ }
+
+ if (a) {
+ m_logical->setText( u8( a->actor().prettyName() ) );
+ connect( m_logical, SIGNAL( clicked() ),
+ a, SLOT( destructiveAct() ) );
+ } else {
+ m_logical->setText( i18n( "Immutable" ) );
+ m_logical->setEnabled( false );
+ }
+
+}
+
+bool ListerItemExtender::eventFilter( QObject *o, QEvent *e )
+{
+ if (o == m_description && e->type() == QEvent::Wheel) {
+ // kdDebug() << "discarding wheel event..." << endl;
+ QApplication::sendEvent( this, e );
+ return true;
+ }
+ return false;
+}
+
+void ListerItemExtender::resize( int w, int h )
+{
+ int namew = - item()->lister()->extenderOffset( item() ) - 2
+ - layout()->margin()
+ - layout()->spacing()
+ + item()->lister()->columnWidth( 0 );
+ int statw = item()->lister()->columnWidth( 1 )
+ - layout()->spacing();
+ int chw = item()->lister()->columnWidth( 2 ) - 2
+ - layout()->spacing();
+ m_name->setMinimumWidth( namew );
+ m_status->setMinimumWidth( statw );
+ m_change->setMinimumWidth( chw );
+ m_packageInfo->adjustSize();
+ m_leftHeight = m_name->height() + m_packageInfo->height()
+ + m_logical->height() + 20;
+ QWidget::resize( w, 500 );
+ QWidget::resize(
+ w,
+ QMAX( m_description->contentsHeight() + 16,
+ m_leftHeight ) );
+}
+
+bool entityLess::operator()( entity::Entity e1, entity::Entity e2 )
+{
+ if ( e1.is< entity::Package >() ) {
+ if ( e2.is< entity::Package >() )
+ return e1 < e2;
+ return true;
+ }
+
+ if ( e1.is< entity::Version >() ) {
+ if ( e2.is< entity::Package >() )
+ return false;
+ if ( e2.is< entity::Version >() )
+ return e1 < e2;
+ return true;
+ }
+
+ if ( e1.is< entity::Relation >() ) {
+ if ( e2.is< entity::Package >() )
+ return false;
+ if ( e2.is< entity::Version >() )
+ return false;
+ if ( e2.is< entity::Relation >() )
+ return e1 < e2;
+ return true;
+ }
+ return true;
+}
+
+bool ListerItem::less( const ExtendableItem *b ) const
+{
+ entity::Entity e1 = entity(), e2 = dynamic_cast< const ListerItem * >( b )->entity();
+ return entityLess()( e1, e2 );
+}
+
+bool ListerItem::keepLess( const ListerItem *o ) const
+{
+ const ListerItem *b = o;
+ while ( b != 0 ) {
+ if ( b == this )
+ return false;
+ b = b->m_previous;
+ }
+ while ( o != 0 ) {
+ o = dynamic_cast< const ListerItem * >( o->nextSibling() );
+ if ( o == this )
+ return true;
+ }
+ return false;
+}
+
+QString ListerTooltip::format( const QString &what,
+ const QString &txt, bool nobr )
+{
+ QString ret = "<b>" + what + "</b>&nbsp;" + (nobr ? "<nobr>" : "")
+ + txt + (nobr ? "</nobr>" : "") + "<br>";
+ return ret;
+}
+
+void ListerTooltip::maybeTip( const QPoint &pt )
+{
+ if ( !m_parent )
+ return;
+ kdDebug() << "ListTreeWidgetTooltip::maybeTip ()" << endl;
+ ListerItem *x = dynamic_cast<ListerItem *>( m_parent->itemAt( pt ) );
+ if ( !x )
+ return;
+ if ( x->extender() )
+ return; // no tips for extended items, thank you
+ QString str = u8( "<qt>" );
+ QString descr, cand, cur;
+ descr = cand = cur = i18n( "<i>Not available</i>" );
+ entity::Package p( x->entity() );
+ descr = p.shortDescription( std::string(
+ i18n( "<i>Not available</i>" ).local8Bit() ) );
+ try {
+ cand = u8( p.candidateVersion().versionString() );
+ } catch (...) {}
+ try {
+ cur = u8( p.installedVersion().versionString() );
+ } catch (...) {}
+
+ str += format( i18n( "Package:" ), u8( p.name() ) );
+ str += format( i18n( "Description:" ), descr );
+ str += format( i18n( "Current&nbsp;Version:" ), cur );
+ str += format( i18n( "Candidate&nbsp;Version:" ), cand );
+
+ str.append( u8( "</qt>" ) );
+ tip( m_parent->itemRect( x ), str );
+}
diff --git a/adept/libadept/lister.h b/adept/libadept/lister.h
new file mode 100644
index 0000000..dede538
--- /dev/null
+++ b/adept/libadept/lister.h
@@ -0,0 +1,220 @@
+/** -*- C++ -*-
+ @file adept/lister.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qtooltip.h>
+#include <qmap.h>
+#include <qmutex.h>
+#include <set>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/actor.h>
+#include <apt-front/predicate/matchers.h>
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/utils/range.h>
+
+#include <adept/extendablelist.h>
+#include <adept/listerextenderui.h>
+#include <adept/actor.h>
+#include <adept/listerpredicate.h>
+
+#ifndef EPT_LISTER_H
+#define EPT_LISTER_H
+
+class KLineEdit;
+
+namespace adept {
+
+using namespace aptFront;
+using namespace aptFront::cache;
+class ListerTooltip;
+class ListerItemExtender;
+class ListerItem;
+class Lister;
+
+struct entityLess {
+ bool operator()( entity::Entity e1, entity::Entity e2 );
+};
+
+class Lister: public ExtendableList, public Observer
+{
+ Q_OBJECT
+public:
+ typedef entity::Entity Entity;
+ typedef std::vector< Entity > Vector;
+ typedef utils::Range< Entity > Range;
+ typedef utils::VectorRange< Entity > VectorRange;
+ typedef std::set< Entity > Set;
+ typedef std::map< Entity, ListerItem *, entityLess > Map;
+ typedef actor::Actor< entity::Package > Actor;
+ typedef predicate::Predicate< Entity > Predicate;
+ typedef std::map< cache::entity::Tag, int > Cardinality;
+ struct RangeProvider {
+ virtual Range listerRange() = 0;
+ };
+
+ Lister (QWidget *parent = 0, const char *name = 0);
+ ~Lister();
+ void setSource();
+ virtual void notifyPostChange( component::Base * );
+ virtual void notifyPreRebuild( component::Base * );
+ virtual void notifyPostRebuild( component::Base * );
+ VectorRange selection();
+ VectorRange content();
+ int itemCount() { return m_itemCount; }
+ // void setRange( const Range &r ) { m_range = r; }
+ void setRangeProvider( RangeProvider *r ) { m_rangeProvider = r; }
+ void insertRange( Range );
+ void setOpenToplevel( bool o ) { m_openToplevel = o; }
+
+ bool busy() { return m_rebuildScheduled || m_inRebuild; }
+
+signals:
+ // this is adept::Lister because of braindead moc
+ void actionsChanged( adept::Lister * );
+ void cardinalityChanged( const Lister::Cardinality & );
+ void detailsRequested( Lister::Entity );
+ void rebuildStarted();
+ void rebuildFinished();
+ // void filterChanged( Lister::Predicate );
+
+public slots:
+ virtual void cleanRebuild();
+ virtual void rebuild();
+ virtual void baseAnd( ListerPredicate );
+ virtual void interactiveDrop( ListerPredicate );
+ virtual void interactiveAnd( ListerPredicate );
+ virtual void baseSet( ListerPredicate );
+ virtual void updateActions();
+ virtual void scheduleRebuild();
+ virtual void reallyUpdate();
+protected slots:
+ void contextMenu( QListViewItem *, const QPoint &, int );
+ void contextActivated( int );
+protected:
+ typedef std::pair< ListerItem *, Range > InsertRangePair;
+ void insertRangeInternal( InsertRangePair );
+ ListerTooltip *m_tip;
+
+ static Entity extractKey( Map::value_type );
+ static bool itemSelected( Map::value_type );
+
+ struct CreateItem {
+ CreateItem( Lister *, ListerItem * );
+ ~CreateItem();
+ Map::value_type operator()( Entity );
+ Lister *l;
+ int time;
+ int items;
+ ListerItem *last;
+ ListerItem *parent;
+ };
+
+ bool cancelRebuild();
+ void rebuildInsertRange( Range );
+
+ ListerItem *m_context;
+ QMap< QString, QString > m_icons;
+ Map m_items;
+ Vector m_all;
+ RangeProvider *m_rangeProvider;
+ Predicate m_baseF, m_interactiveF;
+ int m_itemCount;
+ bool m_rebuildScheduled:1;
+ bool m_inRebuild:1;
+ bool m_cancelRebuild:1;
+ bool m_openToplevel:1;
+ Cardinality m_cardinality;
+ QMutex m_rebuildMutex;
+};
+
+class ListerTooltip : public QToolTip
+{
+public:
+ ListerTooltip (QWidget *v, Lister *p) : QToolTip (v, 0), m_parent (p) {};
+protected:
+ QString format( const QString &, const QString &, bool = true );
+ virtual void maybeTip (const QPoint &p);
+ Lister *m_parent;
+};
+
+class ListerItemExtender : public ListerItemExtenderUi,
+ public cache::Observer {
+ Q_OBJECT
+public:
+ ListerItemExtender( QWidget *parent = 0, const char * n = 0 );
+ ~ListerItemExtender();
+ virtual void resize( int w, int h );
+ void setItem( ExtendableItem *i );
+ ListerItem *item();
+ entity::Entity entity() const { return m_entity; }
+ void notifyPostChange( component::Base * );
+ void notifyPostRebuild( component::Base * );
+protected slots:
+ void detailsClicked();
+ void updateLogical();
+signals:
+ void detailsRequested( Lister::Entity );
+protected:
+ bool eventFilter( QObject *o, QEvent *e );
+ void mouseReleaseEvent( QMouseEvent *e );
+ entity::Entity m_entity;
+ unsigned m_leftHeight;
+};
+
+class ListerItem: public ExtendableItem
+{
+public:
+ ListerItem(Lister *v, entity::Entity e)
+ : ExtendableItem (v), m_previous( 0 ), m_entity( e )
+ {}
+ ListerItem(Lister *v, ListerItem *i, entity::Entity e)
+ : ExtendableItem( v, i ), m_previous( i ), m_entity( e )
+ {}
+ ListerItem(ListerItem *p, ListerItem *i, entity::Entity e)
+ : ExtendableItem( p, i ), m_previous( i ), m_entity( e )
+ {}
+ ListerItem(ListerItem *p, entity::Entity e)
+ : ExtendableItem( p ), m_previous( 0 ), m_entity( e )
+ {}
+
+ virtual ItemExtender *createExtender() {
+ if ( extendable() )
+ return new ListerItemExtender();
+ return 0;
+ }
+
+ /* virtual void updateIcon( const QPixmap &p ) {
+ if ( m_entity.is< entity::Package >()
+ || m_entity.is< entity::Version >() )
+ return ExtendableItem::updateIcon( p );
+ setPixmap( list()->toggleColumn(), QPixmap() );
+ } */
+
+ virtual QString text( int column ) const;
+ entity::Entity entity() { return m_entity; }
+ const entity::Entity entity() const { return m_entity; }
+ virtual void paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment);
+ virtual bool less( const ExtendableItem * ) const;
+ Lister *lister() {
+ return dynamic_cast< Lister* >( listView() );
+ }
+
+ // beware, makes sort O(n^2lg(n^2))
+ bool keepLess( const ListerItem *o ) const;
+ virtual bool extendable() const {
+ return ( entity().is< entity::Package >()
+ || m_entity.is< entity::Version >() );
+ }
+
+protected:
+ ListerItem *m_previous;
+ entity::Entity m_entity;
+};
+
+}
+
+#endif /* ifndef PKGLIST_H */
diff --git a/adept/libadept/listerextenderui.ui b/adept/libadept/listerextenderui.ui
new file mode 100644
index 0000000..de2e481
--- /dev/null
+++ b/adept/libadept/listerextenderui.ui
@@ -0,0 +1,310 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::ListerItemExtenderUi</class>
+<widget class="adept::ItemExtender">
+ <property name="name">
+ <cstring>ListerItemExtenderrUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>587</width>
+ <height>230</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>ListerItemExtenderrUi</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="4" column="2">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="3">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>4</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>name</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_status</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>status</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_change</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>change</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QTextBrowser" row="0" column="2" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="resizePolicy">
+ <enum>AutoOneFit</enum>
+ </property>
+ <property name="vScrollBarMode">
+ <enum>AlwaysOff</enum>
+ </property>
+ <property name="hScrollBarMode">
+ <enum>AlwaysOff</enum>
+ </property>
+ <property name="text">
+ <string>description...</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>4</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_logical</cstring>
+ </property>
+ <property name="text">
+ <string>logical</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_details</cstring>
+ </property>
+ <property name="text">
+ <string>Details</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="adept::PackageInfo" row="1" column="1">
+ <property name="name">
+ <cstring>m_packageInfo</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>80</height>
+ </size>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>4</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::PackageInfo</class>
+ <header location="global">adept/packageinfo.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
+ </image>
+</images>
+<includes>
+ <include location="global" impldecl="in declaration">adept/extendablelist.h</include>
+</includes>
+<layoutdefaults spacing="0" margin="4"/>
+<includehints>
+ <includehint>adept/packageinfo.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/listerpredicate.h b/adept/libadept/listerpredicate.h
new file mode 100644
index 0000000..98f1b41
--- /dev/null
+++ b/adept/libadept/listerpredicate.h
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/predicate/predicate.h>
+
+#ifndef EPT_LISTERPREDICATE_H
+#define EPT_LISTERPREDICATE_H
+
+namespace adept {
+using namespace aptFront;
+using namespace cache;
+typedef predicate::Predicate< entity::Entity > ListerPredicate;
+}
+
+#endif
diff --git a/adept/libadept/packagedetails.cpp b/adept/libadept/packagedetails.cpp
new file mode 100644
index 0000000..4e97fd4
--- /dev/null
+++ b/adept/libadept/packagedetails.cpp
@@ -0,0 +1,253 @@
+#include <qtoolbutton.h>
+#include <qtextbrowser.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <qpushbutton.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+
+#include <kfileitem.h>
+#include <kfiledetailview.h>
+#include <kapplication.h>
+
+#include <adept/lister.h>
+#include <adept/tagchooser.h>
+#include <adept/packageinfo.h>
+#include <adept/packagedetails.h>
+#include <adept/utils.h>
+
+#include <fstream>
+
+using namespace adept;
+
+PackageDetails::PackageDetails( QWidget *w, const char *n )
+ : PackageDetailsUi( w, n ),
+ m_thread( 0 ),
+ m_qtMutex( true ),
+ m_logicalAct( 0 ), m_removeAct( 0 ),
+ m_fileListRunning( false )
+{
+ m_toolbar->setIconSize( 22 );
+ m_toolbar->setIconText( KToolBar::IconTextRight );
+
+ m_toolbar->insertButton( u8( "back" ), BBack, false, i18n( "Back" ) );
+ m_toolbar->insertButton( u8( "forward" ), BForward, false, i18n( "Forward" ) );
+ m_toolbar->insertLineSeparator();
+ m_toolbar->insertButton( u8( "" ), BShow, true, i18n( "Show List" ) );
+
+ m_tags->setTitle( i18n( "Assigned Tags" ) );
+
+ m_lister->setRangeProvider( this ); // wee
+ // m_lister->setOpenToplevel( true );
+
+ m_description->setPaper( QBrush( colorGroup().background() ) );
+
+ connect( m_toolbar->getButton( BShow ), SIGNAL( clicked() ),
+ this, SIGNAL( showList() ) );
+ connect( m_toolbar->getButton( BBack ), SIGNAL( clicked() ),
+ this, SIGNAL( back() ) );
+ connect( m_toolbar->getButton( BForward ), SIGNAL( clicked() ),
+ this, SIGNAL( forward() ) );
+ connect( m_lister, SIGNAL( detailsRequested( Lister::Entity ) ),
+ this, SIGNAL( detailsRequested( Lister::Entity ) ) );
+
+ observeComponent< component::State >();
+
+ adjustFontSize( m_name, 1 );
+
+ Cache &c = cache::Global::get( m_cache );
+ component::Packages::iterator i = c.packages().packagesBegin();
+ while ( !i->hasVersion() ) ++i; // ha hum...
+ setPackage( *i );
+}
+
+Lister::Range PackageDetails::listerRange() {
+ utils::Range< entity::Relation > r = m_package.depends();
+ utils::VectorRange< entity::Entity > vr;
+ while ( r != r.end() ) {
+ if ( !r->targetPackages().empty() )
+ std::cerr << r->targetPackages()->name() << std::endl;
+ vr.consume( *r );
+ r = r.next();
+ }
+ return vr.sorted();
+}
+
+void PackageDetails::loadFileListWorker()
+{
+ entity::Package p = m_package;
+
+ std::string fl, flfile = "/var/lib/dpkg/info/" + p.name() + ".list";
+ std::ifstream ifl( flfile.c_str() );
+
+ int i = 0;
+ kdDebug() << "PackageDetails::loadFileListWorker() entering loop" << endl;
+
+ while ( ifl.is_open() && !ifl.eof() ) {
+ std::string line;
+ getline( ifl, line );
+ if ( line == "/." || line == "" )
+ continue; // nasty evil thing go away
+ m_qtMutex.lock();
+ KURL url( "file:///" );
+ url.addPath( u8( line ) );
+ KFileItem *it = new KFileItem( url, u8( "" ), 0 );
+ it->setName( u8( line ) );
+ m_fileList->insertItem( it );
+ ++i;
+ m_qtMutex.unlock();
+ }
+ kdDebug() << "PackageDetails::loadFileListWorker() leaving loop" << endl;
+ ifl.close();
+}
+
+void PackageDetails::notifyPreRebuild( component::Base * ) {
+ kdDebug() << "PackageDetails::notifyPreRebuild()" << endl;
+ Threads::wait();
+ m_logical->setEnabled( false );
+ m_remove->setEnabled( false );
+ m_logical->disconnect( SIGNAL( clicked() ) );
+ m_remove->disconnect( SIGNAL( clicked() ) );
+ delete m_logicalAct;
+ delete m_removeAct;
+ kdDebug() << "PackageDetails::notifyPreRebuild() done" << endl;
+}
+
+void PackageDetails::loadFileList() {
+ Cache &c = cache::Global::get( m_cache );
+ if ( m_fileListRunning || !c.isOpen() ) {
+ QTimer::singleShot( 100, this, SLOT( loadFileList() ) );
+ return;
+ }
+
+ kdDebug() << "PackageDetails::loadFileList()" << endl;
+ m_fileListRunning = true;
+
+ // the following call is neccessary to invoke buildDefaultType of KMimeType
+ // the first time the method is called it will check for
+ // existence of application/octet-stream and *popup a dialog* if
+ // not found -- we don't want that to happen in a non-gui thread
+ KMimeType::defaultMimeTypePtr();
+ m_thread = asyncCall( std::mem_fun( &PackageDetails::loadFileListWorker ), this );
+
+ m_qtMutex.lock();
+ m_fileList->KFileView::clear();
+ c.progress().OverallProgress( 0, 0, 0, i18n( "Loading filelist..." ) );
+
+ m_qtMutex.unlock();
+ Threads::enqueue( m_thread, &m_qtMutex );
+ Threads::wait();
+ c.progress().Done();
+ m_fileListRunning = false;
+ kdDebug() << "PackageDetails::loadFileList() finished" << endl;
+}
+
+void PackageDetails::setPackage( cache::entity::Package p )
+{
+ kdDebug() << "PackageDetails::setPackage()" << endl;
+ m_package = p.stable();
+ m_name->setText( QString( "<b>" ) +
+ p.name( std::string( "No package" ) ) + "</b>" );
+ m_info->setPackage( p );
+ QString l = p.longDescription(
+ std::string( i18n( "No long description available" ).local8Bit() ) );
+ m_description->setText( QString( "<qt>" )
+ + formatLongDescription( l ) + "</qt>" );
+
+ std::string na = u8( i18n( "not available" ) );
+ m_tags->setTags( p.tags( entity::Package::TagSet() ) );
+ m_tags->openToplevel();
+ m_architecture->setText( labelFormat( i18n( "Architecture: " ),
+ p.architecture( na ) ) );
+ m_filename->setText( labelFormat( i18n( "Filename: " ), p.fileName( na ) ) );
+ m_md5->setText( labelFormat( i18n( "MD5: " ), p.md5sum( na ) ) );
+ m_source->setText( labelFormat( i18n( "Source Package: " ), p.source( na ) ) );
+
+
+ notifyPostChange( 0 );
+ m_lister->cleanRebuild();
+ loadFileList();
+}
+
+void PackageDetails::notifyPostChange( cache::component::Base * )
+{
+ kdDebug() << "PackageDetails::notifyPostChange()" << endl;
+ // without the timer to break it, there could be a loop where
+ // we connect the clicked() signal to a slot which would be
+ // invoked right away when we return -> evil
+ QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
+}
+
+void PackageDetails::notifyPostRebuild( cache::component::Base *b )
+{
+ kdDebug() << "PackageDetails::notifyPostRebuild( " << b << " )" << endl;
+ // can't call directly because stable entities are not guaranteed
+ // to be stabilised at this point yet
+ QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
+ QTimer::singleShot( 0, this, SLOT( loadFileList() ) );
+ m_lister->cleanRebuild();
+}
+
+void PackageDetails::updateLogical()
+{
+ Cache &c = cache::Global::get( m_cache );
+ if ( !c.isOpen() ) {
+ QTimer::singleShot( 100, this, SLOT( updateLogical() ) );
+ return;
+ }
+ kdDebug() << "PackageDetails::updateLogical()" << endl;
+ entity::Package p = m_package;
+ kdDebug() << "PackageDetails::updateLogical: p = " << p.name()
+ << " p.component() = " << &p.component() << endl;
+ if ( !p.valid() ) return; // nothing to update
+ EntityActor *a = 0, *b = 0;
+
+ if ( p.canUpgrade() ) {
+ a = new EntityActor( p.upgrade() );
+ } else if ( p.canInstall() ) {
+ a = new EntityActor( p.install() );
+ } else if ( p.canKeep() ) {
+ a = new EntityActor( p.keep() );
+ }
+
+ if ( p.canRemove() ) {
+ b = new EntityActor( p.remove() );
+ }
+
+ if ( a ) {
+ m_logical->setEnabled( true );
+ m_logical->setText( u8( a->actor().prettyName() ) );
+ connect( m_logical, SIGNAL( clicked() ),
+ a, SLOT( destructiveAct() ) );
+ } else {
+ m_logical->setText( i18n( "Install" ) );
+ m_logical->setEnabled( false );
+ }
+
+ if ( b ) {
+ m_remove->setEnabled( true );
+ m_remove->setText( u8( b->actor().prettyName() ) );
+ connect( m_remove, SIGNAL( clicked() ),
+ b, SLOT( destructiveAct() ) );
+ } else {
+ m_remove->setText( i18n( "Remove" ) );
+ m_remove->setEnabled( false );
+ }
+
+ m_logicalAct = a;
+ m_removeAct = b;
+ // std::copy( r, r.last(), vr );
+
+ // r.consume( utils::upcastRange< entity::Entity >( p.depends() ) );
+}
+
+void PackageDetails::setHasForward( bool e ) {
+ m_toolbar->setItemEnabled( BForward, e );
+ // m_forward->setEnabled( e );
+}
+
+void PackageDetails::setHasBack( bool e ) {
+ m_toolbar->setItemEnabled( BBack, e );
+ // m_back->setEnabled( e );
+}
diff --git a/adept/libadept/packagedetails.h b/adept/libadept/packagedetails.h
new file mode 100644
index 0000000..655e226
--- /dev/null
+++ b/adept/libadept/packagedetails.h
@@ -0,0 +1,55 @@
+/* -*- C++ -*- adept/packagedetails.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <apt-front/cache/entity/package.h>
+#include <adept/packagedetailsui.h>
+#include <adept/lister.h>
+
+#include <qmutex.h>
+#include <qguardedptr.h>
+
+#ifndef EPT_PACKGEDETAILS_H
+#define EPT_PACKGEDETAILS_H
+
+class KToolBarButton;
+class QThread;
+
+namespace adept {
+
+using namespace aptFront;
+
+class PackageDetails : public PackageDetailsUi, public Lister::RangeProvider,
+ public cache::Observer
+{
+ Q_OBJECT
+public:
+ enum ButtonID { BForward, BBack, BShow };
+ PackageDetails( QWidget *p = 0, const char *n = 0 );
+ void setPackage( cache::entity::Package );
+ void setHasForward( bool );
+ void setHasBack( bool );
+ virtual Lister::Range listerRange();
+ void notifyPostChange( cache::component::Base * );
+ void notifyPreRebuild( cache::component::Base * );
+ void notifyPostRebuild( cache::component::Base * );
+signals:
+ void showList();
+ void back();
+ void forward();
+ void detailsRequested( Lister::Entity );
+protected slots:
+ void loadFileList();
+ void updateLogical();
+protected:
+ void loadFileListWorker();
+ cache::entity::StablePackage m_package;
+ QMutex m_qtMutex;
+ QThread *m_thread;
+ QGuardedPtr< EntityActor > m_logicalAct, m_removeAct;
+ int m_fileListRunning;
+
+};
+
+}
+
+#endif
diff --git a/adept/libadept/packagedetailsui.ui b/adept/libadept/packagedetailsui.ui
new file mode 100644
index 0000000..dacf7be
--- /dev/null
+++ b/adept/libadept/packagedetailsui.ui
@@ -0,0 +1,464 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>PackageDetailsUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>PackageDetailsUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>705</width>
+ <height>529</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="KToolBar">
+ <property name="name">
+ <cstring>m_toolbar</cstring>
+ </property>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>8</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>(title)</string>
+ </property>
+ </widget>
+ <widget class="adept::PackageInfo" row="1" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>m_info</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>8</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>75</height>
+ </size>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="3" column="2">
+ <property name="name">
+ <cstring>m_remove</cstring>
+ </property>
+ <property name="text">
+ <string>(remove)</string>
+ </property>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="3" column="1">
+ <property name="name">
+ <cstring>m_logical</cstring>
+ </property>
+ <property name="text">
+ <string>(logical)</string>
+ </property>
+ </widget>
+ <spacer row="3" column="3">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QTextBrowser" row="0" column="4" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>28</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="resizePolicy">
+ <enum>AutoOneFit</enum>
+ </property>
+ <property name="vScrollBarMode">
+ <enum>Auto</enum>
+ </property>
+ <property name="hScrollBarMode">
+ <enum>AlwaysOff</enum>
+ </property>
+ <property name="text">
+ <string>description...</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>16</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Package Relationships</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="adept::Lister" row="0" column="0">
+ <property name="name">
+ <cstring>m_lister</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>120</height>
+ </size>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Installed Files</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KFileDetailView" row="0" column="0">
+ <property name="name">
+ <cstring>m_fileList</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Additional Information</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="adept::TagChooser">
+ <property name="name">
+ <cstring>m_tags</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_source</cstring>
+ </property>
+ <property name="text">
+ <string>source</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_architecture</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>architecture</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_filename</cstring>
+ </property>
+ <property name="text">
+ <string>file</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_md5</cstring>
+ </property>
+ <property name="text">
+ <string>md5</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>61</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::TagChooser</class>
+ <header location="global">adept/tagchooser.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>adept::PackageInfo</class>
+ <header location="global">adept/packageinfo.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>adept::Lister</class>
+ <header location="global">adept/lister.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>KToolBar</class>
+ <header location="global">ktoolbar.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>1</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>KFileDetailView</class>
+ <header location="global">kfiledetailview.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>ktoolbar.h</includehint>
+ <includehint>adept/packageinfo.h</includehint>
+ <includehint>adept/lister.h</includehint>
+ <includehint>kfiledetailview.h</includehint>
+ <includehint>adept/tagchooser.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/packageinfo.cpp b/adept/libadept/packageinfo.cpp
new file mode 100644
index 0000000..dac788b
--- /dev/null
+++ b/adept/libadept/packageinfo.cpp
@@ -0,0 +1,181 @@
+/** -*- C++ -*-
+ @file adept/packageinfo.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qcolor.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <adept/packageinfo.h>
+#include <adept/utils.h>
+
+using namespace adept;
+using namespace cache;
+
+PackageInfo::PackageInfo( QWidget *p, const char *n )
+ : PackageInfoUi( p, n ), m_specificVersion( false )
+{
+ observeComponent< component::State >();
+}
+
+void PackageInfo::adjustFontSize( int s ) {
+ adept::adjustFontSize( m_status, s );
+ adept::adjustFontSize( m_change, s );
+ adept::adjustFontSize( m_section, s );
+ adept::adjustFontSize( m_installedSize, s );
+ adept::adjustFontSize( m_maintainer, s );
+ adept::adjustFontSize( m_candidateVer, s );
+ adept::adjustFontSize( m_installedVer, s );
+}
+
+void PackageInfo::hideStatus() {
+ m_status->hide();
+ m_change->hide();
+}
+
+namespace adept {
+
+QColor statusColor( entity::Package p )
+{
+ if ( !p.valid() )
+ return Qt::black;
+
+ QColor c = Qt::blue;
+ if (p.isInstalled())
+ c = Qt::darkGreen;
+ if (p.isUpgradable())
+ c = Qt::darkYellow;
+ if (p.isBroken())
+ c = Qt::red;
+ return c;
+}
+
+QColor actionColor( entity::Package p )
+{
+ if ( !p.valid() )
+ return Qt::black;
+
+ QColor c = Qt::blue;
+ if (p.markedNewInstall())
+ c = Qt::darkGreen;
+ if (p.markedUpgrade())
+ c = Qt::darkYellow;
+ if (p.markedReInstall())
+ c = Qt::darkYellow;
+ if (p.markedRemove())
+ c = Qt::darkRed;
+ if (p.markedPurge())
+ c = Qt::red;
+ if (p.willBreak())
+ c = Qt::red;
+ return c;
+}
+
+/* QString hexColor( QColor c )
+{
+ QString r( "#%1%2%3" );
+ return r.arg( c.red(), -2, 16 ).arg( c.green(), -2, 16 ).arg( c.blue(), -2, 16 );
+ } */
+
+QString colorify( QColor c, QString s )
+{
+ return QString( "<font color=\"" ) + c.name()
+ + "\">" + s + "</font>";
+}
+
+QString formatLongDescription( QString l )
+{
+ QRegExp rx( u8( "^(.*)\n" ) );
+ rx.setMinimal( true );
+ l.replace( rx, u8( "\\1</p><p>" ) );
+ rx = QRegExp( u8( "\\n[ ]*\\.\\n" ) );
+ l.replace( rx, u8( "</p><p>" ) );
+ rx = QRegExp( u8( "\n " ) );
+ l.replace( rx, u8( " " ) );
+ rx = QRegExp( u8( "\n - (.*)(\n|$)" ) );
+ rx.setMinimal( true );
+ l.replace( rx, u8( "\n<li>\\1</li>\n" ) );
+ l.replace( rx, u8( "\n<li>\\1</li>\n" ) );
+ return QString( "<p>" ) + l + u8( "</p>" );
+}
+
+void PackageInfo::setPackage( entity::Package p )
+{
+ kdDebug() << "PackageInfo::setPackage()" << endl;
+ // ho hum, probably XXX fix libapt-front?
+ setVersion( p.valid() ? p.anyVersion() : entity::Version(), false );
+}
+
+void PackageInfo::setVersion( entity::Version v, bool specific )
+{
+ m_specificVersion = specific;
+ m_version = v.stable();
+ if ( !m_version.valid() ) return;
+ kdDebug() << "PackageInfo::setVersion() (valid)" << endl;
+ m_section->setText(
+ labelFormat( i18n( "Section:" ), u8( v.section( u8( i18n( "Unknown" ) ) ) ) ) );
+ m_maintainer->setText(
+ labelFormat( i18n( "Maintainer:" ), u8( v.maintainer( u8( i18n( "Unknown" ) ) ) ),
+ false ) );
+
+ notifyPostChange( 0 );
+}
+
+void PackageInfo::notifyPostRebuild( component::Base *b ) {
+ return notifyPostChange( b );
+}
+
+void PackageInfo::notifyPostChange( component::Base * )
+{
+ if ( !m_version.valid() ) return;
+ entity::Version v = m_version;
+ entity::Package p = v.package();
+ QString cv = i18n( "n/a" ), iv = i18n( "n/a" ), is = i18n( "n/a" ), status, action;
+
+ if (p.valid()) {
+ entity::Version _cv = p.candidateVersion();
+ entity::Version _iv = p.installedVersion();
+
+ if (_cv.valid()) {
+ cv = u8( _cv.versionString() );
+ is = u8( _cv.installedSizeString() );
+ }
+
+ if (_iv.valid()) {
+ iv = _iv.versionString();
+ }
+ }
+
+ std::string unk = u8( i18n( "unknown" ) );
+ /* m_status->setText( i18n( "<nobr>Currently " ) + colorify(
+ statusColor( p ),
+ u8( p.statusString( unk ) ) )
+ + i18n( ", " ) + colorify(
+ actionColor( p ),
+ u8( p.actionString( unk ) ) ) + i18n( "
+ requested</nobr>" ) ); */
+ m_status->setText(
+ labelFormat( i18n( "Status:" ), colorify(
+ statusColor( p ),
+ u8( p.statusString( u8( i18n( "Unknown" ) ) ) ) ) ) );
+ m_change->setText(
+ labelFormat( i18n( "Requested change:" ), colorify(
+ actionColor( p ),
+ u8( p.actionString( u8( i18n( "Unknown" ) ) )
+ ) ) ) );
+
+ m_candidateVer->setText(
+ m_specificVersion ?
+ labelFormat( i18n( "Version:" ),
+ v.versionString() + "(" + i18n( "candidate" ) + " " + cv + ")" )
+ : labelFormat( i18n( "Candidate Version:" ), cv ) );
+ m_installedVer->setText(
+ labelFormat( i18n( "Installed Version:" ), iv ) );
+ m_installedSize->setText(
+ labelFormat( i18n( "Installed Size:" ), is ) );
+}
+
+}
diff --git a/adept/libadept/packageinfo.h b/adept/libadept/packageinfo.h
new file mode 100644
index 0000000..1a83c0d
--- /dev/null
+++ b/adept/libadept/packageinfo.h
@@ -0,0 +1,49 @@
+/* -*- C++ -*- adept/packageinfo.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/cache.h>
+#include <adept/packageinfoui.h>
+
+#ifndef EPT_PACKAGEINFO_H
+#define EPT_PACKAGEINFO_H
+
+namespace adept {
+
+using namespace aptFront;
+
+class PackageInfo : public PackageInfoUi, public cache::Observer
+{
+ Q_OBJECT
+public:
+ PackageInfo( QWidget *p, const char *n = 0 );
+public slots:
+ void setVersion( cache::entity::Version v, bool = true );
+ void setPackage( cache::entity::Package v );
+ void adjustFontSize( int );
+public:
+ void notifyPostChange( cache::component::Base * );
+ void notifyPostRebuild( cache::component::Base * );
+ void hideStatus();
+protected:
+ cache::entity::StableVersion m_version;
+ bool m_specificVersion;
+};
+
+inline QString labelFormat( const QString &what,
+ const QString &txt, bool nobr = true )
+{
+ QString ret = "<b><nobr>" + what + "</nobr></b>&nbsp;" + (nobr ? "<nobr>" : "")
+ + txt + (nobr ? "</nobr>" : "");
+ return ret;
+}
+
+QColor actionColor( cache::entity::Package p );
+QColor statusColor( cache::entity::Package p );
+
+QString formatLongDescription( QString in );
+QString colorify( QColor c, QString s );
+
+}
+
+#endif
diff --git a/adept/libadept/packageinfoui.ui b/adept/libadept/packageinfoui.ui
new file mode 100644
index 0000000..d7d5dc5
--- /dev/null
+++ b/adept/libadept/packageinfoui.ui
@@ -0,0 +1,180 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>PackageInfoUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>details</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>253</width>
+ <height>128</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form2</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>1</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>m_indent</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>16</width>
+ <height>5</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16</width>
+ <height>5</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="1">
+ <property name="name">
+ <cstring>m_maintainer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>maintainer</string>
+ </property>
+ <property name="alignment">
+ <set>AlignBottom</set>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="1">
+ <property name="name">
+ <cstring>m_candidateVer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>candidate version</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="6" column="1">
+ <property name="name">
+ <cstring>m_installedVer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>installed version</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>m_section</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>section</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="1">
+ <property name="name">
+ <cstring>m_installedSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>installed size</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>m_status</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>status</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>m_change</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>change</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/libadept/progress.cpp b/adept/libadept/progress.cpp
new file mode 100644
index 0000000..60a3bd3
--- /dev/null
+++ b/adept/libadept/progress.cpp
@@ -0,0 +1,58 @@
+#include <kapplication.h>
+#include <qcursor.h>
+#include <kdebug.h>
+#include <adept/progress.h>
+#include <adept/utils.h>
+
+using namespace adept;
+
+Progress::Progress()
+ : m_pbar( 0 ), m_sbar( 0 ), m_busy( false )
+{
+}
+
+void Progress::Update ()
+{
+ if (!m_sbar)
+ return;
+ if (!m_pbar) {
+ if (Percent) {
+ m_pbar = new KProgress( m_sbar );
+ m_pbar->setMinimumWidth( 80 );
+ m_pbar->setMaximumWidth( 120 );
+ m_pbar->setTextEnabled( false );
+ m_pbar->show();
+ m_sbar->addWidget( m_pbar, 0, true );
+ m_pbar->setTotalSteps( 100 );
+ }
+ MajorChange = true;
+ }
+ if (MajorChange) {
+ if ( !m_busy ) {
+ QApplication::setOverrideCursor( QCursor( Qt::BusyCursor ) );
+ m_busy = true;
+ }
+ m_sbar->message( u8( Op + "..." ) );
+ }
+ if (CheckChange (0.05) == false)
+ return;
+ // kdDebug() << "Progress::Update()" << endl;
+ if (m_pbar)
+ m_pbar->setProgress( Percent );
+ kapp->processEvents();
+}
+
+void Progress::Done ()
+{
+ kdDebug() << "Progress::Done()" << endl;
+
+ QApplication::restoreOverrideCursor();
+ m_busy = false;
+
+ if (m_sbar)
+ m_sbar->clear();
+ delete m_pbar;
+ m_pbar = 0;
+}
+
+Progress::~Progress() {}
diff --git a/adept/libadept/progress.h b/adept/libadept/progress.h
new file mode 100644
index 0000000..aef3d92
--- /dev/null
+++ b/adept/libadept/progress.h
@@ -0,0 +1,30 @@
+/** -*- C++ -*-
+ @file adept/progress.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <kprogress.h>
+#include <kstatusbar.h>
+#include <apt-pkg/progress.h>
+
+#ifndef EPT_PROGRESS_H
+#define EPT_PROGRESS_H
+
+namespace adept {
+
+class Progress : public OpProgress {
+public:
+ Progress();
+ virtual ~Progress();
+ virtual void Update();
+ virtual void Done();
+ void setStatusBar( KStatusBar *b ) { m_sbar = b; }
+protected:
+ KProgress *m_pbar;
+ KStatusBar *m_sbar;
+ bool m_busy;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/quickfilter.cpp b/adept/libadept/quickfilter.cpp
new file mode 100644
index 0000000..2cb0577
--- /dev/null
+++ b/adept/libadept/quickfilter.cpp
@@ -0,0 +1,79 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <qobjectlist.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <klineedit.h>
+#include <qcheckbox.h>
+
+#include "quickfilter.h"
+
+using namespace aptFront;
+using namespace adept;
+
+QuickFilterWidget::QuickFilterWidget( QWidget *parent, const char *name )
+ : QuickFilterUi( parent, name )
+{
+ setFocusProxy( m_match );
+ connect( m_match, SIGNAL( textChanged( const QString & ) ),
+ this, SLOT( textChanged( const QString & ) ) );
+ /* connect( m_reset, SIGNAL( clicked() ),
+ this, SLOT( reset() ) ); */
+ connect( m_match, SIGNAL( returnPressed() ),
+ this, SLOT( widgetsChanged() ) );
+ connect( &timer, SIGNAL( timeout() ),
+ this, SLOT( widgetsChanged() ) );
+
+ QObjectList *chld = queryList( "QCheckBox" );
+ QObjectListIt it( *chld );
+ while( it.current() != 0 ) {
+ connect( it.current(), SIGNAL( toggled( bool ) ),
+ this, SLOT( widgetsChanged() ) );
+ ++it;
+ }
+}
+
+void QuickFilterWidget::mouseReleaseEvent( QMouseEvent *e ) {
+ m_match->setFocus();
+ QuickFilterUi::mouseReleaseEvent( e );
+}
+
+void QuickFilterWidget::textChanged( const QString & )
+{
+ kdDebug() << "QuickFilterWidget::textChanged" << endl;
+ timer.start( 1000, true );
+}
+
+QuickFilterWidget::Predicate QuickFilterWidget::predicate()
+{
+ typedef QuickFilter< entity::Package > F;
+ F f; int w = 0;
+ if ( m_name->isChecked() ) w |= F::Name;
+ if ( m_description->isChecked() ) w |= F::Description;
+ if ( m_maintainer->isChecked() ) w |= F::Maintainer;
+
+ f.setMatch( u8( m_match->text() ) );
+ f.setWhat( w );
+
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void blockedSet( QCheckBox *b, bool v ) {
+ b->blockSignals( true );
+ b->setChecked( v );
+ b->blockSignals( false );
+}
+
+void QuickFilterWidget::predicateChanged() {
+ typedef QuickFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ m_match->blockSignals( true );
+ m_match->setText( f.match() );
+ m_match->blockSignals( false );
+ int w = f.what();
+
+ blockedSet( m_name, w & F::Name );
+ blockedSet( m_description, w & F::Description );
+ blockedSet( m_maintainer, w & F::Maintainer );
+}
+
diff --git a/adept/libadept/quickfilter.h b/adept/libadept/quickfilter.h
new file mode 100644
index 0000000..788c9da
--- /dev/null
+++ b/adept/libadept/quickfilter.h
@@ -0,0 +1,119 @@
+/** -*- C++ -*-
+ @file adept/quickfilter.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <qtimer.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/predicate/factory.h>
+#include <adept/quickfilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+#include <adept/utils.h>
+
+#ifndef EPT_QUICKFILTER_H
+#define EPT_QUICKFILTER_H
+
+class KLineEdit;
+
+namespace adept {
+
+template< typename T >
+struct QuickFilter : predicate::Implementation< T, QuickFilter< T > >,
+ InterfacingPredicate
+{
+ enum Type { Regex, Substring, Exact };
+ enum What { Name = 0x1, Description = 0x2, Maintainer = 0x4 };
+
+ QuickFilter()
+ : m_type( Substring ), m_match( "" ), m_what( Name | Description ) {
+ setupPredicate();
+ }
+
+ void setupPredicate() {
+ predicate::ArgumentList l;
+ l.push_back( m_match );
+ predicate::Predicate< T > a = not predicate::True< T >();
+ if ( m_what & Name ) a = a or predicate::Factory< T >::name( m_match );
+ if ( m_what & Description )
+ a = a or predicate::Factory< T >::description( m_match );
+ if ( m_what & Maintainer )
+ a = a or predicate::Factory< T >::maintainer( m_match );
+ m_op = a;
+ /* m_op = predicate::map(
+ predicate::predicate( predicate::Factory< T >::description( "" )
+ or predicate::Factory< T >::name( "" )
+ or predicate::Factory< T
+ >::maintainer( "" ) ), l ); */
+ }
+
+ std::string summary() const {
+ return u8( i18n( "Search: " ) ) + "\"" + m_match + "\"";
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const QuickFilter &o ) const {
+ return o.m_type == m_type && o.m_match == m_match;
+ }
+
+ std::string typeString() const {
+ if (m_type == Regex) return "Regular Expression";
+ if (m_type == Substring) return "Substring";
+ if (m_type == Exact) return "Exact Match";
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ std::string match() const {
+ return m_match;
+ }
+
+ void setMatch( const std::string &s ) {
+ m_match = s;
+ setupPredicate();
+ }
+
+ void setWhat( int w ) {
+ m_what = w;
+ setupPredicate();
+ }
+
+ int what() { return m_what; }
+
+ virtual void reset() {
+ m_match = "";
+ setupPredicate();
+ }
+
+protected:
+ Type m_type;
+ std::string m_match;
+ int m_what;
+ predicate::Predicate< T > m_op;
+};
+
+class QuickFilterWidget : public QuickFilterUi
+{
+ Q_OBJECT
+public:
+ QuickFilterWidget( QWidget *parent, const char *name = 0 );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+protected slots:
+ void textChanged( const QString & );
+protected:
+ void mouseReleaseEvent( QMouseEvent *e );
+ QTimer timer;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/quickfilterui.ui b/adept/libadept/quickfilterui.ui
new file mode 100644
index 0000000..d45c154
--- /dev/null
+++ b/adept/libadept/quickfilterui.ui
@@ -0,0 +1,130 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::QuickFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>QuickFilterUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>805</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>QuickFilterUi</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Search:&amp;nbsp;&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_match</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Match: </string>
+ </property>
+ <property name="textFormat">
+ <enum>AutoText</enum>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_name</cstring>
+ </property>
+ <property name="text">
+ <string>package name,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="text">
+ <string>description,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_maintainer</cstring>
+ </property>
+ <property name="text">
+ <string>maintainer.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/adept/libadept/sourceseditor.cpp b/adept/libadept/sourceseditor.cpp
new file mode 100644
index 0000000..3b04cf6
--- /dev/null
+++ b/adept/libadept/sourceseditor.cpp
@@ -0,0 +1,165 @@
+#include <fstream>
+#include <iostream>
+
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qpainter.h>
+
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+
+#include "sourceseditor.h"
+#include <adept/utils.h>
+
+using namespace aptFront;
+using namespace adept;
+
+SourcesEditor::SourcesEditor( std::string f, QWidget *p, const char *n )
+ : SourcesEditorUi( p, n ), m_filename( f )
+{
+ m_list->setSorting( -1 );
+ m_list->setAcceptDrops( true );
+ connect( m_close, SIGNAL( clicked() ),
+ this, SIGNAL( close() ) );
+ connect( m_apply, SIGNAL( clicked() ),
+ this, SLOT( save() ) );
+ connect( m_reset, SIGNAL( clicked() ),
+ this, SLOT( reset() ) );
+
+ connect( m_list, SIGNAL( contextMenuRequested(
+ QListViewItem *, const QPoint &, int) ),
+ this, SLOT( contextMenu( QListViewItem *, const QPoint & ) ) );
+
+ connect( m_newAdd, SIGNAL( clicked() ),
+ this, SLOT( newAdd() ) );
+
+ reset();
+}
+
+void SourcesEditor::newAdd()
+{
+ Sources::Entry e( true, Sources::Entry::Binary );
+ std::string s = m_newLine->text();
+ std::istringstream i( s );
+ i >> e;
+ new EntryItem( e, m_list );
+ m_newLine->setText( u8( "" ) );
+}
+
+void SourcesEditor::contextMenu( QListViewItem *, const QPoint &pt ) {
+ EntryItem *s = dynamic_cast< EntryItem * >( m_list->selectedItem() );
+ if (!s) return;
+ KPopupMenu *m = new KPopupMenu (this);
+ m->insertItem( s->entry().enabled() ? i18n( "Disable" ) : i18n( "Enable" ), 0 );
+ m->insertItem( i18n( "Clone" ), 1 );
+ m->insertItem( i18n( "Remove" ), 2 );
+ connect( m, SIGNAL( activated( int ) ),
+ this, SLOT( contextMenuActivated( int ) ) );
+ m->exec( pt );
+ delete m;
+}
+
+void SourcesEditor::contextMenuActivated( int i ) {
+ EntryItem *s = dynamic_cast< EntryItem * >( m_list->selectedItem() );
+ Sources::Entry e = s->entry();
+ if (i == 0) {
+ e.setEnabled( !e.enabled() );
+ s->setEntry( e );
+ }
+ if (i == 2)
+ delete s;
+ if (i == 1)
+ new EntryItem( e, m_list, s );
+}
+
+void SourcesEditor::reset() {
+ std::ifstream in( m_filename.c_str() );
+ m_sources.clear();
+ in >> m_sources;
+ utils::Range< Sources::Entry > r = m_sources.entries();
+ EntryItem *last = 0;
+ m_list->clear();
+ while( r != r.end() ) {
+ last = last ? new EntryItem( *r, m_list, last ) :
+ new EntryItem( *r, m_list );
+ ++ r;
+ }
+}
+
+void SourcesEditor::save() {
+ m_sources.clear();
+ EntryItem *i = dynamic_cast< EntryItem * >( m_list->firstChild() );
+ while (i) {
+ m_sources.add( i->entry() );
+ i = dynamic_cast< EntryItem * >( i->nextSibling() );
+ }
+ std::ofstream out( m_filename.c_str() );
+ out << m_sources;
+ std::cerr << "--" << m_sources << "--" << std::endl;
+ out.close();
+ reset(); // re-parse
+}
+
+/* void SourcesEditor::toggleSelectionEnabled()
+{
+ EntryItem *s = dynamic_cast< EntryItem * >( m_list->selectedItem() );
+ if (s) {
+ Sources::Entry e = s->entry();
+ e.setEnabled( !e.enabled() );
+ s->setEntry( e );
+ updateActions();
+ }
+ } */
+
+QString EntryItem::text( int c ) const {
+ if (entry().type() == Sources::Entry::Comment) {
+ if (c == 0)
+ if (entry().comment() == "")
+ return u8( "" );
+ else
+ return entry().typeString();
+ if (c == 1)
+ return entry().comment();
+ return u8( "" );
+ }
+
+ if (c == 0) return entry().typeString();
+ if (c == 1) return entry().url();
+ if (c == 2) return entry().distribution();
+ if (c == 3) return entry().components();
+ return u8( "" );
+}
+
+void EntryItem::setText( int c, const QString &_s )
+{
+ kdDebug() << "setText on column " << c << endl;
+ Sources::Entry e = entry();
+ std::string s;
+ s = _s.local8Bit();
+ if (c == 0) e.setTypeString( s );
+ if (c == 1)
+ if (entry().type() == Sources::Entry::Comment)
+ e.setComment( s );
+ else
+ e.setUrl( s );
+ if (c == 2) e.setDistribution( s );
+ if (c == 3) e.setComponents( s );
+ setEntry( e );
+ KListViewItem::setText( c, _s ); // stop qlistview from looping infinitely
+}
+
+void EntryItem::paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+{
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ QPixmap pm( width, height() );
+ QPainter _p( &pm );
+ if (!entry().enabled())
+ c = Qt::gray;
+ _cg.setColor( QColorGroup::Text, c );
+ KListViewItem::paintCell( &_p, _cg, column, width, AlignTop );
+ p->drawPixmap( 0, 0, pm );
+}
+
diff --git a/adept/libadept/sourceseditor.h b/adept/libadept/sourceseditor.h
new file mode 100644
index 0000000..32b474f
--- /dev/null
+++ b/adept/libadept/sourceseditor.h
@@ -0,0 +1,63 @@
+/** -*- C++ -*-
+ @file adept/sourceseditor.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-front/sources.h>
+#include <adept/sourceseditorui.h>
+#include <klistview.h>
+
+namespace adept {
+
+using namespace aptFront;
+
+class SourcesEditor : public SourcesEditorUi
+{
+ Q_OBJECT
+public:
+ SourcesEditor( std::string f, QWidget *p = 0, const char *n = 0 );
+public slots:
+ void save();
+ void reset();
+protected slots:
+ void contextMenu( QListViewItem *, const QPoint & );
+ void contextMenuActivated( int );
+ void newAdd();
+signals:
+ void close();
+protected:
+ aptFront::Sources m_sources;
+ std::string m_filename;
+};
+
+class EntryItem : public KListViewItem {
+public:
+ Sources::Entry entry() const {
+ return m_entry;
+ }
+ void setEntry( const Sources::Entry &e ) {
+ m_entry = e;
+ }
+ EntryItem( Sources::Entry e, KListView *v, EntryItem *prev )
+ : KListViewItem( v, prev ), m_entry( e ) {
+ init();
+ }
+ EntryItem( Sources::Entry e, KListView *v )
+ : KListViewItem( v ), m_entry( e ) {
+ init();
+ }
+ void init() {
+ setRenameEnabled( 0, false );
+ setRenameEnabled( 1, true );
+ setRenameEnabled( 2, true );
+ setRenameEnabled( 3, true );
+ }
+ QString text( int c ) const;
+ void setText( int c, const QString &s );
+ virtual void paintCell (QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment);
+protected:
+ Sources::Entry m_entry;
+};
+
+}
diff --git a/adept/libadept/sourceseditorui.ui b/adept/libadept/sourceseditorui.ui
new file mode 100644
index 0000000..43397d3
--- /dev/null
+++ b/adept/libadept/sourceseditorui.ui
@@ -0,0 +1,173 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::SourcesEditorUi</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>adept::SourcesEditorUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>683</width>
+ <height>442</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>adept::SourcesEditorUi</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Distribution</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Components</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_list</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ <property name="itemsMovable">
+ <bool>true</bool>
+ </property>
+ <property name="itemsRenameable">
+ <bool>true</bool>
+ </property>
+ <property name="dragEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>New Repository:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_newLine</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Write or paste a normal sources.list line here to add it to your sources</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_newAdd</cstring>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_reset</cstring>
+ </property>
+ <property name="text">
+ <string>Reset</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_apply</cstring>
+ </property>
+ <property name="text">
+ <string>Apply</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_close</cstring>
+ </property>
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>m_newLine</tabstop>
+ <tabstop>m_newAdd</tabstop>
+ <tabstop>m_reset</tabstop>
+ <tabstop>m_apply</tabstop>
+ <tabstop>m_close</tabstop>
+ <tabstop>m_list</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/statefilter.cpp b/adept/libadept/statefilter.cpp
new file mode 100644
index 0000000..45ee470
--- /dev/null
+++ b/adept/libadept/statefilter.cpp
@@ -0,0 +1,60 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <qcheckbox.h>
+#include <qobjectlist.h>
+#include "statefilter.h"
+
+using namespace aptFront;
+using namespace adept;
+
+StateFilterWidget::StateFilterWidget( QWidget *parent, const char *name )
+ : StateFilterUi( parent, name )
+{
+ QObjectList *chld = queryList( "QCheckBox" );
+ QObjectListIt it( *chld );
+ while( it.current() != 0 ) {
+ connect( it.current(), SIGNAL( toggled( bool ) ),
+ this, SLOT( widgetsChanged() ) );
+ ++it;
+ }
+}
+
+StateFilterWidget::Predicate StateFilterWidget::predicate()
+{
+ typedef StateFilter< entity::Package > F;
+ unsigned mask = 0;
+ if (m_installed->isChecked()) mask |= F::Installed;
+ if (m_notInstalled->isChecked()) mask |= F::NotInstalled;
+ if (m_upgradable->isChecked()) mask |= F::Upgradable;
+ if (m_keep->isChecked()) mask |= F::Keep;
+ if (m_install->isChecked()) mask |= F::Install;
+ if (m_remove->isChecked()) mask |= F::Remove;
+ if (m_upgrade->isChecked()) mask |= F::Upgrade;
+
+ StateFilter< entity::Package > f;
+ f.setMask( mask );
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void blockedSet( QCheckBox *b, bool v ) {
+ b->blockSignals( true );
+ b->setChecked( v );
+ b->blockSignals( false );
+}
+
+void StateFilterWidget::predicateChanged()
+{
+ typedef StateFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ unsigned mask = f.mask();
+ blockedSet( m_installed, mask & F::Installed );
+ blockedSet( m_notInstalled, mask & F::NotInstalled );
+ blockedSet( m_upgradable, mask & F::Upgradable );
+ blockedSet( m_keep, mask & F::Keep );
+ blockedSet( m_install, mask & F::Install );
+ blockedSet( m_upgrade, mask & F::Upgrade );
+ blockedSet( m_remove, mask & F::Remove );
+}
+
diff --git a/adept/libadept/statefilter.h b/adept/libadept/statefilter.h
new file mode 100644
index 0000000..570edb1
--- /dev/null
+++ b/adept/libadept/statefilter.h
@@ -0,0 +1,144 @@
+/** -*- C++ -*-
+ @file adept/filterwidgets.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/statefilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <iostream>
+#include <sstream>
+
+#ifndef EPT_STATEFILTER_H
+#define EPT_STATEFILTER_H
+
+class KLineEdit;
+
+namespace adept {
+
+template< typename T >
+struct StateFilter : predicate::Implementation< T, StateFilter< T > >,
+ InterfacingPredicate
+{
+ enum Mask { Installed = 1 << 0,
+ NotInstalled = 1 << 1,
+ Upgradable = 1 << 2,
+ Install = 1 << 3,
+ Remove = 1 << 4,
+ Keep = 1 << 5,
+ Upgrade = 1 << 6 };
+
+ StateFilter()
+ : m_mask( 0xff ) {
+ setupPredicate();
+ }
+
+ void setupPredicate() {
+ predicate::Predicate< T >
+ p0 = not predicate::True< T >(),
+ p1 = not predicate::True< T >();
+ if (m_mask & Installed)
+ p0 = p0 or (predicate::Factory< T >::member( &T::isInstalled )
+ and not predicate::Factory< T >::member( &T::isUpgradable ) );
+ if (m_mask & NotInstalled)
+ p0 = p0 or not predicate::Factory< T >::member( &T::isInstalled );
+ if (m_mask & Upgradable)
+ p0 = p0 or predicate::Factory< T >::member( &T::isUpgradable );
+
+ if (m_mask & Install)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedNewInstall );
+ if (m_mask & Remove)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedRemove );
+ if (m_mask & Keep)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedKeep );
+ if (m_mask & Upgrade)
+ p1 = p1 or predicate::Factory< T >::member( &T::markedUpgrade );
+
+ m_op = p0 and p1;
+ }
+
+ std::string summary() const {
+ std::ostringstream s;
+ std::vector< std::string > r;
+ s << "State filter: ";
+ if (m_mask & Installed && m_mask & NotInstalled && m_mask & Upgradable)
+ r.push_back( "Any State" );
+ else {
+ if (m_mask & Installed)
+ r.push_back( i18n( "Installed" ) );
+ if (m_mask & NotInstalled)
+ r.push_back( i18n( "Not Installed" ) );
+ if (m_mask & Upgradable)
+ r.push_back( i18n( "Upgradable" ) );
+ }
+ std::copy( r.begin(), r.end(),
+ std::ostream_iterator< std::string >( s, " " ) );
+ s << "; ";
+ r.clear();
+ if (m_mask & Install && m_mask & Remove
+ && m_mask & Keep && m_mask & Upgrade)
+ r.push_back( i18n( "Any Action" ) );
+ else {
+ if (m_mask & Install)
+ r.push_back( i18n( "Install" ) );
+ if (m_mask & Remove)
+ r.push_back( i18n( "Remove" ) );
+ if (m_mask & Keep)
+ r.push_back( i18n( "Keep" ) );
+ if (m_mask & Upgrade)
+ r.push_back( i18n( "Upgrade" ) );
+ }
+ std::copy( r.begin(), r.end(),
+ std::ostream_iterator< std::string >( s, " " ) );
+ return s.str();
+ }
+
+ unsigned mask() const {
+ return m_mask;
+ }
+
+ void setMask( unsigned m ) {
+ m_mask = m;
+ setupPredicate();
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const StateFilter &o ) const {
+ return o.m_op == m_op;
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ virtual void reset() {
+ m_mask = 0xff;
+ setupPredicate();
+ }
+
+protected:
+ unsigned m_mask;
+ predicate::Predicate< T > m_op;
+};
+
+class StateFilterWidget : public StateFilterUi
+{
+ Q_OBJECT
+public:
+ StateFilterWidget( QWidget *parent, const char *name = 0 );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+};
+
+}
+
+#endif
diff --git a/adept/libadept/statefilterui.ui b/adept/libadept/statefilterui.ui
new file mode 100644
index 0000000..1ef19e0
--- /dev/null
+++ b/adept/libadept/statefilterui.ui
@@ -0,0 +1,166 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::StateFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>StateFilterUi</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>574</width>
+ <height>55</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>StateFilterUi</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="text">
+ <string>Show: </string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_notInstalled</cstring>
+ </property>
+ <property name="text">
+ <string>not installed,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_installed</cstring>
+ </property>
+ <property name="text">
+ <string>installed,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_upgradable</cstring>
+ </property>
+ <property name="text">
+ <string>upgradable packages,</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>195</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_keep</cstring>
+ </property>
+ <property name="text">
+ <string>no changes,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_install</cstring>
+ </property>
+ <property name="text">
+ <string>install,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_remove</cstring>
+ </property>
+ <property name="text">
+ <string>removal,</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_upgrade</cstring>
+ </property>
+ <property name="text">
+ <string>upgrade requested.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>195</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>with: </string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="3" margin="11"/>
+</UI>
diff --git a/adept/libadept/tagchooser.cpp b/adept/libadept/tagchooser.cpp
new file mode 100644
index 0000000..6443663
--- /dev/null
+++ b/adept/libadept/tagchooser.cpp
@@ -0,0 +1,144 @@
+#include <klocale.h>
+#include <qdragobject.h>
+
+#include <apt-front/cache/component/tags.h>
+#include <apt-front/cache/component/packagetags.h>
+#include <adept/tagchooser.h>
+#include <adept/taglist.h>
+#include <adept/utils.h>
+
+using namespace adept;
+
+FacetItem::FacetItem( TagChooser *t )
+ : KListViewItem( t )
+{
+}
+
+void FacetItem::removeTag( TagItem::Tag t ) {
+ // kdDebug() << "removing tag " << t.fullname() << endl;
+ for ( QListViewItem *n, *i = firstChild(); i != 0; i = n ) {
+ n = i->nextSibling();
+ if ( dynamic_cast< TagItem * >( i )->tag() == t )
+ delete i;
+ }
+}
+
+TagItem::TagItem( FacetItem *p )
+ : KListViewItem( p ), m_toplevel( false )
+{
+}
+
+TagItem::TagItem( TagChooser *l )
+ : KListViewItem( l ), m_toplevel( true )
+{
+}
+
+QString TagItem::text( int c ) const
+{
+ if (c != 0) return u8( "" );
+ return QString( "[" ) + m_tag.name() + "] " + m_tag.shortDescription("");
+}
+
+TagChooser::TagChooser( QWidget *p, const char *n )
+ : KListView( p, n )
+{
+ observeComponent< cache::component::PackageTags >();
+ // addColumn( " ", 20 );
+ setRootIsDecorated( true );
+ addColumn( i18n( "Available Tags" ) );
+ setResizeMode( LastColumn );
+ setDragEnabled( true );
+ setAcceptDrops( true );
+ viewport()->setAcceptDrops( false );
+ // kdDebug() << "TagChooser: tags set" << endl;
+}
+
+void TagChooser::openToplevel() {
+ QListViewItem *i;
+ for ( i = firstChild(); i != 0; i = i->nextSibling() ) {
+ i->setOpen( true );
+ }
+}
+
+QDragObject *TagChooser::dragObject()
+{
+ TagItem *sel = dynamic_cast< TagItem * >( selectedItem() );
+ if (sel)
+ return new QTextDrag( sel->tag().fullname(), this );
+ return 0;
+}
+
+void TagChooser::dragEnterEvent( QDragEnterEvent *e )
+{
+ // hmmmmm :-)
+ kdDebug() << "TagChooser::dragEnterEvent" << endl;
+ e->accept( dynamic_cast< TagList * >( e->source() )
+ && QTextDrag::canDecode( e ) );
+ kdDebug() << dynamic_cast< TagList * >( e->source() )
+ << "; can decode " << QTextDrag::canDecode( e ) << endl;
+}
+
+void TagChooser::dropEvent( QDropEvent* e )
+{
+ TagList *tl = dynamic_cast< TagList * >( e->source() );
+ QString tag;
+ QTextDrag::decode( e, tag );
+ tl->setTags( tl->tags() - cache::Global::get().tags().tagByName(
+ static_cast< const char * >( tag.local8Bit() ) ) );
+}
+
+QString FacetItem::text( int column ) const
+{
+ if ( column == 0 )
+ return QString( "[" ) + m_facet.name() + "] " + m_facet.shortDescription( "" );
+ return u8( "" );
+}
+
+static bool drop( TagChooser::Tag t ) {
+ if ( t.facet().name() == "special" )
+ return true;
+ if ( t.name() == "TODO" )
+ return true;
+ return false;
+}
+
+void TagChooser::setTags( Tag::Set s )
+{
+ Tag::Set remove = m_tags - s;
+ Tag::Set add = s - m_tags;
+ m_tags = s;
+ Tag::Set::iterator i;
+
+ for ( i = add.begin(); i != add.end(); ++i ) {
+
+ if ( drop( *i ) )
+ continue;
+
+ FacetItem *fi = m_facets[ i->facet() ];
+ if ( fi == 0 ) {
+ fi = m_facets[ i->facet() ] = new FacetItem( this );
+ fi->setFacet( i->facet() );
+ }
+
+ TagItem *ti = new TagItem( fi );
+ ti->setTag( *i );
+ }
+
+ for ( i = remove.begin(); i != remove.end(); ++i ) {
+
+ if ( drop( *i ) )
+ continue;
+
+ FacetItem *fi = m_facets[ i->facet() ];
+ fi->removeTag( *i );
+ if ( fi->childCount() == 0 ) {
+ m_facets[ i->facet() ] = 0;
+ delete fi;
+ }
+ }
+
+}
+
+void TagChooser::notifyPreRebuild( cache::component::Base *b ) {
+ setTags( Tag::Set() );
+}
diff --git a/adept/libadept/tagchooser.h b/adept/libadept/tagchooser.h
new file mode 100644
index 0000000..082a60b
--- /dev/null
+++ b/adept/libadept/tagchooser.h
@@ -0,0 +1,82 @@
+/* -*- C++ -*- file adept/tagchooser.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <kdebug.h>
+#include <qlayout.h>
+
+#include <apt-front/utils/range.h>
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/entity/tag.h>
+
+#include <adept/extendablelist.h>
+
+#ifndef EPT_TAGCHOOSER_H
+#define EPT_TAGCHOOSER_H
+
+namespace adept {
+
+using namespace aptFront;
+
+class FacetItem;
+class FacetExtender;
+class TagChooser;
+
+class TagItem : public KListViewItem {
+public:
+ typedef cache::entity::Tag Tag;
+ virtual QString text( int ) const;
+ TagItem( TagChooser *t );
+ TagItem( FacetItem *t );
+ void setTag( Tag t ) { m_tag = t; }
+ Tag tag() { return m_tag; }
+protected:
+ bool m_toplevel;
+ Tag m_tag;
+};
+
+class FacetItem : public KListViewItem
+{
+public:
+ typedef cache::entity::Facet Facet;
+ virtual QString text( int ) const;
+ FacetItem( TagChooser *t );
+ void setFacet( Facet f ) { m_facet = f; }
+ void removeTag( TagItem::Tag );
+protected:
+ Facet m_facet;
+};
+
+class TagChooser : public KListView, public cache::Observer // ExtendableList
+{
+ Q_OBJECT
+public:
+ typedef cache::entity::Tag Tag;
+ typedef cache::entity::Facet Facet;
+ TagChooser( QWidget *p = 0, const char *n = 0 );
+ virtual void notifyPreRebuild( cache::component::Base * );
+public slots:
+ virtual void setTags( TagChooser::Tag::Set );
+ void setTitle( QString s ) {
+ setColumnText( 0, s );
+ }
+ void openToplevel();
+
+protected:
+ virtual void dragEnterEvent( QDragEnterEvent *e );
+ virtual void dropEvent( QDropEvent* e );
+ virtual void contentsDragEnterEvent( QDragEnterEvent *e ) {
+ kdDebug() << "TagChooser::contentsDragEnterEvent" << endl;
+ dragEnterEvent( e );
+ }
+ virtual void contentsDropEvent( QDropEvent *e ) {
+ kdDebug() << "TagChooser::contentsDropEvent" << endl;
+ dropEvent( e );
+ }
+ virtual QDragObject *dragObject();
+ Tag::Set m_tags;
+ std::map< Facet, FacetItem * > m_facets;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/tagfilter.cpp b/adept/libadept/tagfilter.cpp
new file mode 100644
index 0000000..4a08adc
--- /dev/null
+++ b/adept/libadept/tagfilter.cpp
@@ -0,0 +1,67 @@
+/* -*- C++ -*- libapt/tagfilter.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+
+#include <tagcoll/InputMerger.h>
+
+#include <adept/tagfilter.h>
+#include <adept/taglist.h>
+
+using namespace adept;
+
+TagFilterWidget::TagFilterWidget( QWidget *w, const char *n )
+ : TagFilterUi( w, n )
+{
+ m_wanted->setName( i18n( "Tags I Want (drop tags here)" ) );
+ m_unwanted->setName( i18n( "Tags I Do Not Want (drop tags here)" ) );
+
+ connect( m_wanted, SIGNAL( tagsChanged( TagList::Tag::Set ) ),
+ this, SLOT( wantedChanged() ) );
+ connect( m_unwanted, SIGNAL( tagsChanged( TagList::Tag::Set ) ),
+ this, SLOT( unwantedChanged() ) );
+}
+
+TagFilterWidget::Predicate TagFilterWidget::predicate()
+{
+ TagFilter< entity::Package > f;
+ f.setWanted( m_wanted->tags() );
+ f.setUnwanted( m_unwanted->tags() );
+ return predicate::adapt< entity::Entity >( f );
+}
+
+static void setTagsBlocking( TagList *l, TagList::Tag::Set s ) {
+ l->blockSignals( true );
+ l->setTags( s );
+ l->blockSignals( false );
+}
+
+void TagFilterWidget::predicateChanged()
+{
+ typedef TagFilter< entity::Package > F;
+ F f = downcast< F >( m_pred );
+ setTagsBlocking( m_wanted, f.wanted() );
+ setTagsBlocking( m_unwanted, f.unwanted() );
+ if ( item() && item()->list() ) {
+ setupColors();
+ item()->list()->delayedUpdateExtenders();
+ }
+}
+
+void TagFilterWidget::wantedChanged()
+{
+ setTagsBlocking( m_unwanted, m_unwanted->tags() - m_wanted->tags() );
+ setupColors();
+ widgetsChanged();
+ item()->list()->delayedUpdateExtenders();
+}
+
+void TagFilterWidget::unwantedChanged()
+{
+ setTagsBlocking( m_wanted, m_wanted->tags() - m_unwanted->tags() );
+ setupColors();
+ widgetsChanged();
+ item()->list()->delayedUpdateExtenders();
+}
diff --git a/adept/libadept/tagfilter.h b/adept/libadept/tagfilter.h
new file mode 100644
index 0000000..1afa44a
--- /dev/null
+++ b/adept/libadept/tagfilter.h
@@ -0,0 +1,113 @@
+/* -*- C++ -*- adept/tagfilter.h
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qpoint.h>
+
+#include <apt-front/cache/entity/entity.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/entity/tag.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/quickfilterui.h>
+#include <adept/filterlist.h>
+#include <adept/lister.h>
+#include <adept/taglist.h>
+#include <adept/tagfilterui.h>
+#include <adept/utils.h>
+
+#ifndef EPT_TAGFILTER_H
+#define EPT_TAGFILTER_H
+
+namespace adept {
+
+using namespace Tagcoll;
+
+template< typename T >
+struct TagFilter : predicate::Implementation< T, TagFilter< T > >,
+ InterfacingPredicate, cache::Observer
+{
+ typedef cache::entity::Tag Tag;
+
+ TagFilter() {
+ setupPredicate();
+ observeComponent< cache::component::Tags >();
+ }
+
+ void setupPredicate() {
+ Cache &cache = cache::Global::get(); // FIXME?
+ m_op = predicate::Factory< T >::tagSet( m_wanted );
+ for (Tag::Set::iterator i = m_unwanted.begin(); i != m_unwanted.end(); ++i ) {
+ m_op = m_op and not predicate::Factory< T >::tag( *i );
+ }
+ }
+
+ std::string summary() const {
+ return u8( i18n( "Tag Filter" ) );
+ }
+
+ void parseArguments( const predicate::ArgumentList & ) {}
+
+ bool operator==( const TagFilter &o ) const {
+ return o.m_wanted == m_wanted && o.m_unwanted == m_unwanted;
+ }
+
+ bool operator()( const T &p ) {
+ return m_op( p );
+ }
+
+ void setWanted( Tag::Set t ) {
+ m_wanted = t;
+ setupPredicate();
+ }
+
+ void setUnwanted( Tag::Set t ) {
+ m_unwanted = t;
+ setupPredicate();
+ }
+
+ Tag::Set wanted() const { return m_wanted; }
+ Tag::Set unwanted() const { return m_unwanted; }
+
+ void notifyPreRebuild( cache::component::Base * ) {
+ kdDebug() << "TagFilter pre-rebuild" << endl;
+ m_unwanted.clear(); m_wanted.clear();
+ }
+
+ void notifyPostRebuild( cache::component::Base * ) {
+ Cache &c = cache::Global::get( m_cache );
+ setupPredicate();
+ }
+
+ virtual void reset() {
+ m_wanted.clear();
+ m_unwanted.clear();
+ setupPredicate();
+ }
+
+protected:
+ predicate::Predicate< T > m_op;
+ Tag::Set m_wanted;
+ Tag::Set m_unwanted;
+};
+
+class TagFilterWidget : public TagFilterUi
+{
+ Q_OBJECT
+public:
+ TagFilterWidget( QWidget *p, const char *n );
+ virtual Predicate predicate();
+public slots:
+ void predicateChanged();
+ void wantedChanged();
+ void unwantedChanged();
+protected:
+ TagList *m_addingTo;
+ std::vector< entity::Tag > m_tagMenuMap;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/tagfilterui.ui b/adept/libadept/tagfilterui.ui
new file mode 100644
index 0000000..1f78b8a
--- /dev/null
+++ b/adept/libadept/tagfilterui.ui
@@ -0,0 +1,95 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>adept::TagFilterUi</class>
+<widget class="adept::PredicateInterface">
+ <property name="name">
+ <cstring>TagFilterUi</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>627</width>
+ <height>130</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <widget class="adept::TagList">
+ <property name="name">
+ <cstring>m_wanted</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>90</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="adept::TagList">
+ <property name="name">
+ <cstring>m_unwanted</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>adept::TagList</class>
+ <header location="global">adept/taglist.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
+ </image>
+</images>
+<includes>
+ <include location="global" impldecl="in declaration">adept/filterlist.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>adept/taglist.h</includehint>
+</includehints>
+</UI>
diff --git a/adept/libadept/taglist.cpp b/adept/libadept/taglist.cpp
new file mode 100644
index 0000000..22b3d58
--- /dev/null
+++ b/adept/libadept/taglist.cpp
@@ -0,0 +1,134 @@
+/* -*- C++ -*- adept/taglist.cpp
+ written by Peter Rockai <me@mornfall.net> */
+
+#include <qlabel.h>
+#include <qtimer.h>
+#include <kdebug.h>
+#include <qdragobject.h>
+#include <qevent.h>
+#include <klocale.h>
+
+#include <apt-front/cache/component/tags.h>
+#include <adept/taglist.h>
+#include <adept/utils.h>
+
+using namespace adept;
+
+TagLabel::TagLabel( Tag t, TagList *l, QWidget *p, const char *n )
+ : QHBox( p, n ), m_tag( t ), m_list( l )
+{
+ if ( t == Tag() ) {
+ m_description = new QLabel( QString( " " ) + i18n( "[none]" ), this );
+ } else {
+ m_remove = new QLabel( this );
+ m_remove->setPixmap( SmallIcon( u8( "cancel" ) ) );
+ m_remove->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ m_description = new QLabel( QString( " [" ) + t.fullname( "n/a" ) + "] "
+ + t.shortDescription( "n/a" ), this );
+ }
+}
+
+void TagLabel::mouseReleaseEvent( QMouseEvent *e ) {
+ if ( e->button() == Qt::LeftButton &&
+ dynamic_cast< QLabel * >( childAt( e->pos() ) ) == m_remove )
+ m_list->setTags( m_list->tags() - m_tag );
+}
+
+TagList::TagList( QWidget *p, const char *n )
+ : QVBox( p, n )
+{
+ m_name = new QLabel( this );
+ m_tagBox = new QVBox( this );
+ m_tagBox->setFrameShape( QFrame::Panel );
+ m_tagBox->setFrameShadow( QFrame::Sunken );
+ m_updateScheduled = false;
+ setAcceptDrops( true );
+ scheduleUpdateList();
+ m_tagSpacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
+}
+
+void TagList::setTags( Tag::Set t )
+{
+ m_tags = t;
+ scheduleUpdateList();
+ emit tagsChanged( m_tags );
+}
+
+void TagList::addTag( Tag t )
+{
+ if ( t == Tag() )
+ return;
+ m_tags += t;
+ scheduleUpdateList();
+ emit tagsChanged( m_tags );
+}
+
+void TagList::setName( QString n )
+{
+ m_name->setText( n );
+}
+
+void TagList::scheduleUpdateList()
+{
+ if (! m_updateScheduled) {
+ kdDebug() << "TagList: scheduling update" << endl;
+ QTimer::singleShot( 0, this, SLOT( updateList() ) );
+ m_updateScheduled = true;
+ }
+}
+
+void TagList::updateList()
+{
+ kdDebug() << "TagList (" + m_name->text() + "): updating list" << endl;
+ clearList();
+ if ( m_tags.empty() ) {
+ appendLabel( new TagLabel( Tag(), this, m_tagBox ) );
+ } else {
+ for ( Tag::Set::iterator i = m_tags.begin(); i != m_tags.end(); ++i ) {
+ appendLabel( new TagLabel( *i, this, m_tagBox ) );
+ }
+ }
+ m_tagBox->layout()->addItem( m_tagSpacer );
+ update();
+ parentWidget()->adjustSize();
+ m_updateScheduled = false;
+}
+
+void TagList::appendLabel( TagLabel *l )
+{
+ m_list.push_back( l );
+ l->show();
+}
+
+void TagList::mouseMoveEvent( QMouseEvent *e ) {
+ TagLabel *child = dynamic_cast< TagLabel * >( childAt( e->pos() )->parentWidget() );
+ if ( !child )
+ return;
+ QDragObject *d = new QTextDrag( child->tag().fullname( "" ), this );
+ d->dragCopy();
+}
+
+void TagList::dragEnterEvent( QDragEnterEvent *e ) {
+ kdDebug() << "TagList::dragEnterEvent" << endl;
+ e->accept( QTextDrag::canDecode( e ) );
+}
+
+void TagList::dropEvent( QDropEvent* e ) {
+ QString tag;
+ kdDebug() << "TagList: drop event" << endl;
+ QTextDrag::decode( e, tag );
+ try {
+ addTag( cache::Global::get().tags().tagByName(
+ static_cast< const char * >( tag.local8Bit() ) ) );
+ } catch (...) {} // not a tag, ignore
+ scheduleUpdateList();
+}
+
+void TagList::clearList()
+{
+ for (List::iterator i = m_list.begin(); i != m_list.end(); ++i ) {
+ delete *i;
+ }
+ m_list.clear();
+ m_tagBox->layout()->removeItem( m_tagSpacer );
+}
diff --git a/adept/libadept/taglist.h b/adept/libadept/taglist.h
new file mode 100644
index 0000000..4cd55a3
--- /dev/null
+++ b/adept/libadept/taglist.h
@@ -0,0 +1,75 @@
+/** -*- C++ -*-
+ @file adept/taglist.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <kiconloader.h>
+#include <vector>
+
+#include <apt-front/cache/entity/tag.h>
+
+#ifndef EPT_TAGLIST_H
+#define EPT_TAGLIST_H
+
+class QLabel;
+
+namespace adept {
+
+using namespace aptFront;
+
+class TagList;
+
+class TagLabel : public QHBox
+{
+ Q_OBJECT
+public:
+ typedef cache::entity::Tag Tag;
+ TagLabel( Tag t, TagList *l, QWidget *p = 0, const char *n = 0 );
+ Tag tag() { return m_tag; }
+protected:
+ void mouseReleaseEvent( QMouseEvent *e );
+ Tag m_tag;
+ QLabel *m_remove;
+ QLabel *m_description;
+ TagList *m_list;
+};
+
+class TagList : public QVBox
+{
+ Q_OBJECT
+public:
+ typedef cache::entity::Tag Tag;
+ TagList( QWidget *p = 0, const char *n = 0 );
+ void setTags( Tag::Set t );
+ void addTag( Tag t );
+ Tag::Set tags() { return m_tags; }
+ void setName( QString n );
+public slots:
+ void scheduleUpdateList();
+ void updateList();
+signals:
+ void tagsChanged( TagList::Tag::Set );
+protected:
+ void mouseMoveEvent( QMouseEvent *e );
+ void dropEvent( QDropEvent * );
+ void dragEnterEvent( QDragEnterEvent * );
+ void appendLabel( TagLabel * );
+ void clearList();
+
+ bool m_updateScheduled;
+ Tag::Set m_tags;
+ QLabel *m_name;
+ QVBox *m_tagBox;
+ QSpacerItem *m_tagSpacer;
+ typedef std::vector< TagLabel * > List;
+ List m_list;
+};
+
+}
+
+#endif
diff --git a/adept/libadept/threadutils.cpp b/adept/libadept/threadutils.cpp
new file mode 100644
index 0000000..722f75d
--- /dev/null
+++ b/adept/libadept/threadutils.cpp
@@ -0,0 +1,44 @@
+/** -*- C++ -*-
+ @file adept/utils.cpp
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <map>
+#include <adept/utils.h>
+
+namespace adept {
+
+QMutex Threads::serialize;
+Threads::Queue Threads::threads;
+
+void Threads::wait() {
+ static std::map< QMutex *, int > locked;
+ while ( !threads.empty() ) {
+ QThread *current = threads.front().first;
+ if ( current->finished() ) {
+ delete current;
+ threads.pop_front();
+ continue;
+ }
+ for ( Queue::iterator thr = threads.begin(); thr != threads.end(); ++thr ) {
+ ++locked[ thr->second ];
+ thr->second->lock();
+ }
+ kapp->processEvents();
+ for ( Queue::iterator thr = threads.begin(); thr != threads.end(); ++thr ) {
+ while ( locked[ thr->second ] > 0 ) {
+ thr->second->unlock();
+ --locked[ thr->second ];
+ }
+ }
+ usleep( 50000 );
+ }
+}
+
+void Threads::enqueue( QThread *t, QMutex *m )
+{
+ threads.push_back( std::make_pair( t, m ) );
+ t->start();
+}
+
+}
diff --git a/adept/libadept/utils.h b/adept/libadept/utils.h
new file mode 100644
index 0000000..6c3a3d3
--- /dev/null
+++ b/adept/libadept/utils.h
@@ -0,0 +1,71 @@
+/** -*- C++ -*-
+ @file adept/utils.h
+ @author Peter Rockai <me@mornfall.net>
+*/
+
+#include <qthread.h>
+#include <qstring.h>
+#include <kapplication.h>
+#include <string>
+#include <queue>
+#include <kdebug.h>
+
+#ifndef EPT_UTILS_H
+#define EPT_UTILS_H
+
+namespace adept {
+
+inline QString u8( std::string s ) {
+ return QString::fromUtf8( s.c_str() );
+}
+
+inline std::string u8( QString s ) {
+ return std::string( s.utf8() );
+}
+
+inline QString u8( const char *s ) {
+ return QString::fromUtf8( s );
+}
+
+struct Threads {
+ static QMutex serialize;
+ typedef std::deque< std::pair< QThread *, QMutex * > > Queue;
+ static Queue threads;
+ static void enqueue( QThread *t, QMutex *m );
+ static void wait();
+};
+
+template< typename F, typename P >
+struct AsyncCall : public QThread
+{
+ AsyncCall( F f, P p ) : func( f ), param( p ) {}
+ virtual void run()
+ {
+ // kdDebug() << "Thread waiting for mutex..." << endl;
+ Threads::serialize.lock();
+ // kdDebug() << "starting thread (mutex acquired)" << endl;
+ func( param );
+ // kdDebug() << "finishing thread (releasing mutex)" << endl;
+ Threads::serialize.unlock();
+ }
+ virtual ~AsyncCall() {}
+protected:
+ F func;
+ P param;
+};
+
+
+template< typename F, typename P > AsyncCall< F, P > *asyncCall( F f, P p ) {
+ return new AsyncCall< F, P >( f, p );
+}
+
+inline static void adjustFontSize( QWidget *w, int off ) {
+ QFont f = w->font();
+ f.setPointSize( f.pointSize() + off ); // a bit smaller font...
+ w->setFont( f );
+ w->updateGeometry();
+}
+
+}
+
+#endif
diff --git a/adept/libadept/view.cpp b/adept/libadept/view.cpp
new file mode 100644
index 0000000..207277c
--- /dev/null
+++ b/adept/libadept/view.cpp
@@ -0,0 +1,153 @@
+#include <apt-front/predicate/combinators.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/quickfilter.h>
+#include <adept/statefilter.h>
+#include <adept/tagfilter.h>
+
+#include <adept/packagedetails.h>
+#include <adept/view.h>
+#include <adept/filtersidebar.h>
+
+using namespace adept;
+
+View::View( QWidget *p, const char *n )
+ : QSplitter( p, n )
+{
+ setOrientation( Qt::Vertical );
+ m_flist = new FilterList( this );
+ m_bottom = new QSplitter( this );
+ m_bottom->setOrientation( Qt::Horizontal );
+ m_lister = new Lister( m_bottom );
+ m_flist->plugLister( m_lister );
+ m_sidebar = new FilterSidebar( m_bottom );
+
+ connect( m_lister, SIGNAL( cardinalityChanged( const Lister::Cardinality & ) ),
+ m_sidebar, SLOT( setCardinality( const Lister::Cardinality & ) ) );
+
+ m_flist->setHiddenPredicate(
+ predicate::adapt< entity::Entity >(
+ predicate::Package::member( &entity::Package::hasVersion ) ) );
+ m_flist->appendPredicate(
+ predicate::adapt< entity::Entity >(
+ StateFilter< entity::Package >() ) );
+ m_flist->appendPredicate(
+ predicate::adapt< entity::Entity >(
+ TagFilter< entity::Package >() ) );
+ m_flist->appendPredicate(
+ predicate::adapt< entity::Entity >(
+ QuickFilter< entity::Package >() ) );
+
+ m_lister->setRangeProvider( this );
+
+ QTimer::singleShot( 0, this, SLOT( delayed() ) );
+}
+
+Lister::Range View::listerRange() {
+ component::Packages &cp = cache::Global::get().packages();
+ return cp.sorted();
+ // return range( cp.packagesBegin(), cp.packagesEnd() );
+}
+
+void View::hideTags() {
+ QValueList< int > szl;
+ szl.append( 0 ); szl.append( 1 );
+ setSizes( szl );
+}
+
+void View::hideFilters() {
+ QValueList< int > szl;
+ szl.append( 1 ); szl.append( 0 );
+ m_bottom->setSizes( szl );
+}
+
+predicate::Predicate< entity::Entity > View::previewPredicate()
+{
+ return predicate::adapt< entity::Entity >(
+ (not predicate::Package::member( &entity::Package::markedKeep ))
+ or predicate::Package::member( &entity::Package::isBroken )
+ or predicate::Package::member( &entity::Package::willBreak ) );
+}
+
+void View::setUpgradeMode()
+{
+ setPreviewMode();
+ filterList()->setHiddenPredicate(
+ previewPredicate() or predicate::adapt< entity::Entity >(
+ predicate::Package::member( &entity::Package::isUpgradable ) ) );
+}
+
+void View::setPreviewMode()
+{
+ filterList()->setHiddenPredicate( previewPredicate() );
+ hideFilters();
+ hideTags();
+}
+
+void View::delayed()
+{
+ // cleanRebuild();
+}
+
+Browser::Browser( QWidget *p, const char *n )
+ : QWidgetStack( p, n ), m_currentValid( false )
+{
+ m_current = entity::Entity();
+ addWidget( m_view = new View( this ) );
+ addWidget( m_details = new PackageDetails( this ) );
+ connect( m_view->lister(), SIGNAL( detailsRequested( Lister::Entity ) ),
+ this, SLOT( show( Lister::Entity ) ) );
+ connect( m_details, SIGNAL( showList() ),
+ this, SLOT( showList() ) );
+ connect( m_details, SIGNAL( back() ),
+ this, SLOT( back() ) );
+ connect( m_details, SIGNAL( forward() ),
+ this, SLOT( forward() ) );
+ connect( m_details, SIGNAL( detailsRequested( Lister::Entity ) ),
+ this, SLOT( show( Lister::Entity ) ) );
+}
+
+void Browser::showList()
+{
+ raiseWidget( m_view );
+}
+
+void Browser::back()
+{
+ m_forward.push_back( m_current );
+ m_current = m_back.back();
+ m_back.pop_back();
+ doShow( m_current );
+}
+
+void Browser::forward()
+{
+ m_back.push_back( m_current );
+ m_current = m_forward.back();
+ m_forward.pop_back();
+ doShow( m_current );
+}
+
+void Browser::doShow( Lister::Entity e )
+{
+ m_details->setHasForward( !m_forward.empty() );
+ m_details->setHasBack( !m_back.empty() );
+ raiseWidget( m_details );
+ m_details->setPackage( downcast< entity::Package >( e ) );
+}
+
+void Browser::show( Lister::Entity e )
+{
+ m_forward.clear();
+ if ( m_currentValid )
+ m_back.push_back( m_current );
+ m_currentValid = true;
+ m_current = e.stable();
+ doShow( e );
+}
+
+/* Kolik existencialistu je potreba k zasroubovani zarovky?
+ Dva. Jeden sroubuje zarovku, a druhy premysli jak zarovka
+ sama o sobe predstavuje jednotlivy zarivy bod v subjektivni
+ realite v podsveti nekonecne absurdity dosahujici neuprimny
+ vesmir nicoty. */
diff --git a/adept/libadept/view.h b/adept/libadept/view.h
new file mode 100644
index 0000000..ea6c6f5
--- /dev/null
+++ b/adept/libadept/view.h
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+
+#include <deque>
+
+#include <qsplitter.h>
+#include <qwidgetstack.h>
+
+#include <adept/lister.h>
+#include <adept/filterlist.h>
+
+#ifndef EPT_VIEW_H
+#define EPT_VIEW_H
+
+class QSplitter;
+
+namespace adept {
+
+class FilterSidebar;
+class PackageDetails;
+
+class View: public QSplitter, public Lister::RangeProvider {
+ Q_OBJECT
+public:
+ View( QWidget *p = 0, const char *n = 0 );
+ FilterList *filterList() { return m_flist; }
+ Lister *lister() { return m_lister; }
+ virtual Lister::Range listerRange();
+public slots:
+ void cleanRebuild() { m_lister->cleanRebuild(); }
+ void hideFilters();
+ void hideTags();
+ void setPreviewMode();
+ void setUpgradeMode();
+protected slots:
+ void delayed();
+protected:
+ predicate::Predicate< entity::Entity > previewPredicate();
+ QSplitter *m_bottom;
+ FilterList *m_flist;
+ Lister *m_lister;
+ FilterSidebar *m_sidebar;
+};
+
+class Browser : public QWidgetStack {
+ Q_OBJECT
+public:
+ Browser( QWidget *p = 0, const char *n = 0 );
+ View *searchView() const { return m_view; }
+public slots:
+ void forward();
+ void back();
+ void show( Lister::Entity e );
+ void showList();
+ void doShow( Lister::Entity e );
+protected:
+ typedef std::deque< Lister::Entity > Deque;
+ Deque m_forward, m_back;
+ entity::Entity m_current;
+ View *m_view;
+ PackageDetails *m_details;
+ bool m_currentValid;
+};
+
+}
+
+#endif
diff --git a/adept/manager/Makefile.am b/adept/manager/Makefile.am
new file mode 100644
index 0000000..a7b8a0f
--- /dev/null
+++ b/adept/manager/Makefile.am
@@ -0,0 +1,20 @@
+bin_PROGRAMS = adept_manager
+noinst_HEADERS = app.h
+adept_manager_SOURCES = main.cpp app.cpp
+adept_manager_LDADD = ../adept/libadept.la -lapt-front $(LIBEPT_LIBS) $(LIBTAGCOLL2_LIBS) $(LIBWIBBLE_LIBS) $(LIB_KIO) $(LIB_KDEUI) ../kubuntu_upgrader/libkubuntuupgradewizard.la
+adept_manager_LDFLAGS = -L/usr/lib/debug
+INCLUDES = $(all_includes) $(LIBAPT_FRONT_CFLAGS) $(LIBEPT_CFLAGS) $(LIBTAGCOLL2_CFLAGS) $(LIBWIBBLE_CFLAGS) -I$(srcdir)/.. -I..
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII
+METASOURCES = AUTO
+KDE_ICON = AUTO
+
+rcdir = $(kde_datadir)/adept_manager
+rc_DATA = adept_managerui.rc
+
+#shelldesktopdir = $(kde_appsdir)/System
+xdg_apps_DATA = adept_manager.desktop
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(EXTRACTRC) `find . -name "*.rc"` >> rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/adept.pot
diff --git a/adept/manager/adept_manager.desktop b/adept/manager/adept_manager.desktop
new file mode 100644
index 0000000..6e7e311
--- /dev/null
+++ b/adept/manager/adept_manager.desktop
@@ -0,0 +1,43 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Adept Manager
+Name[ca]=Gestor Adept
+Name[ga]=Bainisteoir Adept
+Name[ja]=Adept マネージャ
+Name[pt]=Gestor do Adept
+Name[sv]=Adept-hantering
+GenericName=Manage Packages
+GenericName[ca]=Gestiona de paquets
+GenericName[ga]=Bainistigh Pacáistí
+GenericName[ja]=パッケージを管理
+GenericName[pt]=Gestão de Pacotes
+GenericName[sv]=Hantera paket
+Exec=/opt/kde3/bin/adept_manager
+Categories=Qt;KDE;System;
+Icon=adept_manager
+Type=Application
+X-KDE-SubstituteUID=true
+Comment=Manage installed and available software
+Comment[bg]=Управление на инсталиран и наличен софтуер
+Comment[ca]=Gestiona el programari instal·lat i disponible
+Comment[cs]=Správa nainstalovaného a dostupného softwaru
+Comment[da]=Håndtér installeret og tilgængelig software
+Comment[de]=Verwaltet installierte und verfügbare Software
+Comment[el]=Διαχείριση εγκατεστημένου και διαθέσιμου λογισμικού
+Comment[es]=Administrar el software instalado y disponible
+Comment[et]=Paigaldatud ja saadaoleva tarkvara haldamine
+Comment[fr]=Gestion des logiciels disponibles et installés
+Comment[ga]=Bainistigh bogearraí atá suiteáilte agus ar fáil
+Comment[gl]=Xestiona o software instalado e disponíbel
+Comment[it]=Gestisce il software installato e disponibile
+Comment[ja]=インストール済み及び利用可能なソフトウェアを管理
+Comment[ka]=დაყენებული და ხელმისაწვდომი პროგრამების მართვა
+Comment[lt]=Įdiegtų ir prieinamų programų tvarkymas
+Comment[nl]=Beheren van geïnstalleerde en beschikbare software software
+Comment[pt]=Gerir o 'software' instalado e disponível
+Comment[sk]=Manažuje inštalovaný a dostupný software
+Comment[sr]=Управља инсталираним и доступним програмима
+Comment[sr@Latn]=Upravlja instaliranim i dostupnim programima
+Comment[sv]=Hantera installerad och tillgänglig programvara
+Comment[xx]=xxManage installed and available softwarexx
+Terminal=false
diff --git a/adept/manager/adept_managerui.rc b/adept/manager/adept_managerui.rc
new file mode 100644
index 0000000..add78d4
--- /dev/null
+++ b/adept/manager/adept_managerui.rc
@@ -0,0 +1,38 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="6" name="adept">
+ <MenuBar>
+ <Menu name="file" noMerge="1">
+ <text>&amp;Adept</text>
+ <Action name="update" />
+ <Action name="sourceseditor" />
+ <Action name="commit" />
+ <Separator />
+ <Action name="upgrade" />
+ <Action name="dist-upgrade" />
+ <Separator />
+ <Action name="file_quit" />
+ </Menu>
+ <Menu name="view" noMerge="1">
+ <text>&amp;View</text>
+ <Action name="packagelist" />
+ <Action name="download_out" />
+ <Action name="commit_out" />
+ </Menu>
+ <Menu name="edit" noMerge="1">
+ <text>&amp;Edit</text>
+ <Action name="edit_undo" />
+ <Action name="edit_redo" />
+ </Menu>
+ </MenuBar>
+
+ <ToolBar name="mainToolBar" noMerge="1">
+ <Action name="update" />
+ <Action name="preview" />
+ <Action name="commit" />
+ <Separator />
+ <Action name="dist-upgrade" />
+ <Separator/>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ </ToolBar>
+</kpartgui>
diff --git a/adept/manager/app.cpp b/adept/manager/app.cpp
new file mode 100644
index 0000000..832016e
--- /dev/null
+++ b/adept/manager/app.cpp
@@ -0,0 +1,450 @@
+#define KUBUNTU
+
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qwidgetstack.h>
+#include <qsplitter.h>
+#include <qtimer.h>
+#include <qfile.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kaction.h>
+#include <kactionclasses.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kparts/part.h>
+#include <kstatusbar.h>
+#include <kprocess.h>
+
+// bleeeh
+#include <apt-pkg/init.h>
+#include <cassert>
+
+#include <apt-front/manager.h>
+#include <apt-front/init.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/acqprogresswidget.h>
+#include <adept/progress.h>
+#include <adept/utils.h>
+
+#ifdef KUBUNTU
+#include <kubuntu_upgrader/upgradewizard.h>
+#endif
+
+#include "app.h"
+
+using namespace aptFront;
+using namespace aptFront::cache;
+using namespace adept;
+
+TestApp::TestApp() {
+ kdDebug() << "ctor running" << endl;
+ setAcceptReadOnly( true );
+
+ setupActions();
+ setupGUI();
+
+ m_rebuilds = 0;
+ m_stack = new QWidgetStack( this );
+
+ m_stack->addWidget( m_loading = new QLabel( i18n( "Loading, please wait..." ), m_stack ) );
+ m_loading->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+
+ Application::setStatusBar( statusBar() );
+
+ setCentralWidget( m_stack );
+
+ QTimer::singleShot(
+ 0, this,
+ SLOT( delayed() ) );
+
+ kdDebug() << "ctor done" << endl;
+
+#ifdef KUBUNTU
+ m_upgradeButtonAdded = false;
+#endif
+}
+
+void TestApp::guardLister( Lister *l )
+{
+ connect( l, SIGNAL( rebuildStarted() ),
+ this, SLOT( rebuildStarted() ) );
+ connect( l, SIGNAL( rebuildFinished() ),
+ this, SLOT( rebuildFinished() ) );
+}
+
+void TestApp::delayed() {
+ initialize();
+
+ observeComponent< component::State >();
+
+ m_stack->addWidget( m_list = new adept::Browser( m_stack ) );
+ guardLister( m_list->searchView()->lister() );
+
+ m_stack->addWidget( m_sources = new adept::SourcesEditor(
+ _config->FindFile(
+ "Dir::Etc::sourcelist").c_str(),
+ this ) );
+
+ connect ( m_sources, SIGNAL( close() ),
+ this, SLOT( closeSources() ) );
+
+ // set up preview widget
+ m_stack->addWidget( m_preview = new adept::Browser( m_stack ) );
+
+ m_preview->searchView()->setPreviewMode();
+ guardLister( m_preview->searchView()->lister() );
+
+ m_stack->addWidget( m_progress = new adept::AcqProgressWidget( m_stack ) );
+ m_stack->addWidget( m_commitProgress = new adept::CommitProgress( m_stack ) );
+
+ m_stack->raiseWidget( m_list );
+
+ addMode( Sources, m_sourcesAction, m_sources );
+ addMode( Preview, m_previewAction, m_preview );
+ addMode( Download, m_progressAction, m_progress );
+ addMode( Commit, m_commitProgressAction, m_commitProgress );
+
+ m_list->searchView()->lister()->cleanRebuild();
+ m_preview->searchView()->lister()->cleanRebuild();
+ setActionsEnabled( true );
+ statusBar()->clear();
+ notifyPostChange( 0 );
+}
+
+void TestApp::setupActions()
+{
+ (new KAction(
+ i18n( "Fetch Updates" ), u8( "adept_update" ),
+ 0, this, SLOT( update() ), actionCollection(),
+ "update" ))->setEnabled( false );
+
+ (new KAction(
+ i18n( "Reload Cache" ), u8( "adept_reload" ),
+ 0, this, SLOT( reload() ), actionCollection(),
+ "reload" ))->setEnabled( false );
+
+ m_upgrade = new KAction(
+ i18n( "Safe Upgrade" ), u8( "adept_upgrade" ),
+ 0, this, SLOT( upgrade() ), actionCollection(),
+ "upgrade" );
+ m_distUpgrade = new KAction(
+ i18n( "Full Upgrade" ), u8( "adept_distupgrade" ),
+ 0, this, SLOT( distUpgrade() ), actionCollection(),
+ "dist-upgrade" );
+ m_commit = new KAction(
+ i18n( "Apply Changes" ), u8( "adept_commit" ),
+ 0, this, SLOT( commit() ), actionCollection(),
+ "commit" );
+
+ m_sourcesAction = new KToggleAction(
+ i18n( "Manage Repositories" ), u8( "adept_sourceseditor" ),
+ 0, this, SLOT( toggleSources() ), actionCollection(),
+ "sourceseditor" );
+ m_previewAction = new KToggleAction(
+ i18n( "Preview Changes" ), u8( "adept_preview" ),
+ 0, this, SLOT( togglePreview() ), actionCollection(),
+ "preview" );
+
+ m_progressAction = new KToggleAction(
+ i18n( "Show Last Download" ), u8( "adept_download_out" ),
+ 0, this, SLOT( toggleDownload() ), actionCollection(),
+ "download_out" );
+
+ m_commitProgressAction = new KToggleAction(
+ i18n( "Show Last DPkg Run" ), u8( "adept_commit_out" ),
+ 0, this, SLOT( toggleCommit() ), actionCollection(),
+ "commit_out" );
+
+ m_listAction = new KToggleAction(
+ i18n( "Show Package List" ), u8( "adept_packagelist" ),
+ 0, this, SLOT( closeModes() ), actionCollection(),
+ "packagelist" );
+
+ m_sourcesAction->setEnabled( true );
+ m_progressAction->setEnabled( false );
+ m_previewAction->setEnabled( false );
+ m_commitProgressAction->setEnabled( false );
+ m_listAction->setEnabled( false );
+
+ m_modesClosed = m_listAction;
+ m_listAction->setChecked( true );
+
+ m_undo = KStdAction::undo( this, SLOT( undo() ), actionCollection() );
+ m_redo = KStdAction::redo( this, SLOT( redo() ), actionCollection() );
+
+ m_distUpgrade->setEnabled( false );
+ m_upgrade->setEnabled( false );
+
+ m_commit->setEnabled( false );
+ KStdAction::quit( this, SLOT( close() ), actionCollection() );
+ setHistoryEnabled( false );
+ createStandardStatusBarAction();
+}
+
+void TestApp::setHistoryEnabled( bool e ) {
+ if ( e && history() ) {
+ m_undo->setEnabled( history()->canUndo() );
+ m_redo->setEnabled( history()->canRedo() );
+ } else {
+ m_undo->setEnabled( false );
+ m_redo->setEnabled( false );
+ }
+}
+
+void TestApp::setActionsEnabled( bool e )
+{
+ m_actionsEnabled = e;
+ updateActionState();
+}
+
+void TestApp::updateActionState()
+{
+ bool e = m_actionsEnabled;
+ bool w = cache::Global::get().writeable();
+ component::State &s = cache::Global::get().state();
+ KActionPtrList a = actionCollection()->actions();
+ /* View menus seem to be BROKEN HERE?! */
+ for (KActionPtrList::iterator i = a.begin(); i != a.end(); ++i) {
+ if ( u8( (*i)->name() ) == u8( "update" ) ) {
+ (*i)->setEnabled( e && w );
+ } else if ( u8( (*i)->name() ) == u8( "preview" ) ) {
+ (*i)->setEnabled( e );
+ } else {
+ (*i)->setEnabled(e && w);
+ }
+ }
+ setHistoryEnabled( e );
+ m_commit->setEnabled( e && w && s.changed() );
+ m_upgrade->setEnabled( e && w && s.upgradableCount() );
+ m_distUpgrade->setEnabled( e && w && s.upgradableCount() );
+}
+
+template< typename T, typename In >
+void TestApp::aptAction( In b, In e ) {
+ const KAction *a = dynamic_cast<const KAction *>( sender() ); // HACK
+ typename T::Vector v = T::list();
+ for (typename T::Vector::iterator i = v.begin(); i != v.end(); ++i) {
+ if( a->name() == i->name() ) {
+ (*i)( b, e );
+ return;
+ }
+ }
+}
+
+void TestApp::notifyPostRebuild( component::Base *b )
+{
+ Application::notifyPostRebuild( b );
+ notifyPostChange( b );
+}
+
+void TestApp::notifyPreChange( component::Base *b )
+{
+ Application::notifyPreChange( b );
+ checkpoint();
+}
+
+void TestApp::notifyPostChange( component::Base *b )
+{
+ Application::notifyPostChange( b );
+ updateActionState();
+}
+
+void TestApp::closeEvent( QCloseEvent *e ) {
+ cache::component::State &s = cache::Global::get().state();
+ if (s.changed()) {
+ if (KMessageBox::warningYesNo(
+ this, i18n( "You have done changes that were left uncommited. "
+ "Are you sure you want to exit? " ),
+ i18n( "Uncommited changes, really quit?" ) ) == KMessageBox::Yes)
+ e->accept();
+ } else
+ e->accept();
+}
+
+void TestApp::foregroundClosed()
+{
+ m_stack->raiseWidget( m_list );
+}
+
+void TestApp::update() {
+ closeModes();
+ setActionsEnabled( false );
+ aptFront::Manager m;
+ m.setProgressCallback( m_progress->callback() );
+ m.setUpdateInterval( 100000 );
+ try {
+ m_stack->raiseWidget( m_progress );
+ m.update();
+ } catch ( exception::OperationCancelled ) { // ignore
+ } catch (...) {
+ KMessageBox::sorry( this,
+ i18n( "There was an error downloading updates. " ),
+ i18n( "Could not fetch updates" ) );
+ }
+ kdDebug() << "closing progress widget" << endl;
+ m_stack->raiseWidget( m_list );
+ setActionsEnabled( true );
+ notifyPostChange( 0 );
+#ifdef KUBUNTU
+ wizard = new UpgradeWizard(this, 0, 1);
+ if( !m_upgradeButtonAdded && wizard->checkForDistUpgrade(true) ) {
+ KToolBar* tool = toolBar();
+ tool->insertButton(QString("2uparrow"), 12345, SIGNAL(released()), this, SLOT(releaseUpgrade()), true, i18n("Version Upgrade"));
+ m_upgradeButtonAdded = true;
+ } else {
+ wizard->close();
+ }
+#endif
+}
+
+#ifdef KUBUNTU
+void TestApp::releaseUpgrade() {
+ wizard->show();
+}
+#endif
+
+#ifdef KUBUNTU
+void TestApp::addVersionUpgrade(QString url, bool develVersion) {
+ wizard = new UpgradeWizard(this, 0, 1);
+ bool show = wizard->checkForDistUpgrade(false, url, develVersion);
+ if (show || develVersion) {
+ KToolBar* tool = toolBar();
+ tool->insertButton(QString("2uparrow"), 12345, SIGNAL(released()), this, SLOT(releaseUpgrade()), true, i18n("Version Upgrade"));
+ m_upgradeButtonAdded = true;
+ }
+}
+#endif
+
+void TestApp::reload() {
+ cache().reopen();
+}
+
+void TestApp::commit() {
+ closeModes();
+ setActionsEnabled( false );
+
+ aptFront::Manager m;
+ m.setProgressCallback( m_progress->callback() );
+ m.setUpdateInterval( 100000 );
+ try {
+ m_stack->raiseWidget( m_progress );
+ m.download();
+ m_stack->raiseWidget( m_commitProgress );
+ m.commit();
+ } catch ( exception::OperationCancelled ) {
+ } catch (...) {
+ KMessageBox::sorry(
+ this, i18n( "There was an error commiting changes. "
+ "Possibly there was a problem downloading some "
+ "packages or the commit would break packages. " ),
+ i18n( "Could not commit changes" ) );
+ // FIXME: this should be handled by libapt-front
+ cache::Global::get().reopen();
+ }
+ m_stack->raiseWidget( m_list );
+ setActionsEnabled( true );
+ notifyPostChange( 0 );
+}
+
+void TestApp::upgrade() {
+ closeModes();
+ cache::Global::get().state().upgrade();
+}
+
+void TestApp::distUpgrade() {
+ closeModes();
+ cache::Global::get().state().distUpgrade();
+}
+
+void TestApp::togglePreview() {
+ if ( modeActive( Preview ) )
+ closeModes();
+ else
+ openPreview();
+}
+
+void TestApp::toggleSources() {
+ QFile file(QString("/usr/bin/software-properties-kde"));
+ if (file.exists()) {
+ softwarePropertiesProcess = new KProcess(this);
+
+ *softwarePropertiesProcess << "/usr/bin/software-properties-kde" << "--no-update";
+ QApplication::connect(softwarePropertiesProcess, SIGNAL(processExited(KProcess *)),
+ this, SLOT(softwarePropertiesExited(KProcess *)));
+ softwarePropertiesProcess->start();
+ } else {
+ kdDebug() << " no software-properties-kde exists" << endl;
+ if ( modeActive( Sources ) )
+ closeModes();
+ else
+ openSources();
+ }
+}
+
+void TestApp::softwarePropertiesExited(KProcess *) {
+ if (softwarePropertiesProcess->exitStatus() == 1) {
+ update();
+ }
+}
+
+void TestApp::toggleDownload() {
+ toggleMode( Download );
+}
+
+void TestApp::toggleCommit() {
+ toggleMode( Commit );
+}
+
+void TestApp::toggleMode( Mode m ) {
+ if ( modeActive( m ) )
+ closeModes();
+ else
+ openMode( m );
+}
+
+void TestApp::openPreview() {
+ if ( openMode( Preview ) )
+ m_preview->searchView()->lister()->scheduleRebuild();
+}
+
+void TestApp::closePreview() {
+ if ( closeMode( Preview ) )
+ m_list->searchView()->lister()->scheduleRebuild();
+}
+
+void TestApp::openSources() {
+ if ( openMode( Sources ) )
+ m_sources->reset();
+}
+
+void TestApp::closeSources() {
+ closeMode( Sources );
+}
+
+bool TestApp::closeMode ( Mode m ) {
+ if ( modeActive( m ) ) {
+ m_stack->raiseWidget( m_list );
+ modeAction( m )->setChecked( false );
+ return true;
+ }
+ return false;
+}
+
+bool TestApp::openMode( Mode m ) {
+ if ( !modeActive( m ) ) {
+ closeModes();
+ m_modesClosed->setChecked( false );
+ kdDebug() << "openMode widget: " << modeWidget( m ) << endl;
+ m_stack->raiseWidget( modeWidget( m ) );
+ return true;
+ }
+ return false;
+}
+
+#include "app.moc"
diff --git a/adept/manager/app.h b/adept/manager/app.h
new file mode 100644
index 0000000..0fc1927
--- /dev/null
+++ b/adept/manager/app.h
@@ -0,0 +1,162 @@
+/* -*- C++ -*- */
+#ifndef TESTUI_APP_H
+#define TESTUI_APP_H
+
+#define KUBUNTU
+
+#include <kmainwindow.h>
+#include <kprocess.h>
+#include <kparts/part.h>
+#include <kactionclasses.h>
+#include <apt-front/cache/observer.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+#include <adept/view.h>
+#include <adept/commitprogress.h>
+#include <adept/sourceseditor.h>
+#include <adept/application.h>
+
+#ifdef KUBUNTU
+#include <kubuntu_upgrader/upgradewizard.h>
+#endif
+
+class QVBox;
+class QWidgetStack;
+class QSplitter;
+class KAction;
+namespace adept {
+class AcqProgressWidget;
+}
+
+using namespace aptFront;
+using namespace adept;
+
+class TestApp : public KMainWindow, Application {
+ Q_OBJECT
+public:
+ enum Mode { Default, Sources, Preview, Download, Commit };
+ void setupActions();
+ ExtTerminalInterface *terminal();
+ TestApp();
+#ifdef KUBUNTU
+ void addVersionUpgrade(QString url, bool develVersion=false);
+#endif
+protected slots:
+ void delayed(); // initialisation
+
+ void setActionsEnabled( bool );
+ void setHistoryEnabled( bool );
+
+ void update(); // actions
+ void upgrade();
+ void distUpgrade();
+#ifdef KUBUNTU
+ void releaseUpgrade();
+#endif
+ void commit();
+
+ void reload(); // debugging
+
+ void undo() { Application::undo(); }
+ void redo() { Application::redo(); }
+ void checkpoint() { Application::checkpoint(); }
+
+ void foregroundClosed();
+
+ void togglePreview();
+ void toggleSources();
+ void softwarePropertiesExited(KProcess *);
+ void toggleDownload();
+ void toggleCommit();
+
+ void closePreview();
+ void closeSources();
+
+ void openPreview();
+ void openSources();
+
+ bool modeActive( Mode m ) {
+ // return modeAction( m )->isChecked();
+ return modeWidget( m ) == m_stack->visibleWidget();
+ }
+
+ void closeModes() {
+ closePreview();
+ closeSources();
+ closeMode( Download );
+ closeMode( Commit );
+ m_modesClosed->setChecked( true );
+ }
+
+ void rebuildStarted() {
+ if ( !m_rebuilds ) setActionsEnabled( false );
+ m_rebuilds ++;
+ }
+
+ void rebuildFinished() {
+ m_rebuilds --;
+ if ( !m_rebuilds ) setActionsEnabled( true );
+ }
+
+protected:
+ void updateActionState();
+ void guardLister( adept::Lister * );
+ void addMode( Mode m, KToggleAction *a, QWidget *w ) {
+ m_modeActionMap[ m ] = a;
+ m_modeWidgetMap[ m ] = w;
+ a->setChecked( false );
+ }
+
+ KToggleAction *modeAction( Mode m ) {
+ return m_modeActionMap[ m ];
+ }
+
+ QWidget *modeWidget( Mode m ) {
+ return m_modeWidgetMap[ m ];
+ }
+
+ bool openMode( Mode );
+ bool closeMode( Mode );
+ void toggleMode( Mode );
+
+ friend class WaitForLister;
+ virtual void closeEvent( QCloseEvent * );
+ virtual void notifyPostChange( cache::component::Base * );
+ virtual void notifyPostRebuild( cache::component::Base * );
+ virtual void notifyPreChange( cache::component::Base * );
+
+ QWidgetStack *m_stack;
+ QLabel *m_loading;
+
+ // stacked widgets
+ adept::AcqProgressWidget *m_progress;
+ adept::Browser *m_list, *m_preview;
+ adept::SourcesEditor *m_sources;
+ adept::CommitProgress *m_commitProgress;
+
+ // other stuff
+ std::vector<KAction *> m_actions;
+ QMap< QString, QString > m_icons;
+ KAction *m_undo, *m_redo;
+
+ int m_rebuilds;
+ bool m_actionsEnabled;
+
+ KAction *m_commit, *m_upgrade, *m_distUpgrade;
+ KToggleAction *m_sourcesAction, *m_commitProgressAction, *m_listAction,
+ *m_previewAction, *m_progressAction;
+ std::map< Mode, KToggleAction * > m_modeActionMap;
+ std::map< Mode, QWidget * > m_modeWidgetMap;
+ KToggleAction *m_modesClosed;
+private:
+ template<typename T> void plugAptActions();
+ // template<typename T, typename In> void updateAptActions( In b, In e );
+ template<typename T, typename In> void aptAction( In b, In e );
+ KProcess* softwarePropertiesProcess;
+#ifdef KUBUNTU
+ UpgradeWizard* wizard;
+ bool m_upgradeButtonAdded;
+#endif
+};
+
+#endif
diff --git a/adept/manager/hi128-app-adept_manager.png b/adept/manager/hi128-app-adept_manager.png
new file mode 100644
index 0000000..ba3cb4b
--- /dev/null
+++ b/adept/manager/hi128-app-adept_manager.png
Binary files differ
diff --git a/adept/manager/hi16-app-adept_manager.png b/adept/manager/hi16-app-adept_manager.png
new file mode 100644
index 0000000..80a35a1
--- /dev/null
+++ b/adept/manager/hi16-app-adept_manager.png
Binary files differ
diff --git a/adept/manager/hi22-app-adept_manager.png b/adept/manager/hi22-app-adept_manager.png
new file mode 100644
index 0000000..dc4392d
--- /dev/null
+++ b/adept/manager/hi22-app-adept_manager.png
Binary files differ
diff --git a/adept/manager/hi32-app-adept_manager.png b/adept/manager/hi32-app-adept_manager.png
new file mode 100644
index 0000000..d1b4a61
--- /dev/null
+++ b/adept/manager/hi32-app-adept_manager.png
Binary files differ
diff --git a/adept/manager/hi48-app-adept_manager.png b/adept/manager/hi48-app-adept_manager.png
new file mode 100644
index 0000000..d76f679
--- /dev/null
+++ b/adept/manager/hi48-app-adept_manager.png
Binary files differ
diff --git a/adept/manager/hi64-app-adept_manager.png b/adept/manager/hi64-app-adept_manager.png
new file mode 100644
index 0000000..cabb87b
--- /dev/null
+++ b/adept/manager/hi64-app-adept_manager.png
Binary files differ
diff --git a/adept/manager/hisc-app-adept_manager.svgz b/adept/manager/hisc-app-adept_manager.svgz
new file mode 100644
index 0000000..55ac033
--- /dev/null
+++ b/adept/manager/hisc-app-adept_manager.svgz
Binary files differ
diff --git a/adept/manager/main.cpp b/adept/manager/main.cpp
new file mode 100644
index 0000000..c6e1eba
--- /dev/null
+++ b/adept/manager/main.cpp
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kuniqueapplication.h>
+
+#include "app.h"
+
+static KCmdLineOptions options[] =
+{
+ { "dist-upgrade", I18N_NOOP("add toolbar button to launch the version upgrade tool to the latest release"), 0},
+ { "dist-upgrade-proposed", I18N_NOOP("add toolbar button to launch the version upgrade tool to proposed next release"), 0},
+ { "dist-upgrade-devel", I18N_NOOP("add toolbar button to launch the version upgrade tool to development version"), 0},
+ KCmdLineLastOption
+};
+
+int main(int argc, char *argv[])
+{
+
+ KLocale::setMainCatalogue("adept");
+
+ putenv( "QT_IM_MODULE=xim" );
+ QString description = i18n("Adept Manager");
+
+ KAboutData aboutData( "adept_manager",
+ I18N_NOOP("Adept Manager"),
+ "2.1 Cruiser",
+ description.latin1(),
+ KAboutData::License_BSD,
+ I18N_NOOP("(c) 2005, 2006 Peter Rockai"),
+ 0,
+ "http://web.mornfall.net/adept.html");
+
+ aboutData.addAuthor ( "Peter Rockai",
+ I18N_NOOP("developer"),
+ "me at mornfall dot net",
+ "http://web.mornfall.net");
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+ // if (args && args->isSet("xy")) ...
+
+ /* KConfig* config = KGlobal::config();
+ config->setGroup("General Settings");
+ QString version = config->readEntry("Version"); */
+
+ KGlobal::locale()->insertCatalogue(QString::fromUtf8("libept"));
+ KGlobal::locale()->insertCatalogue(QString::fromUtf8("libapt-front"));
+
+ TestApp *ta = new TestApp();
+
+ app.setMainWidget(ta);
+
+#ifdef KUBUNTU
+ if (args && args->isSet("dist-upgrade")) {
+ ta->addVersionUpgrade(QString("http://changelogs.ubuntu.com/meta-release"));
+ } else if (args && args->isSet("dist-upgrade-proposed")) {
+ ta->addVersionUpgrade(QString("http://changelogs.ubuntu.com/meta-release-proposed"));
+ } else if (args && args->isSet("dist-upgrade-devel")) {
+ ta->addVersionUpgrade(QString("http://changelogs.ubuntu.com/meta-release-development"), true);
+ }
+#endif
+
+ ta->show();
+
+ return app.exec();
+}
diff --git a/adept/notifier/15adept-periodic-update b/adept/notifier/15adept-periodic-update
new file mode 100644
index 0000000..d1922e3
--- /dev/null
+++ b/adept/notifier/15adept-periodic-update
@@ -0,0 +1,3 @@
+APT::Periodic::Update-Package-Lists "1";
+APT::Periodic::Download-Upgradeable-Packages "0";
+APT::Periodic::AutocleanInterval "0";
diff --git a/adept/notifier/Makefile.am b/adept/notifier/Makefile.am
new file mode 100644
index 0000000..6b576be
--- /dev/null
+++ b/adept/notifier/Makefile.am
@@ -0,0 +1,26 @@
+
+bin_PROGRAMS = adept_notifier
+#kdeinit_LTLIBRARIES = adept-notifier.la
+noinst_HEADERS = app.h
+
+adept_notifier_SOURCES = app.cpp
+adept_notifier_LDADD = ../adept/libadept.la $(LIBAPT_FRONT_LIBS) $(LIBEPT_LIBS) $(LIBTAGCOLL2_LIBS) $(LIB_KIO) $(LIBKDE_UI)
+adept_notifier_LDFLAGS = -L/usr/lib/debug
+
+INCLUDES = $(all_includes) $(LIBAPT_FRONT_CFLAGS) $(LIBEPT_CFLAGS) $(LIBTAGCOLL2_CFLAGS) $(LIBWIBBLE_CFLAGS) -I$(srcdir)/.. -I..
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII
+METASOURCES = AUTO
+KDE_ICON = AUTO
+
+rcdir = $(kde_datadir)/adept-notifier
+#rc_DATA = adept-updaterui.rc
+
+#shelldesktopdir = $(kde_appsdir)/System
+xdg_apps_DATA = adept_notifier.desktop
+autostart_DATA = adept_notifier_auto.desktop
+autostartdir = /etc/xdg/autostart
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(EXTRACTRC) `find . -name "*.rc"` >> rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/adept_notifier.pot
diff --git a/adept/notifier/adept_notifier.desktop b/adept/notifier/adept_notifier.desktop
new file mode 100644
index 0000000..453ef5f
--- /dev/null
+++ b/adept/notifier/adept_notifier.desktop
@@ -0,0 +1,63 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Adept Notifier
+Name[ca]=Notificador Adept
+Name[da]=Adept underretninger
+Name[de]=Adept Benachrichtigung
+Name[el]=Ειδοποίηση ενημερώσεων του Adept
+Name[es]=Notificador Adept
+Name[fr]=Notificateur Adept
+Name[ga]=Fógróir Adept
+Name[gl]=Notificador de Adept
+Name[it]=Notifica automatica Adept
+Name[ka]=Adept შემტყობინებელი
+Name[lt]=Adept informuoklis
+Name[pt]=Notificador do Adept
+Name[sk]=Adept upozornenie
+Name[sv]=Adept uppdatering
+Name[xx]=xxAdept Notifierxx
+GenericName=Update Reminder
+GenericName[bg]=Напомняне за обновяване
+GenericName[ca]=Recordador d'actualitzacions
+GenericName[cs]=Upozorňování na aktualizace
+GenericName[da]=Opdateringspåmindelser
+GenericName[de]=Aktualisierungsbenachrichtigung
+GenericName[el]=Υπενθύμιση ενημέρωσης
+GenericName[es]=Recordar actualización
+GenericName[gl]=Recorda-lle a existéncia de Actualizazóns
+GenericName[it]=Avviso aggiornamenti
+GenericName[ja]=アップデートを通知
+GenericName[ka]=შემხსენებლის განახლება
+GenericName[lt]=Atnaujinimų priminimai
+GenericName[nl]=Updateherinnering
+GenericName[pt]=Chamada de Atenção de Actualizações
+GenericName[sk]=Pripomienka aktualizácie
+GenericName[sv]=Uppdateringspåminnelse
+GenericName[xx]=xxUpdate Reminderxx
+Exec=adept_notifier -caption "%c"
+TryExec=adept_notifier
+Categories=Qt;KDE;System;
+Icon=adept_notifier
+Type=Application
+X-KDE-SubstituteUID=false
+Comment=Watch for updates
+Comment[bg]=Следене за обновяване
+Comment[ca]=Vigila les actualitzacions
+Comment[cs]=Sledování aktualizací
+Comment[da]=Overvåg opdateringer
+Comment[de]=Überprüft Aktualisierungen
+Comment[el]=Παρακολούθηση για ενημερώσεις
+Comment[es]=Busca actualizaciones
+Comment[ga]=Déan faire ar nuashonruithe
+Comment[gl]=Comproba as actualizazóns
+Comment[it]=Controlla la presenza di aggiornamenti
+Comment[ja]=アップデートを監視
+Comment[ka]=განახლებების თვალთვალი
+Comment[lt]=Atnaujinimų stebėjimas
+Comment[nl]=Updates volgen
+Comment[pt]=Pesquisar actualizações
+Comment[sk]=Sledovať aktualizácie
+Comment[sv]=Bevaka uppdateringar
+Comment[xx]=xxWatch for updatesxx
+Terminal=false
+NoDisplay=true
diff --git a/adept/notifier/adept_notifier_auto.desktop b/adept/notifier/adept_notifier_auto.desktop
new file mode 100644
index 0000000..42c37ba
--- /dev/null
+++ b/adept/notifier/adept_notifier_auto.desktop
@@ -0,0 +1,23 @@
+[Desktop Entry]
+Encoding=UTF-8
+Exec=adept_notifier
+Name=Adept Notifier
+Name[ca]=Notificador Adept
+Name[da]=Adept underretninger
+Name[de]=Adept Benachrichtigung
+Name[el]=Ειδοποίηση ενημερώσεων του Adept
+Name[es]=Notificador Adept
+Name[fr]=Notificateur Adept
+Name[ga]=Fógróir Adept
+Name[gl]=Notificador de Adept
+Name[it]=Notifica automatica Adept
+Name[ka]=Adept შემტყობინებელი
+Name[lt]=Adept informuoklis
+Name[pt]=Notificador do Adept
+Name[sk]=Adept upozornenie
+Name[sv]=Adept uppdatering
+Name[xx]=xxAdept Notifierxx
+X-KDE-autostart-after=panel
+Type=Service
+X-KDE-autostart-condition=adept_notifierrc:General:Autostart:true
+OnlyShowIn=KDE;
diff --git a/adept/notifier/app.cpp b/adept/notifier/app.cpp
new file mode 100644
index 0000000..2ed8c2b
--- /dev/null
+++ b/adept/notifier/app.cpp
@@ -0,0 +1,342 @@
+#include <unistd.h>
+#include <sys/stat.h>
+#include <qtooltip.h>
+#include <qtimer.h>
+#include <qfile.h>
+
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kglobalaccel.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <kaboutapplication.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kconfig.h>
+#include <kpassivepopup.h>
+#include <kiconloader.h>
+
+#include <apt-front/init.h>
+#include <apt-front/cache/cache.h>
+#include <apt-front/cache/component/packages.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/utils.h>
+
+#include "app.h"
+
+using namespace aptFront;
+using namespace cache;
+using namespace utils;
+using namespace adept;
+
+TrayWindow::TrayWindow(QWidget *parent, const char *name)
+ : KSystemTray(parent, name), m_updates( 0 )
+{
+ setAvailableUpdates( m_updates );
+ // actionCollection()->remove( actionCollection()->action( "quit" ) );
+ m_quit = KStdAction::quit( this, SIGNAL( quitSelected() ), actionCollection() );
+ m_about = KStdAction::aboutApp( this, SIGNAL( aboutSelected() ), actionCollection() );
+ // setPixmap( loadIcon( u8( "adept_notifier_warning" ) ) );
+}
+
+void TrayWindow::contextMenuAboutToShow( KPopupMenu *r ) {
+ kdDebug() << "TrayWindow::contextMenu()" << endl;
+ r->clear();
+ m_about->plug( r );
+ m_quit->plug( r );
+}
+
+void TrayWindow::setAvailableUpdates( int n )
+{
+ m_updates = n;
+ kdDebug() << "TrayWindow obtained " << n << endl;
+
+ setPixmap( m_updates == 0 ?
+ loadIcon( u8( "adept_notifier_ok" ) ) :
+ loadIcon( u8( "adept_notifier_warning" ) ) );
+
+ if ( m_updates == 0 )
+ hide();
+ else
+ show();
+
+ QToolTip::remove(this);
+ QToolTip::add(this, n == 0 ? i18n( "No updates needed." )
+ : i18n( "There is %n updated package available",
+ "There are %n updated packages available", n ) );
+}
+
+void TrayWindow::mouseReleaseEvent(QMouseEvent *ev)
+{
+ if (ev->button() == QMouseEvent::LeftButton)
+ emit clicked();
+ KSystemTray::mouseReleaseEvent(ev);
+}
+
+void ApportTrayWindow::mousePressEvent(QMouseEvent *ev)
+{
+ emit clicked();
+ hide();
+}
+
+void RebootTrayWindow::mousePressEvent(QMouseEvent *ev)
+{
+ emit clicked();
+}
+
+NotifierApp::NotifierApp(bool allowStyles, bool GUIenabled)
+ : KUniqueApplication(allowStyles, GUIenabled),
+ m_tray( 0 )
+{
+ sharedConfig()->setGroup( "General" );
+ m_okAutostart = sharedConfig()->readBoolEntry( "Autostart", true );
+ m_timer = new QTimer( this );
+ m_tray = new TrayWindow( 0, 0 );
+ m_tray->show();
+ m_rebootRequired = false;
+ m_rebootShown = false;
+
+ aptFront::init();
+
+ fileUpdated( "/var/cache/apt/pkglist.bin", m_updateStamp );
+ // fileUpdated( "/var/lib/apt/periodic/update-stamp", m_updateStamp );
+ fileUpdated( "/var/lib/dpkg/status", m_statusStamp );
+
+ m_tray->setAvailableUpdates( upgradable() );
+
+ connect( m_tray, SIGNAL( clicked() ), this, SLOT( clicked() ) );
+ // connect( m_tray, SIGNAL( quitSelected() ), this, SLOT( quit() ) );
+ connect( m_tray, SIGNAL( quitSelected() ), this, SLOT( askQuit() ) );
+ connect( m_tray, SIGNAL( aboutSelected() ), this, SLOT( about() ) );
+ connect( m_timer, SIGNAL( timeout() ), this, SLOT( checkUpdates() ) );
+ m_timer->start( 1000*5 ); // 5 secs now, used to be 60
+ if ( !m_okAutostart ) {
+ int r = KMessageBox::questionYesNo(
+ m_tray, i18n( "You disabled automatic startup of Adept Notifier last time "
+ "you quit the application. "
+ "Do you want to start Adept Notifier next time you log in?" ),
+ i18n( "Automatic Startup" ),
+ KGuiItem( i18n( "Start" ) ), KGuiItem( i18n( "Don't Start" ) ),
+ u8( "enableAutostart" ) );
+ if ( r == KMessageBox::Yes ) {
+ sharedConfig()->setGroup( "General" );
+ sharedConfig()->writeEntry( "Autostart", true );
+ m_okAutostart = true;
+ }
+ }
+
+ // if apport crash handler it installed, watch for crash reports appearing and run
+ // the apport frontend when they do
+ bool runApport = sharedConfig()->readBoolEntry( "Apport", true );
+ if ( QFile::exists(QString("/usr/share/apport/apport-qt")) && runApport ) {
+ m_dirWatch = new KDirWatch(this);
+ m_dirWatch->addDir(QString("/var/crash"));
+ connect( m_dirWatch, SIGNAL( dirty(const QString&) ), this, SLOT( crashWatcher() ) );
+
+ KProcess *proc = new KProcess;
+ *proc << "/usr/share/apport/apport-checkreports";
+ connect( proc, SIGNAL(processExited(KProcess*)), this, SLOT(apportCheckExited(KProcess*)) );
+ proc->start(KProcess::Block);
+
+ if (m_crashes) {
+ ApportTrayWindow* crashApplet = new ApportTrayWindow;
+ crashApplet->setPixmap( crashApplet->loadIcon(u8("apport")) );
+ QString crashMessage = i18n("An application has crashed on your "
+ "system (now or in the past).\n"
+ "Click to "
+ "display details. "
+ );
+ QToolTip::add(crashApplet, crashMessage);
+ connect( crashApplet, SIGNAL(clicked()), this, SLOT(crashWatcher()) );
+ crashApplet->show();
+ QPixmap icon = BarIcon(u8("apport"));
+ KPassivePopup::message(i18n("Crash Handler"), crashMessage, icon, crashApplet);
+ }
+ }
+ // if reboot-required is installed watch for reboot-required and dpkg-run-stamp
+ if ( QFile::exists(QString("/usr/share/update-notifier/notify-reboot-required")) ) {
+ m_rebootDirWatch = new KDirWatch(this);
+ m_rebootDirWatch->addFile(QString("/var/run/reboot-required"));
+ m_rebootDirWatch->addFile(QString("/var/lib/update-notifier/dpkg-run-stamp"));
+ connect( m_rebootDirWatch, SIGNAL( dirty(const QString&) ), this, SLOT( rebootWatcher(const QString&) ) );
+
+ }
+}
+
+void NotifierApp::crashWatcher() {
+ // find out if there are system crash reports first, if there are run it as root
+ KProcess *proc = new KProcess;
+ *proc << "/usr/share/apport/apport-checkreports";
+ *proc << "--system";
+ connect( proc, SIGNAL(processExited(KProcess*)), this, SLOT(apportCheckExited(KProcess*)) );
+ proc->start(KProcess::Block);
+
+ if (m_crashes) {
+ KProcess *proc2 = new KProcess;
+ *proc2 << "kdesu" << "/usr/share/apport/apport-qt";
+ proc2->start(KProcess::DontCare);
+ } else {
+ KShellProcess *proc2 = new KShellProcess;
+ *proc2 << "sleep 1; /usr/share/apport/apport-qt"; //needs a seconds delay else we're too fast for apport
+ proc2->start(KProcess::DontCare);
+ }
+}
+
+void NotifierApp::apportCheckExited(KProcess* proc) {
+ if (proc->exitStatus() == 0) {
+ m_crashes = true;
+ } else {
+ m_crashes = false;
+ }
+}
+
+void NotifierApp::rebootWatcher(const QString& path) {
+ kdDebug() << "NotifierApp::rebootWatcher: " << path << endl;
+
+ if (path == QString("/var/run/reboot-required")) {
+ m_rebootRequired = true;
+ }
+
+ if (path == QString("/var/lib/update-notifier/dpkg-run-stamp") && m_rebootRequired && !m_rebootShown) {
+
+ RebootTrayWindow* rebootApplet = new RebootTrayWindow;
+ rebootApplet->setPixmap( rebootApplet->loadIcon(u8("reload")) );
+
+ QString rebootMessage = i18n("In order to complete the update your system needs to be restarted.");
+ QToolTip::add(rebootApplet, rebootMessage);
+ connect( rebootApplet, SIGNAL(clicked()), this, SLOT(rebootClicked()) );
+ rebootApplet->show();
+ QPixmap icon = BarIcon(u8("reload"));
+ KPassivePopup::message(i18n("Reboot Required"), rebootMessage, icon, rebootApplet);
+ m_rebootShown = true;
+ }
+
+}
+
+void NotifierApp::rebootClicked() {
+ kdDebug() << "NotifierApp::rebootClicked" << endl;
+ if (KMessageBox::questionYesNo(0, QString("In order to complete the update your system needs to be restarted."), QString("Restart Require")) == KMessageBox::Yes) {
+ kdDebug() << "NotifierApp::rebootClicked yes!" << endl;
+ KProcess *proc = new KProcess;
+ *proc << "/usr/bin/dcop";
+ *proc << "ksmserver" << "ksmserver" << "logout" << "0" << "1" << "2"; // 0 1 2 == ShutdownConfirmNo ShutdownTypeReboot ShutdownModeForceNow
+ proc->start();
+ }
+}
+
+void NotifierApp::askQuit() {
+ if ( m_okAutostart ) {
+ int r = KMessageBox::questionYesNoCancel(
+ m_tray, i18n( "Do you want to start Adept Notifier next time you log in?" ),
+ i18n( "Automatic Startup" ),
+ KGuiItem( i18n( "Start" ) ), KGuiItem( i18n( "Don't Start" ) ) );
+ if ( r == KMessageBox::Cancel )
+ return;
+ if ( r == KMessageBox::No ) {
+ sharedConfig()->setGroup( "General" );
+ sharedConfig()->writeEntry( "Autostart", false );
+ }
+ }
+ exit( 0 );
+
+}
+
+bool NotifierApp::fileUpdated( const char *f, time_t &stamp ) {
+ time_t old = stamp;
+ struct stat s;
+ ::stat( f, &s );
+ stamp = s.st_mtime;
+ if ( stamp > old )
+ return true;
+ return false;
+}
+
+int NotifierApp::upgradable() {
+ try {
+ kdDebug() << "checking cache for upgradable packages..." << endl;
+ cache::Cache &c = cache::Global::get();
+ c.open( Cache::OpenReadOnly
+ | Cache::OpenPackages
+ | Cache::OpenState );
+
+ kdDebug() << "cache opened, listing..." << endl;
+ Range< entity::Package > r = range( c.packages().packagesBegin(),
+ c.packages().packagesEnd() );
+ kdDebug() << "looking for upgradable packages..." << endl;
+ Range< entity::Package > fr = filteredRange(
+ r, predicate::Package::member( &entity::Package::isUpgradable ) );
+ VectorRange< entity::Package > vr = VectorRange< entity::Package >();
+ fr.output( vr );
+ kdDebug() << "found " << vr.size() << " upgradable package(s)" << endl;
+ int ret = vr.size();
+ c.close();
+ return ret;
+ } catch ( exception::Error e ) {
+ kdDebug() << "error checking cache for upgradable packages..." << endl;
+ kdDebug() << "what: " << e.message() << endl;
+ } catch ( std::exception e ) {
+ kdDebug() << "exception checking cache for upgradable packages..." << endl;
+ kdDebug() << "what: " << e.what() << endl;
+ // XXX error handling
+ }
+ return true; // we don't know, so assume true (safe)
+}
+
+void NotifierApp::checkUpdates() {
+ // kdDebug() << "checking updates status" << endl;
+ if ( // fileUpdated( "/var/lib/apt/periodic/update-stamp", m_updateStamp )
+ fileUpdated( "/var/cache/apt/pkgcache.bin", m_updateStamp )
+ || fileUpdated( "/var/lib/dpkg/status", m_statusStamp ) )
+ m_tray->setAvailableUpdates( upgradable() );
+}
+
+void NotifierApp::about() {
+ KAboutApplication *a = new KAboutApplication( m_tray, "", true );
+ a->exec();
+ delete a;
+}
+
+NotifierApp::~NotifierApp()
+{
+ delete m_tray;
+}
+
+void NotifierApp::clicked()
+{
+ if ( m_tray->updates() == 0 )
+ return KMessageBox::information(
+ 0, i18n( "There are no known updates available." ),
+ i18n( "Nothing to do" ) );
+ startServiceByDesktopName( u8( "adept_updater" ) );
+}
+
+/* void NotifierApp::menuActivated(int id)
+{
+ // implement help
+} */
+
+const char * DESCRIPTION =
+ I18N_NOOP("Adept update notifier utility");
+
+/* extern "C" KDE_EXPORT */
+int main(int argc, char *argv[])
+{
+ KAboutData about("adept_notifier", I18N_NOOP("Adept Notifier"),
+ "2.1 Cruiser",
+ DESCRIPTION, KAboutData::License_BSD,
+ "Copyright (C) 2005, 2006 Peter Rockai");
+ KCmdLineArgs::init(argc, argv, &about);
+ NotifierApp::addCmdLineOptions();
+
+ if (!NotifierApp::start())
+ return 0;
+
+ NotifierApp app;
+ app.disableSessionManagement();
+ app.exec();
+ return 0;
+}
diff --git a/adept/notifier/app.h b/adept/notifier/app.h
new file mode 100644
index 0000000..c543aaa
--- /dev/null
+++ b/adept/notifier/app.h
@@ -0,0 +1,93 @@
+#ifndef EPT_NOTIFIER_H
+#define EPT_NOTIFIER_H
+
+#include <sys/types.h>
+#include <ksystemtray.h>
+#include <kuniqueapplication.h>
+#include <kdirwatch.h>
+#include <kprocess.h>
+
+class QWidget;
+class KAction;
+// class KGlobalAccel;
+
+// the status indicator in system tray
+class TrayWindow : public KSystemTray
+{
+ Q_OBJECT
+public:
+ TrayWindow(QWidget *parent=0, const char *name=0);
+ void setAvailableUpdates( int n );
+ int updates() { return m_updates; }
+ void contextMenuAboutToShow ( KPopupMenu * );
+signals:
+ void clicked();
+ void aboutSelected();
+protected:
+ void mouseReleaseEvent( QMouseEvent * );
+ int m_updates;
+ KAction *m_quit, *m_about;
+};
+
+// the apport indicator in system tray
+// gets shown where the app is started and
+// existing apport reports are found.
+// clicking starts apport-qt
+class ApportTrayWindow : public KSystemTray
+{
+ Q_OBJECT
+signals:
+ void clicked();
+protected:
+ void mousePressEvent(QMouseEvent*);
+};
+
+// used for the reboot notifier
+class RebootTrayWindow : public KSystemTray
+{
+ Q_OBJECT
+signals:
+ void clicked();
+protected:
+ void mousePressEvent(QMouseEvent*);
+};
+
+
+
+// application watching the current status
+// it will update the icon and run
+class NotifierApp : public KUniqueApplication
+{
+ Q_OBJECT
+public:
+ NotifierApp(bool allowStyles=true, bool GUIenabled=true);
+ ~NotifierApp();
+ bool fileUpdated( const char *, time_t & );
+ int upgradable();
+
+protected slots:
+// void menuActivated(int id);
+ void clicked();
+ void checkUpdates();
+ void askQuit();
+ void about();
+ // for apport
+ void crashWatcher();
+ void apportCheckExited(KProcess*);
+ void rebootWatcher(const QString& path);
+ void rebootClicked();
+
+protected:
+ TrayWindow *m_tray;
+ QTimer *m_timer;
+ time_t m_updateStamp, m_statusStamp;
+ bool m_okAutostart;
+ // for apport crash handler
+ KDirWatch* m_dirWatch;
+ KDirWatch* m_rebootDirWatch;
+ bool m_crashes;
+ bool m_rebootRequired;
+ bool m_rebootShown; //have we already shown the reboot notifier?
+};
+
+#endif
diff --git a/adept/tests/libcapture/celem-test.cpp b/adept/tests/libcapture/celem-test.cpp
new file mode 100644
index 0000000..ada22e3
--- /dev/null
+++ b/adept/tests/libcapture/celem-test.cpp
@@ -0,0 +1,34 @@
+#include <test-util.h>
+#include <libcapture/celem.h>
+#include <libcapture/pkgmanager.h>
+#include <string>
+
+namespace tut {
+
+ using namespace std;
+ using namespace capture;
+
+ struct celem_shar {
+ };
+
+ typedef test_group<celem_shar> tg;
+ typedef tg::object to;
+ tg celem_tg ("celem");
+ template<> template<>
+ void to::test<1> ()
+ {
+ cacheInit ();
+ PkgCElemPtr a = cElem (PkgManager::cache () -> FindPkg ("postfix"));
+ ensure (a -> id () == string ("postfix"));
+ cerr << "a -> id () = " << a -> id () << endl;
+ ensure (a -> Name () == string ("postfix"));
+ cerr << "a -> Name () = " << a -> id () << endl;
+ VerCElemPtr b = a -> VersionList ();
+ cerr << "b -> id () = " << b -> id () << endl;
+ pkgCache::PkgIterator bp = (PkgManager::cache () -> FindPkg
+ ("postfix"));
+ string bver = bp . VersionList () . VerStr ();
+ ensure (bver == b -> id ());
+ ensure (bver == b -> VerStr ());
+ }
+};
diff --git a/adept/tests/libcapture/grouper-test.cpp b/adept/tests/libcapture/grouper-test.cpp
new file mode 100644
index 0000000..c454f78
--- /dev/null
+++ b/adept/tests/libcapture/grouper-test.cpp
@@ -0,0 +1,44 @@
+#include <tut.h>
+#define protected public
+#include <libcapture/grouper.h>
+#include <libcapture/tree.h>
+#include <libcapture/treenode.h>
+#include <libcapture/treefactory.h>
+#include <string>
+
+namespace tut {
+
+ using namespace std;
+ using namespace capture;
+
+ struct grouper_shar {
+ };
+
+ typedef test_group<grouper_shar> tg;
+ typedef tg::object to;
+ tg grouper_tg ("grouper");
+#define IT(x) dynamic_cast <GrouperFactory *> (c -> m_vec [x] . second)
+ template<> template<>
+ void to::test<1> ()
+ {
+ Param::Map a;
+ GrouperChain *c;
+ GrouperTNode *n0, *n1, *n2, *n3;
+ c = new GrouperChain ("test");
+ n0 = c -> addFactory ("SectGrouper", "sect");
+ ensure (IT (0)); ensure (IT (0) == n0);
+ n1 = c -> addFactory ("EndGrouper", "end");
+ ensure (IT (1)); ensure (IT (1) == n1);
+ n2 = c -> addFactory ("PkgExistFilter", "exist", a, Grouper::Custom, 1);
+ ensure (IT (2));
+ ensure (IT (0) == n0);
+ ensure (IT (1) == n2);
+ ensure (IT (2) == n1);
+ n3 = c -> addFactory ("PkgNameFilter", "name", a, Grouper::BeforeLast);
+ ensure (IT (3));
+ ensure (IT (0) == n0);
+ ensure (IT (1) == n2);
+ ensure (IT (2) == n3);
+ ensure (IT (3) == n1);
+ }
+};
diff --git a/adept/tests/libcapture/pkgcache-test.cpp b/adept/tests/libcapture/pkgcache-test.cpp
new file mode 100644
index 0000000..662aaed
--- /dev/null
+++ b/adept/tests/libcapture/pkgcache-test.cpp
@@ -0,0 +1,71 @@
+#include <test-util.h>
+
+#include <libcapture/pkgcache.h>
+#include <libcapture/pkgmanager.h>
+#include <apt-pkg/configuration.h>
+#include <iostream>
+
+namespace tut {
+
+ using namespace std;
+ using namespace capture;
+
+ struct pkgcache_shar {
+ };
+
+ typedef test_group<pkgcache_shar> tg;
+ typedef tg::object to;
+ tg pkgcache_tg ("pkgcache");
+ template<> template<>
+ void to::test<1> ()
+ {
+ cacheInit (true);
+ pkgCache::PkgIterator P;
+ // P = (PkgManager::cache ()) -> FindPkg ("amavis-ng");
+ // PkgManager::cache () -> setExtState (P, true, 500);
+ // PkgManager::cache () -> updateAWanted (true);
+ P = (PkgManager::cache ()) -> FindPkg ("k3b");
+ PkgManager::cache () -> setExtState (P, true, 500);
+ PkgManager::cache () -> updateAWanted ();
+ P = (PkgManager::cache ()) -> FindPkg ("kapture");
+ PkgManager::cache () -> setExtState (P, true, 500);
+ PkgManager::cache () -> updateAWanted ();
+ /* P = (PkgManager::cache ()) -> FindPkg ("apt-listchanges");
+ PkgManager::cache () -> setExtState (P, true, 900);
+ PkgManager::cache () -> updateAWanted (true);
+ P = (PkgManager::cache ()) -> FindPkg ("exim");
+ PkgManager::cache () -> setExtState (P, true, 600);
+ PkgManager::cache () -> updateAWanted (true);
+ P = (PkgManager::cache ()) -> FindPkg ("harden");
+ PkgManager::cache () -> setExtState (P, true, 700);
+ PkgManager::cache () -> updateAWanted (true); */
+ /* P = (PkgManager::cache ()) -> FindPkg ("rmail");
+ PkgManager::cache () -> setExtState (P, true, 200); */
+
+ // PkgManager::cache () -> updateAWanted (0);
+ // PkgManager::cache () -> saveExtState ("pkgcache-test.out");
+ /* PkgManager::cache () -> updateAWanted (1);
+ PkgManager::cache () -> saveExtState ("pkgcache-test-1.out");
+ PkgManager::cache () -> updateAWanted (2);
+ PkgManager::cache () -> saveExtState ("pkgcache-test-2.out"); */
+ cout << "WANTED PACKAGES:" << endl;
+ PkgCache::ExtState *s;
+ for (pkgCache::PkgIterator mP = PkgManager::cache() -> PkgBegin (); ! mP . end (); mP ++) {
+ s = PkgManager::cache() -> extState (mP);
+ if (s -> a_wanted_pri > s -> a_unwanted_pri) {
+ cout << mP . Name ()
+ << ": a_wanted_pri = " << s -> a_wanted_pri
+ << ", a_unwanted_pri = " << s -> a_unwanted_pri << endl;
+ }
+ }
+ cout << "UNWANTED PACKAGES:" << endl;
+ for (pkgCache::PkgIterator mP = PkgManager::cache() -> PkgBegin (); ! mP . end (); mP ++) {
+ s = PkgManager::cache() -> extState (mP);
+ if (s -> a_unwanted_pri > s -> a_wanted_pri) {
+ cout << mP . Name ()
+ << ": a_wanted_pri = " << s -> a_wanted_pri
+ << ", a_unwanted_pri = " << s -> a_unwanted_pri << endl;
+ }
+ }
+ }
+}
diff --git a/adept/tests/libcapture/stl_util-test.cpp b/adept/tests/libcapture/stl_util-test.cpp
new file mode 100644
index 0000000..a083db8
--- /dev/null
+++ b/adept/tests/libcapture/stl_util-test.cpp
@@ -0,0 +1,56 @@
+#include "stl_util.h"
+#include <iostream>
+#include <tut.h>
+
+namespace tut {
+
+ using namespace std;
+ using namespace capture;
+
+ struct stl_util_shar {
+ };
+
+ typedef test_group<stl_util_shar> tg;
+ typedef tg::object to;
+ tg stl_util_tg ("stl_util");
+
+ template<> template<>
+ void to::test<1> ()
+ {
+ argmap test;
+ test["test1"] = "test2";
+ test["fjioj @,,ping"] = "jfdiosqj @@,,";
+ test[",,"] = "#@@@";
+ string out = argmap2string( test );
+ argmap test2 = string2argmap( out );
+ ensure( test2.size() == 3 );
+ ensure( test2["test1"] == "test2" );
+ ensure( test2["fjioj @,,ping"] == "jfdiosqj @@,," );
+ ensure( test2[",,"] == "#@@@" );
+ }
+ template<> template<>
+ void to::test<2> ()
+ {
+ list <string> test;
+ test . push_back (string ("test, #1"));
+ test . push_back (string ("test, #2"));
+ string joinedf2 = join( test, "," );
+ test . push_back ( joinedf2 );
+ list<string> testret = explode (join (test, ","), ",");
+ ensure( test.size() == testret.size() );
+ list<string>::iterator i, j;
+ i = test.begin();
+ j = testret.begin();
+ for ( ; i != test.end(); ++i, ++j )
+ ensure( *i == *j );
+
+ string joinedf3 = join( test, "," );
+ test.push_back( joinedf3 );
+ string str = join (test, "::");
+ testret = explode (str, "::");
+ i = test.begin();
+ j = testret.begin();
+ for ( ; i != test.end(); ++i, ++j )
+ ensure( *i == *j );
+ }
+}
diff --git a/adept/tests/libcapture/tree-test.cpp b/adept/tests/libcapture/tree-test.cpp
new file mode 100644
index 0000000..0e2f8d5
--- /dev/null
+++ b/adept/tests/libcapture/tree-test.cpp
@@ -0,0 +1,86 @@
+// #define protected public
+// #define private public
+#include <libcapture/tree.h>
+#include <libcapture/treenode.h>
+#include <libcapture/treefactory.h>
+
+#include <tut.h>
+
+namespace tut {
+
+ using namespace std;
+ using namespace capture;
+
+ struct tree_shar {
+ };
+
+ typedef test_group<tree_shar> tg;
+ typedef tg::object to;
+ tg tree_tg ("tree");
+
+ class STF: public TreeFactory
+ {
+ public:
+ TreePkgNode *makePkgNode (TreeNode *parent, pkgCache::PkgIterator P)
+ { return new TreePkgNode (parent, P); }
+ TreeBranchNode *makeBranchNode (TreeNode *parent, string id, string name)
+ { return new TreeBranchNode (parent, id, name); }
+ TreeGroupNode *makeGroupNode (TreeNode *parent, pkgTagSection s)
+ { return new TreeGroupNode (parent, s); }
+ TreeBranchNode *makeRoot () { return new TreeBranchNode (0, "ROOT"); }
+ TreeDepNode *makeDepNode (TreeNode *parent, pkgCache::DepIterator) { return 0; }
+ TreeVerNode *makeVerNode (TreeNode *parent, pkgCache::VerIterator) { return 0; }
+ };
+
+ /* class TestProd: public NodeProducer {
+ public:
+ Tree *t;
+ void getNodes (TreeFactory *f, NodeConsumer *c)
+ {
+ TreeNode *a, *b;
+ a = t -> top ();
+ // c -> consumeNode (a = f -> makeBNode (t -> top (), "blah1"));
+ c -> consumeNode (f -> makePkgNode (a, pkgCache::PkgIterator ()));
+ c -> consumeNode (f -> makePkgNode (a, pkgCache::PkgIterator ()));
+ c -> consumeNode (f -> makePkgNode (a, pkgCache::PkgIterator ()));
+ // c -> consumeNode (b = f -> makeBNode (t -> top (), "blah2"));
+ // c -> consumeNode (f -> makePkg (b, pkgCache::PkgIterator ()));
+ // c -> consumeNode (f -> makePkg (b, pkgCache::PkgIterator ()));
+ }
+ }; */
+ template<> template<>
+ void to::test<1> ()
+ {
+ TreeFactory *f = new STF;
+ TestProd *p = new TestProd;
+ Tree *t = new Tree;
+ GrouperChain *c = new GrouperChain ("grouperchain");
+ c -> addFactory ("EndGrouper", "end");
+ t -> setGrouper (c);
+ t -> setProducer (p);
+ t -> setTreeFact (f);
+ p -> t = t;
+ t -> rebuild ();
+
+ TreeNode *A, *B, *C;
+ ensure (t -> top ());
+ A = t -> top () -> firstChild ();
+ ensure (A);
+ B = A -> nextSibling ();
+ ensure (B);
+ for (C = B; C -> nextSibling (); C = C -> nextSibling ());
+ ensure (C);
+ ensure (A -> nextSibling () == B);
+ ensure (B -> nextSibling () == C);
+ t -> refresh ();
+ ensure (t -> top ());
+ A = t -> top () -> firstChild ();
+ ensure (A);
+ B = A -> nextSibling ();
+ ensure (B);
+ for (C = B; C -> nextSibling (); C = C -> nextSibling ());
+ ensure (C);
+ ensure (A -> nextSibling () == B);
+ ensure (B -> nextSibling () == C);
+ }
+};
diff --git a/adept/tests/tut-main.cpp b/adept/tests/tut-main.cpp
new file mode 100644
index 0000000..5c278a1
--- /dev/null
+++ b/adept/tests/tut-main.cpp
@@ -0,0 +1,61 @@
+#include <tut.h>
+#include <tut_reporter.h>
+#include <iostream>
+
+namespace tut
+{
+ test_runner_singleton runner;
+}
+
+int main(int argc,const char* argv[])
+{
+ tut::reporter visi;
+
+ if( argc < 2 || argc > 3 )
+ {
+ std::cout << "TUT example test application." << std::endl;
+ std::cout << "Usage: example [regression] | [list] | [ group] [test]" << std::endl;
+ std::cout << " List all groups: example list" << std::endl;
+ std::cout << " Run all tests: example regression" << std::endl;
+ std::cout << " Run one group: example std::auto_ptr" << std::endl;
+ std::cout << " Run one test: example std::auto_ptr 3" << std::endl;;
+ }
+
+ std::cout << "\nFAILURE and EXCEPTION in these tests are FAKE ;)\n\n";
+
+ tut::runner.get().set_callback(&visi);
+
+ try
+ {
+ if( argc == 1 || (argc == 2 && std::string(argv[1]) == "regression") )
+ {
+ tut::runner.get().run_tests();
+ }
+ else if( argc == 2 && std::string(argv[1]) == "list" )
+ {
+ std::cout << "registered test groups:" << std::endl;
+ tut::groupnames gl = tut::runner.get().list_groups();
+ tut::groupnames::const_iterator i = gl.begin();
+ tut::groupnames::const_iterator e = gl.end();
+ while( i != e )
+ {
+ std::cout << " " << *i << std::endl;
+ ++i;
+ }
+ }
+ else if( argc == 2 && std::string(argv[1]) != "regression" )
+ {
+ tut::runner.get().run_tests(argv[1]);
+ }
+ else if( argc == 3 )
+ {
+ tut::runner.get().run_test(argv[1],::atoi(argv[2]));
+ }
+ }
+ catch( const std::exception& ex )
+ {
+ std::cerr << "tut raised ex: " << ex.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/adept/tests/tut.h b/adept/tests/tut.h
new file mode 100644
index 0000000..dec471a
--- /dev/null
+++ b/adept/tests/tut.h
@@ -0,0 +1,872 @@
+#ifndef TUT_H_GUARD
+#define TUT_H_GUARD
+
+#include <iostream>
+#include <map>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <typeinfo>
+
+#if defined(TUT_USE_SEH)
+#include <windows.h>
+#include <winbase.h>
+#endif
+
+/**
+ * Template Unit Tests Framework for C++.
+ * http://tut.dozen.ru
+ *
+ * @author dozen, tut@dozen.ru
+ */
+namespace tut
+{
+ /**
+ * Exception to be throwed when attempted to execute
+ * missed test by number.
+ */
+ struct no_such_test : public std::logic_error
+ {
+ no_such_test() : std::logic_error("no such test"){};
+ };
+
+ /**
+ * No such test and passed test number is higher than
+ * any test number in current group. Used in one-by-one
+ * test running when upper bound is not known.
+ */
+ struct beyond_last_test : public no_such_test
+ {
+ beyond_last_test(){};
+ };
+
+ /**
+ * Group not found exception.
+ */
+ struct no_such_group : public std::logic_error
+ {
+ no_such_group(const std::string& grp) :
+ std::logic_error(grp){};
+ };
+
+ /**
+ * Internal exception to be throwed when
+ * no more tests left in group or journal.
+ */
+ struct no_more_tests
+ {
+ no_more_tests(){};
+ };
+
+ /**
+ * Exception to be throwed when ensure() fails or fail() called.
+ */
+ class failure : public std::logic_error
+ {
+ public:
+ failure(const std::string& msg) : std::logic_error(msg){};
+ };
+
+ /**
+ * Exception to be throwed when test desctructor throwed an exception.
+ */
+ class warning : public std::logic_error
+ {
+ public:
+ warning(const std::string& msg) : std::logic_error(msg){};
+ };
+
+ /**
+ * Exception to be throwed when test issued SEH (Win32)
+ */
+ class seh : public std::logic_error
+ {
+ public:
+ seh(const std::string& msg) : std::logic_error(msg){};
+ };
+
+ /**
+ * Return type of runned test/test group.
+ *
+ * For test: contains result of test and, possible, message
+ * for failure or exception.
+ */
+ struct test_result
+ {
+ /**
+ * Test group name.
+ */
+ std::string group;
+
+ /**
+ * Test number in group.
+ */
+ int test;
+
+ /**
+ * ok - test finished successfully
+ * fail - test failed with ensure() or fail() methods
+ * ex - test throwed an exceptions
+ * warn - test finished successfully, but test destructor throwed
+ * term - test forced test application to terminate abnormally
+ */
+ typedef enum { ok, fail, ex, warn, term } result_type;
+ result_type result;
+
+ /**
+ * Exception message for failed test.
+ */
+ std::string message;
+ std::string exception_typeid;
+
+ /**
+ * Default constructor.
+ */
+ test_result()
+ : test(0),result(ok)
+ {
+ }
+
+ /**
+ * Constructor.
+ */
+ test_result( const std::string& grp,int pos,result_type res)
+ : group(grp),test(pos),result(res)
+ {
+ }
+
+ /**
+ * Constructor with exception.
+ */
+ test_result( const std::string& grp,int pos,
+ result_type res,
+ const std::exception& ex)
+ : group(grp),test(pos),result(res),
+ message(ex.what()),exception_typeid(typeid(ex).name())
+ {
+ }
+ };
+
+ /**
+ * Interface.
+ * Test group operations.
+ */
+ struct group_base
+ {
+ virtual ~group_base(){};
+
+ // execute tests iteratively
+ virtual void rewind() = 0;
+ virtual test_result run_next() = 0;
+
+ // execute one test
+ virtual test_result run_test(int n) = 0;
+ };
+
+ /**
+ * Test runner callback interface.
+ * Can be implemented by caller to update
+ * tests results in real-time. User can implement
+ * any of callback methods, and leave unused
+ * in default implementation.
+ */
+ struct callback
+ {
+ /**
+ * Virtual destructor is a must for subclassed types.
+ */
+ virtual ~callback(){};
+
+ /**
+ * Called when new test run started.
+ */
+ virtual void run_started(){};
+
+ /**
+ * Called when a test finished.
+ * @param tr Test results.
+ */
+ virtual void test_completed(const test_result& /*tr*/){};
+
+ /**
+ * Called when all tests in run completed.
+ */
+ virtual void run_completed(){};
+ };
+
+ /**
+ * Typedef for runner::list_groups()
+ */
+ typedef std::vector<std::string> groupnames;
+
+ /**
+ * Test runner.
+ */
+ class test_runner
+ {
+ protected:
+ typedef std::map<std::string,group_base*> groups;
+ typedef groups::iterator iterator;
+ typedef groups::const_iterator const_iterator;
+ groups groups_;
+
+ callback default_callback_;
+ callback* callback_;
+
+ public:
+ /**
+ * Constructor
+ */
+ test_runner() : callback_(&default_callback_)
+ {
+ }
+
+ /**
+ * Stores another group for getting by name.
+ */
+ void register_group(const std::string& name,group_base* gr)
+ {
+ if( gr == 0 )
+ {
+ throw std::invalid_argument("group shall be non-null");
+ }
+
+ groups::iterator found = groups_.find(name);
+ if( found != groups_.end() )
+ {
+ std::string msg("attempt to add already existent group "+name);
+ // this exception terminates application so we use cerr also
+ std::cerr << msg << std::endl;
+ throw std::logic_error(msg);
+ }
+
+ groups_[name] = gr;
+ }
+
+ /**
+ * Stores callback object.
+ */
+ void set_callback(callback* cb)
+ {
+ callback_ = cb==0? &default_callback_:cb;
+ }
+
+ /**
+ * Returns callback object.
+ */
+ callback& get_callback() const
+ {
+ return *callback_;
+ }
+
+ /**
+ * Returns list of known test groups.
+ */
+ const groupnames list_groups() const
+ {
+ groupnames ret;
+ const_iterator i = groups_.begin();
+ const_iterator e = groups_.end();
+ while( i != e )
+ {
+ ret.push_back(i->first);
+ ++i;
+ }
+ return ret;
+ }
+
+ /**
+ * Runs all tests in all groups.
+ * @param callback Callback object if exists; null otherwise
+ */
+ void run_tests() const
+ {
+ callback_->run_started();
+
+ const_iterator i = groups_.begin();
+ const_iterator e = groups_.end();
+ while( i != e )
+ {
+ try
+ {
+ // iterate all tests
+ i->second->rewind();
+ for( ;; )
+ {
+ test_result tr = i->second->run_next();
+ callback_->test_completed(tr);
+ }
+ }
+ catch( const no_more_tests& )
+ {
+ // ok
+ }
+
+ ++i;
+ }
+
+ callback_->run_completed();
+ }
+
+ /**
+ * Runs all tests in specified group.
+ */
+ void run_tests(const std::string& group_name) const
+ {
+ callback_->run_started();
+
+ const_iterator i = groups_.find(group_name);
+ if( i == groups_.end() )
+ {
+ throw no_such_group(group_name);
+ }
+
+ try
+ {
+ // iterate all tests
+ i->second->rewind();
+ for(;;)
+ {
+ test_result tr = i->second->run_next();
+ callback_->test_completed(tr);
+ }
+ }
+ catch( const no_more_tests& )
+ {
+ // ok
+ }
+
+ callback_->run_completed();
+ }
+
+ /**
+ * Runs one test in specified group.
+ */
+ test_result run_test(const std::string& group_name,int n) const
+ {
+ callback_->run_started();
+
+ const_iterator i = groups_.find(group_name);
+ if( i == groups_.end() )
+ {
+ throw no_such_group(group_name);
+ }
+
+ try
+ {
+ test_result tr = i->second->run_test(n);
+ callback_->test_completed(tr);
+ callback_->run_completed();
+ return tr;
+ }
+ catch( const beyond_last_test& )
+ {
+ callback_->run_completed();
+ throw;
+ }
+ catch( const no_such_test& )
+ {
+ callback_->run_completed();
+ throw;
+ }
+ }
+ };
+
+ /**
+ * Singleton for test_runner implementation.
+ * Instance with name runner_singleton shall be implemented
+ * by user.
+ */
+ class test_runner_singleton
+ {
+ public:
+ static test_runner& get()
+ {
+ static test_runner tr;
+ return tr;
+ }
+ };
+ extern test_runner_singleton runner;
+
+ /**
+ * Test object. Contains data test run upon and default test method
+ * implementation. Inherited from Data to allow tests to
+ * access test data as members.
+ */
+ template <class Data>
+ class test_object : public Data
+ {
+ public:
+ /**
+ * Default constructor
+ */
+ test_object(){};
+
+ /**
+ * The flag is set to true by default (dummy) test.
+ * Used to detect usused test numbers and avoid unnecessary
+ * test object creation which may be time-consuming depending
+ * on operations described in Data::Data() and Data::~Data().
+ * TODO: replace with throwing special exception from default test.
+ */
+ bool called_method_was_a_dummy_test_;
+
+ /**
+ * Default do-nothing test.
+ */
+ template <int n>
+ void test()
+ {
+ called_method_was_a_dummy_test_ = true;
+ }
+ };
+
+ namespace
+ {
+ /**
+ * Tests provided condition.
+ * Throws if false.
+ */
+ void ensure(bool cond)
+ {
+ if( !cond ) throw failure("");
+ }
+
+ /**
+ * Tests provided condition.
+ * Throws if false.
+ */
+ void ensure(const char* msg,bool cond)
+ {
+ if( !cond ) throw failure(msg);
+ }
+
+ /**
+ * Tests two objects for being equal.
+ * Throws if false.
+ *
+ * NB: both T and Q must have operator << defined somewhere, or
+ * client code will not compile at all!
+ */
+ template <class T,class Q>
+ void ensure_equals(const char* msg,const Q& actual,const T& expected)
+ {
+ if( expected != actual )
+ {
+ std::stringstream ss;
+ ss << (msg?msg:"") << (msg?": ":"") << "expected " << expected << " actual " << actual;
+ throw failure(ss.str().c_str());
+ }
+ }
+
+ template <class T,class Q>
+ void ensure_equals(const Q& actual,const T& expected)
+ {
+ ensure_equals<>(0,actual,expected);
+ }
+
+ /**
+ * Tests two objects for being at most in given distance one from another.
+ * Borders are excluded.
+ * Throws if false.
+ *
+ * NB: T must have operator << defined somewhere, or
+ * client code will not compile at all! Also, T shall have
+ * operators + and -, and be comparable.
+ */
+ template <class T>
+ void ensure_distance(const char* msg,const T& actual,const T& expected,const T& distance)
+ {
+ if( expected-distance >= actual || expected+distance <= actual )
+ {
+ std::stringstream ss;
+ ss << (msg?msg:"") << (msg?": ":"") << "expected [" << expected-distance << ";"
+ << expected+distance << "] actual " << actual;
+ throw failure(ss.str().c_str());
+ }
+ }
+
+ template <class T>
+ void ensure_distance(const T& actual,const T& expected,const T& distance)
+ {
+ ensure_distance<>(0,actual,expected,distance);
+ }
+
+ /**
+ * Unconditionally fails with message.
+ */
+ void fail(const char* msg="")
+ {
+ throw failure(msg);
+ }
+ }
+
+ /**
+ * Walks through test tree and stores address of each
+ * test method in group. Instantiation stops at 0.
+ */
+ template <class Test,class Group,int n>
+ struct tests_registerer
+ {
+ static void reg(Group& group)
+ {
+ group.reg(n,&Test::template test<n>);
+ tests_registerer<Test,Group,n-1>::reg(group);
+ }
+ };
+
+ template<class Test,class Group>
+ struct tests_registerer<Test,Group,0>
+ {
+ static void reg(Group&){};
+ };
+
+ /**
+ * Test group; used to recreate test object instance for
+ * each new test since we have to have reinitialized
+ * Data base class.
+ */
+ template <class Data,int MaxTestsInGroup = 50>
+ class test_group : public group_base
+ {
+ const char* name_;
+
+ typedef void (test_object<Data>::*testmethod)();
+ typedef std::map<int,testmethod> tests;
+ typedef typename tests::iterator tests_iterator;
+ typedef typename tests::const_iterator tests_const_iterator;
+ typedef typename tests::const_reverse_iterator
+ tests_const_reverse_iterator;
+ typedef typename tests::size_type size_type;
+
+ tests tests_;
+ tests_iterator current_test_;
+
+ /**
+ * Exception-in-destructor-safe smart-pointer class.
+ */
+ template <class T>
+ class safe_holder
+ {
+ T* p_;
+ bool permit_throw_in_dtor;
+
+ safe_holder(const safe_holder&);
+ safe_holder& operator = (const safe_holder&);
+
+ public:
+ safe_holder() : p_(0),permit_throw_in_dtor(false)
+ {
+ }
+
+ ~safe_holder()
+ {
+ release();
+ }
+
+ T* operator -> () const { return p_; };
+ T* get() const { return p_; };
+
+ /**
+ * Tell ptr it can throw from destructor. Right way is to
+ * use std::uncaught_exception(), but some compilers lack
+ * correct implementation of the function.
+ */
+ void permit_throw(){ permit_throw_in_dtor = true; }
+
+ /**
+ * Specially treats exceptions in test object destructor;
+ * if test itself failed, exceptions in destructor
+ * are ignored; if test was successful and destructor failed,
+ * warning exception throwed.
+ */
+ void release()
+ {
+ try
+ {
+ if( delete_obj() == false )
+ {
+ throw warning("destructor of test object raised an SEH exception");
+ }
+ }
+ catch( const std::exception& ex )
+ {
+ if( permit_throw_in_dtor )
+ {
+ std::string msg = "destructor of test object raised exception: ";
+ msg += ex.what();
+ throw warning(msg);
+ }
+ }
+ catch( ... )
+ {
+ if( permit_throw_in_dtor )
+ {
+ throw warning("destructor of test object raised an exception");
+ }
+ }
+ }
+
+ /**
+ * Re-init holder to get brand new object.
+ */
+ void reset()
+ {
+ release();
+ permit_throw_in_dtor = false;
+ p_ = new T();
+ }
+
+ bool delete_obj()
+ {
+#if defined(TUT_USE_SEH)
+ __try
+ {
+#endif
+ T* p = p_;
+ p_ = 0;
+ delete p;
+#if defined(TUT_USE_SEH)
+ }
+ __except(handle_seh_(::GetExceptionCode()))
+ {
+ if( permit_throw_in_dtor )
+ {
+ return false;
+ }
+ }
+#endif
+ return true;
+ }
+ };
+
+ public:
+ typedef test_object<Data> object;
+
+ /**
+ * Creates and registers test group with specified name.
+ */
+ test_group(const char* name)
+ : name_(name)
+ {
+ // register itself
+ runner.get().register_group(name_,this);
+
+ // register all tests
+ tests_registerer<object,test_group,MaxTestsInGroup>::reg(*this);
+ };
+
+ /**
+ * This constructor is used in self-test run only.
+ */
+ test_group(const char* name,test_runner& another_runner)
+ : name_(name)
+ {
+ // register itself
+ another_runner.register_group(name_,this);
+
+ // register all tests
+ tests_registerer<test_object<Data>,
+ test_group,MaxTestsInGroup>::reg(*this);
+ };
+
+ /**
+ * Registers test method under given number.
+ */
+ void reg(int n,testmethod tm)
+ {
+ tests_[n] = tm;
+ }
+
+ /**
+ * Reset test position before first test.
+ */
+ void rewind()
+ {
+ current_test_ = tests_.begin();
+ }
+
+ /**
+ * Runs next test.
+ */
+ test_result run_next()
+ {
+ if( current_test_ == tests_.end() )
+ {
+ throw no_more_tests();
+ }
+
+ // find next user-specialized test
+ safe_holder<object> obj;
+ while( current_test_ != tests_.end() )
+ {
+ try
+ {
+ return run_test_(current_test_++,obj);
+ }
+ catch( const no_such_test& )
+ {
+ continue;
+ }
+ }
+
+ throw no_more_tests();
+ }
+
+ /**
+ * Runs one test by position.
+ */
+ test_result run_test(int n)
+ {
+ // beyond tests is special case to discover upper limit
+ if( tests_.rbegin() == tests_.rend() ) throw beyond_last_test();
+ if( tests_.rbegin()->first < n ) throw beyond_last_test();
+
+ // withing scope; check if given test exists
+ tests_iterator ti = tests_.find(n);
+ if( ti == tests_.end() ) throw no_such_test();
+
+ safe_holder<object> obj;
+ return run_test_(ti,obj);
+ }
+
+ private:
+ /**
+ * VC allows only one exception handling type per function,
+ * so I have to split the method
+ */
+ test_result run_test_(const tests_iterator& ti,safe_holder<object>& obj)
+ {
+ try
+ {
+ if( run_test_seh_(ti->second,obj) == false )
+ throw seh("seh");
+ }
+ catch(const no_such_test&)
+ {
+ throw;
+ }
+ catch(const warning& ex)
+ {
+ // test ok, but destructor failed
+ test_result tr(name_,ti->first,test_result::warn,ex);
+ return tr;
+ }
+ catch(const failure& ex)
+ {
+ // test failed because of ensure() or similar method
+ test_result tr(name_,ti->first,test_result::fail,ex);
+ return tr;
+ }
+ catch(const seh& ex)
+ {
+ // test failed with sigsegv, divide by zero, etc
+ test_result tr(name_,ti->first,test_result::term,ex);
+ return tr;
+ }
+ catch(const std::exception& ex)
+ {
+ // test failed with std::exception
+ test_result tr(name_,ti->first,test_result::ex,ex);
+ return tr;
+ }
+ catch(...)
+ {
+ // test failed with unknown exception
+ test_result tr(name_,ti->first,test_result::ex);
+ return tr;
+ }
+
+ // test passed
+ test_result tr(name_,ti->first,test_result::ok);
+ return tr;
+ }
+
+ /**
+ * Runs one under SEH if platform supports it.
+ */
+ bool run_test_seh_(testmethod tm,safe_holder<object>& obj)
+ {
+#if defined(TUT_USE_SEH)
+ __try
+ {
+#endif
+ if( obj.get() == 0 ) obj.reset();
+ obj->called_method_was_a_dummy_test_ = false;
+
+#if defined(TUT_USE_SEH)
+ __try
+ {
+#endif
+ (obj.get()->*tm)();
+#if defined(TUT_USE_SEH)
+ }
+ __except(handle_seh_(::GetExceptionCode()))
+ {
+ // throw seh("SEH");
+ return false;
+ }
+#endif
+
+ if( obj->called_method_was_a_dummy_test_ )
+ {
+ // do not call obj.release(); reuse object
+ throw no_such_test();
+ }
+
+ obj.permit_throw();
+ obj.release();
+#if defined(TUT_USE_SEH)
+ }
+ __except(handle_seh_(::GetExceptionCode()))
+ {
+ // throw seh("SEH");
+ return false;
+ }
+#endif
+ return true;
+ }
+ };
+
+
+#if defined(TUT_USE_SEH)
+ /**
+ * Decides should we execute handler or ignore SE.
+ */
+ inline int handle_seh_(DWORD excode)
+ {
+ switch(excode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ case EXCEPTION_BREAKPOINT:
+ case EXCEPTION_SINGLE_STEP:
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_STACK_CHECK:
+ case EXCEPTION_FLT_UNDERFLOW:
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ case EXCEPTION_INT_OVERFLOW:
+ case EXCEPTION_PRIV_INSTRUCTION:
+ case EXCEPTION_IN_PAGE_ERROR:
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ case EXCEPTION_STACK_OVERFLOW:
+ case EXCEPTION_INVALID_DISPOSITION:
+ case EXCEPTION_GUARD_PAGE:
+ case EXCEPTION_INVALID_HANDLE:
+ return EXCEPTION_EXECUTE_HANDLER;
+ };
+
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+#endif
+}
+
+#endif
+
diff --git a/adept/tests/tut_reporter.h b/adept/tests/tut_reporter.h
new file mode 100644
index 0000000..941d653
--- /dev/null
+++ b/adept/tests/tut_reporter.h
@@ -0,0 +1,182 @@
+#ifndef TUT_REPORTER
+#define TUT_REPORTER
+
+#include <tut.h>
+
+/**
+ * Template Unit Tests Framework for C++.
+ * http://tut.dozen.ru
+ *
+ * @author dozen, tut@dozen.ru
+ */
+namespace
+{
+ std::ostream& operator << (std::ostream& os,const tut::test_result& tr)
+ {
+ switch(tr.result)
+ {
+ case tut::test_result::ok:
+ os << '.';
+ break;
+
+ case tut::test_result::fail:
+ os << '[' << tr.test << "=F]";
+ break;
+
+ case tut::test_result::ex:
+ os << '[' << tr.test << "=X]";
+ break;
+
+ case tut::test_result::warn:
+ os << '[' << tr.test << "=W]";
+ break;
+
+ case tut::test_result::term:
+ os << '[' << tr.test << "=T]";
+ break;
+ }
+
+ return os;
+ }
+}
+
+namespace tut
+{
+ /**
+ * Default TUT callback handler.
+ */
+ class reporter : public tut::callback
+ {
+ std::string current_group;
+ typedef std::vector<tut::test_result> not_passed_list;
+ not_passed_list not_passed;
+ std::ostream& os;
+
+ public:
+ int ok_count;
+ int exceptions_count;
+ int failures_count;
+ int terminations_count;
+ int warnings_count;
+
+ reporter() : os(std::cout)
+ {
+ init();
+ }
+
+ reporter(std::ostream& out) : os(out)
+ {
+ init();
+ }
+
+ void run_started()
+ {
+ init();
+ }
+
+ void test_completed(const tut::test_result& tr)
+ {
+ if( tr.group != current_group )
+ {
+ os << std::endl << tr.group << ": " << std::flush;
+ current_group = tr.group;
+ }
+
+ os << tr << std::flush;
+ if( tr.result == tut::test_result::ok ) ok_count++;
+ else if( tr.result == tut::test_result::ex ) exceptions_count++;
+ else if( tr.result == tut::test_result::fail ) failures_count++;
+ else if( tr.result == tut::test_result::warn ) warnings_count++;
+ else terminations_count++;
+
+ if( tr.result != tut::test_result::ok )
+ {
+ not_passed.push_back(tr);
+ }
+ }
+
+ void run_completed()
+ {
+ os << std::endl;
+
+ if( not_passed.size() > 0 )
+ {
+ not_passed_list::const_iterator i = not_passed.begin();
+ while( i != not_passed.end() )
+ {
+ tut::test_result tr = *i;
+
+ os << std::endl;
+
+ os << "---> " << "test: " << tr.group << ", test<" << tr.test << ">" << std::endl;
+
+ os << " problem: ";
+ switch(tr.result)
+ {
+ case test_result::fail:
+ os << "assertion failed" << std::endl;
+ break;
+ case test_result::ex:
+ os << "unexpected exception" << std::endl;
+ if( tr.exception_typeid != "" )
+ {
+ os << " exception typeid: "
+ << tr.exception_typeid << std::endl;
+ }
+ break;
+ case test_result::term:
+ os << "would be terminated" << std::endl;
+ break;
+ case test_result::warn:
+ os << "test passed, but cleanup code (destructor) raised an exception" << std::endl;
+ break;
+ default: break;
+ }
+
+ if( tr.message != "" )
+ {
+ if( tr.result == test_result::fail )
+ {
+ os << " failed assertion: \"" << tr.message << "\"" << std::endl;
+ }
+ else
+ {
+ os << " message: \"" << tr.message << "\"" << std::endl;
+ }
+ }
+
+ ++i;
+ }
+ }
+
+ os << std::endl;
+
+ os << "tests summary:";
+ if( terminations_count > 0 ) os << " terminations:" << terminations_count;
+ if( exceptions_count > 0 ) os << " exceptions:" << exceptions_count;
+ if( failures_count > 0 ) os << " failures:" << failures_count;
+ if( warnings_count > 0 ) os << " warnings:" << warnings_count;
+ os << " ok:" << ok_count;
+ os << std::endl;
+ }
+
+ bool all_ok() const
+ {
+ return not_passed.size() == 0;
+ }
+
+ private:
+ void init()
+ {
+ ok_count = 0;
+ exceptions_count = 0;
+ failures_count = 0;
+ terminations_count = 0;
+ warnings_count = 0;
+
+ not_passed.clear();
+ }
+ };
+};
+
+#endif
diff --git a/adept/updater/Makefile.am b/adept/updater/Makefile.am
new file mode 100644
index 0000000..83afaae
--- /dev/null
+++ b/adept/updater/Makefile.am
@@ -0,0 +1,21 @@
+
+bin_PROGRAMS = adept_updater
+noinst_HEADERS = app.h
+adept_updater_SOURCES = main.cpp app.cpp
+adept_updater_LDADD = ../adept/libadept.la $(LIBAPT_FRONT_LIBS) $(LIBEPT_LIBS) $(LIBTAGCOLL2_LIBS) $(LIBWIBBLE_LIBS) $(LIB_KIO) $(LIBKDE_UI) ../kubuntu_upgrader/libkubuntuupgradewizard.la
+adept_updater_LDFLAGS = -L/usr/lib/debug
+INCLUDES = $(all_includes) $(LIBAPT_FRONT_CFLAGS) $(LIBEPT_CFLAGS) $(LIBTAGCOLL2_CFLAGS) $(LIBWIBBLE_CFLAGS) -I$(srcdir)/.. -I..
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -DQT_NO_ASCII_CAST -DQT_NO_CAST_ASCII
+METASOURCES = AUTO
+KDE_ICON = AUTO
+
+rcdir = $(kde_datadir)/adept_updater
+rc_DATA = adept_updaterui.rc
+
+#shelldesktopdir = $(kde_appsdir)/System
+xdg_apps_DATA = adept_updater.desktop
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(EXTRACTRC) `find . -name "*.rc"` >> rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/adept_updater.pot
diff --git a/adept/updater/adept_updater.desktop b/adept/updater/adept_updater.desktop
new file mode 100644
index 0000000..8dae4d6
--- /dev/null
+++ b/adept/updater/adept_updater.desktop
@@ -0,0 +1,69 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Adept Updater
+Name[bg]=Обновяване на Adept
+Name[ca]=Actualitzador Adept
+Name[da]=Adept-opdatering
+Name[el]=Ανανεωτής Adept
+Name[es]=Actualizador experto
+Name[et]=Adepti uuendaja
+Name[fr]=Mise à jour Adept
+Name[ga]=Nuashonróir Adept
+Name[gl]=Actualizador de Adept
+Name[it]=Aggiornamento Adept
+Name[ka]=Adept განმაახლებელი
+Name[lt]=Adept atnaujinimai
+Name[pt]=Actualizador do Adept
+Name[sk]=Adept aktualizácia
+Name[sv]=Adept-uppdaterare
+Name[xx]=xxAdept Updaterxx
+GenericName=System Update Wizard
+GenericName[bg]=Обновяване на Adept
+GenericName[ca]=Assistent d'actualització del sistema
+GenericName[cs]=Průvodce aktualizací systému
+GenericName[da]=Systemopdateringsguide
+GenericName[de]=Systemaktualisierungsassistent
+GenericName[el]=Μάγος ενημέρωσης συστήματος
+GenericName[es]=Asistente de actualización del sistema
+GenericName[et]=Süsteemi uuendamine nõustaja
+GenericName[fr]=Assistant de mise à jour du système
+GenericName[gl]=Asistente de Actualizazón do Sistema
+GenericName[it]=Procedura guidata aggiornamento sistema
+GenericName[ja]=システムアップデートウィザード
+GenericName[ka]=სისტემის განახლების ოსტატი
+GenericName[lt]=Sistemos atnaujinimo vediklis
+GenericName[nl]=Systeem-update-assistent
+GenericName[pt]=Assistente de Actualização do Sistema
+GenericName[sk]=Sprievodca systémovou aktualizáciou
+GenericName[sv]=Systemuppdateringsguide
+GenericName[xx]=xxSystem Update Wizardxx
+Exec=/opt/kde3/bin/adept_updater
+Categories=Qt;KDE;System;
+Icon=adept_updater
+Type=Application
+X-KDE-SubstituteUID=true
+Comment=Update installed software
+Comment[bg]=Обновяване на инсталиран софтуер
+Comment[ca]=Actualitza el programari instal·lat
+Comment[cs]=Aktualizace nainstalovaného softwaru
+Comment[da]=Opdatér installeret programmel
+Comment[de]=Aktualisiert installierte Software
+Comment[el]=Ενημέρωση εγκατεστημένου λογισμικού
+Comment[es]=Actualizar el software instalado
+Comment[et]=Paigaldatud tarkvara uuendamine
+Comment[fr]=Mise à jour des logiciels installés
+Comment[ga]=Nuashonraigh bogearraí suiteáilte
+Comment[gl]=Actualiza o software instalado
+Comment[it]=Aggiorna il software installato
+Comment[ja]=インストール済みのソフトウェアをアップデート
+Comment[ka]=დაყენებული პროგრამების განახლება
+Comment[lt]=Įdiegtų programų atnaujinimas
+Comment[nl]=Geïnstalleerde software bijwerken
+Comment[pt]=Actualiza o 'software' instalado
+Comment[sk]=Aktualizácia inštalovaného softwaru
+Comment[sr]=Ажурира инсталиране програме
+Comment[sr@Latn]=Ažurira instalirane programe
+Comment[sv]=Uppdatera installerad programvara
+Comment[xx]=xxUpdate installed softwarexx
+Terminal=false
+NoDisplay=true
diff --git a/adept/updater/adept_updaterui.rc b/adept/updater/adept_updaterui.rc
new file mode 100644
index 0000000..083b9e8
--- /dev/null
+++ b/adept/updater/adept_updaterui.rc
@@ -0,0 +1,16 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="6" name="adept-updater">
+ <MenuBar>
+ <Menu name="file" noMerge="1">
+ <text>&amp;Adept</text>
+ <Action name="file_quit" />
+ </Menu>
+ <Menu name="edit" noMerge="1">
+ <text>&amp;Edit</text>
+ <Action name="edit_undo" />
+ <Action name="edit_redo" />
+ </Menu>
+ </MenuBar>
+ <ToolBar name="mainToolBar" noMerge="1">
+ </ToolBar>
+</kpartgui>
diff --git a/adept/updater/app.cpp b/adept/updater/app.cpp
new file mode 100644
index 0000000..c16424b
--- /dev/null
+++ b/adept/updater/app.cpp
@@ -0,0 +1,275 @@
+#define KUBUNTU
+
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qsplitter.h>
+#include <qtimer.h>
+#include <qwidgetstack.h>
+
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kaction.h>
+#include <kactionclasses.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kparts/part.h>
+#include <ktrader.h>
+#include <klibloader.h>
+#include <kstatusbar.h>
+
+#include <apt-pkg/packagemanager.h>
+#include <apt-front/manager.h>
+#include <apt-front/init.h>
+#include <apt-front/cache/entity/package.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+#include <apt-front/predicate/factory.h>
+
+#include <adept/acqprogresswidget.h>
+#include <adept/progress.h>
+#include <adept/utils.h>
+
+#ifdef KUBUNTU
+#include <kubuntu_upgrader/upgradewizard.h>
+#endif
+
+#include "app.h"
+
+using namespace aptFront;
+using namespace aptFront::cache;
+using namespace adept;
+
+void WaitForLister::waiting()
+{
+ kdDebug() << "WaitForLister::waiting()" << endl;
+ if (app->m_list->searchView()->lister()->busy())
+ QTimer::singleShot( 100, this, SLOT( waiting() ) );
+ else {
+ QTimer::singleShot( 0, app, slot );
+ deleteLater();
+ }
+}
+
+TestApp::TestApp()
+{
+ m_all = new QVBox( this );
+ m_stack = new QWidgetStack( m_all );
+
+ m_stack->addWidget( m_loading = new QLabel( i18n( "Loading, please wait..." ), m_stack ) );
+ m_loading->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+
+ m_buttons = new QHBox( m_all );
+ QLabel *space = new QLabel( m_buttons ); // spacing
+ m_next = new KPushButton( i18n( "Next" ), m_buttons );
+ m_quit = new KPushButton( i18n( "Quit" ), m_buttons );
+ m_next->setEnabled( false );
+ m_quit->setEnabled( false );
+
+ m_buttons->setSpacing( 2 );
+ m_buttons->setMargin( 2 );
+ QSizePolicy buttons( QSizePolicy::Preferred, QSizePolicy::Fixed, false );
+ m_buttons->setSizePolicy( buttons );
+ m_next->setSizePolicy( buttons );
+ m_quit->setSizePolicy( buttons );
+ space->setSizePolicy( QSizePolicy(
+ QSizePolicy::Expanding,
+ QSizePolicy::Fixed, false ) );
+
+ setStandardToolBarMenuEnabled( false );
+ createStandardStatusBarAction();
+ setupActions();
+ setupGUI( Keys|StatusBar|Save|Create );
+ delete toolBar();
+
+ Application::setStatusBar( statusBar() );
+
+ QTimer::singleShot(
+ 0, this,
+ SLOT( delayed() ) );
+
+ setCentralWidget( m_all );
+ setMinimumSize( 400, 300 );
+}
+
+void TestApp::delayed()
+{
+ initialize();
+ observeComponent< component::State >();
+
+ m_stack->addWidget( m_list = new adept::Browser( m_stack ) );
+ m_stack->addWidget( m_bye = new QLabel( i18n( "Update Complete" ),
+ m_stack ) );
+ m_stack->addWidget( m_start = new QLabel( i18n( "Welcome to Adept Updater" ),
+ m_stack ) );
+ m_bye->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ m_start->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+
+ m_list->searchView()->setUpgradeMode();
+
+ m_stack->addWidget( m_progress = new adept::AcqProgressWidget( m_stack ) );
+ m_stack->addWidget( m_commitProgress = new CommitProgress( m_stack ) );
+
+ m_stack->raiseWidget( m_start );
+
+ statusBar()->clear();
+ notifyPostChange(0);
+ start();
+}
+
+void TestApp::setupActions()
+{
+ KStdAction::quit( kapp, SLOT( quit() ), actionCollection() );
+ m_undo = KStdAction::undo( this, SLOT( undo() ), actionCollection() );
+ m_redo = KStdAction::redo( this, SLOT( redo() ), actionCollection() );
+ setHistoryEnabled( false );
+ createStandardStatusBarAction();
+}
+
+void TestApp::setHistoryEnabled( bool e ) {
+ if (e && history() ) {
+ m_undo->setEnabled( history()->canUndo() );
+ m_redo->setEnabled( history()->canRedo() );
+ } else {
+ m_undo->setEnabled( false );
+ m_redo->setEnabled( false );
+ }
+}
+
+void TestApp::notifyPreChange( component::Base *b )
+{
+ Application::notifyPreChange( b );
+ checkpoint();
+}
+
+void TestApp::notifyPostChange( component::Base *b )
+{
+ Application::notifyPostChange( b );
+ m_list->searchView()->lister()->scheduleRebuild(); // rebuild on change...
+}
+
+void TestApp::setNext( QString s, const char *slot, QString q, const char *quits ) {
+ disconnect( m_next, SIGNAL( clicked() ), 0, 0 );
+ m_next->setText( s );
+ m_next->setEnabled( slot );
+ if ( slot )
+ connect( m_next, SIGNAL( clicked() ), this, slot );
+
+ disconnect( m_quit, SIGNAL( clicked() ), 0, 0 );
+ m_quit->setEnabled( quits );
+ m_quit->setText( q );
+ if ( quits )
+ connect( m_quit, SIGNAL( clicked() ), this, quits );
+}
+
+void TestApp::disableNext() {
+ setNext( i18n( "Next" ), 0 );
+}
+
+void TestApp::disableButtons() {
+ disableNext();
+ m_quit->setEnabled( false );
+}
+
+void TestApp::start() {
+// disableNext();
+ update();
+// setNext( i18n( "Fetch List of Updates" ), SLOT( update() ),
+// i18n( "Skip Fetching List" ), SLOT( postUpdate() ) );
+}
+
+void TestApp::update() {
+ kdDebug() << "TestApp::update" << endl;
+ disableButtons();
+
+ aptFront::Manager m;
+ m.setProgressCallback( m_progress->callback() );
+ m.setUpdateInterval( 100000 );
+ kdDebug() << "manager set up" << endl;
+ try {
+ m_stack->raiseWidget( m_progress );
+ m.update();
+ } catch ( exception::OperationCancelled ) {
+ } catch ( ... ) {
+ KMessageBox::sorry(
+ this, i18n( "There was an error downloading updates. " ),
+ i18n( "Could not fetch updates" ) );
+ }
+ postUpdate();
+}
+
+void TestApp::postUpdate() {
+ cache::Global::get().state().distUpgrade();
+ if ( cache::Global::get().state().upgradableCount() > 0 ) {
+ m_list->searchView()->lister()->scheduleRebuild();
+ m_stack->raiseWidget( m_list );
+ setHistoryEnabled( true );
+ setNext( i18n( "Apply Updates" ), SLOT( commit() ) );
+ } else {
+ m_bye->setText( i18n( "Nothing to Update" ) );
+ m_stack->raiseWidget( m_bye );
+ disableNext();
+ // setNext( i18n( "Nothing to do, Quit" ), SLOT( close() ) );
+ m_quit->setText( i18n( "Quit" ) );
+ m_quit->setEnabled( true );
+#ifdef KUBUNTU
+ wizard = new UpgradeWizard(this, 0, 1);
+ if( wizard->checkForDistUpgrade() ) {
+ m_bye->setText(i18n("A new distribution version is available! Click next if you wish to upgrade now.")); //FIXME improve text
+ setNext( i18n( "Version Upgrade" ), SLOT( releaseUpgrade() ) );
+ } else {
+ wizard->close();
+ }
+#endif
+ }
+}
+
+void TestApp::commit() {
+ kdDebug() << "TestApp::commit" << endl;
+ disableButtons();
+ setHistoryEnabled( false );
+ if (m_list->searchView()->lister()->busy()) {
+ new WaitForLister( this, SLOT( commit() ) );
+ return;
+ }
+
+ aptFront::Manager m;
+ m.setProgressCallback( m_progress->callback() );
+ m.setUpdateInterval( 100000 );
+ try {
+ m_stack->raiseWidget( m_progress );
+ m.download();
+ m_stack->raiseWidget( m_commitProgress );
+ m.commit();
+ } catch ( exception::OperationCancelled ) {
+ } catch ( ... ) {
+ KMessageBox::sorry(
+ this, i18n( "There was an error commiting changes. "
+ "Possibly there was a problem downloading some "
+ "packages or the commit would break packages. " ),
+ i18n( "Could not commit changes" ) );
+ }
+
+ m_stack->raiseWidget( m_bye );
+ disableNext();
+#ifdef KUBUNTU
+ wizard = new UpgradeWizard(this, 0, 1);
+ if( wizard->checkForDistUpgrade() ) {
+ m_bye->setText(i18n("A new distribution version is available! Click next if you wish to upgrade now.")); //FIXME improve text
+ setNext( i18n( "Version Upgrade" ), SLOT( releaseUpgrade() ) );
+ } else {
+ wizard->close();
+ }
+#endif
+ m_quit->setText( i18n( "Quit" ) );
+ m_quit->setEnabled( true );
+ notifyPostChange( 0 );
+}
+
+#ifdef KUBUNTU
+void TestApp::releaseUpgrade() {
+ wizard->show();
+}
+#endif
+
+#include "app.moc"
diff --git a/adept/updater/app.h b/adept/updater/app.h
new file mode 100644
index 0000000..a51986c
--- /dev/null
+++ b/adept/updater/app.h
@@ -0,0 +1,105 @@
+/* -*- C++ -*- */
+#ifndef TESTUI_APP_H
+#define TESTUI_APP_H
+
+#define KUBUNTU
+
+#include <kmainwindow.h>
+#include <kparts/part.h>
+#include <kactionclasses.h>
+#include <apt-front/cache/observer.h>
+#include <apt-front/cache/component/state.h>
+#include <apt-front/cache/component/history.h>
+#include <adept/view.h>
+#include <adept/commitprogress.h>
+#include <adept/application.h>
+
+#ifdef KUBUNTU
+#include <kubuntu_upgrader/upgradewizard.h>
+#endif
+
+class QVBox;
+class QWidgetStack;
+class QSplitter;
+class KAction;
+class KPushButton;
+namespace adept {
+class AcqProgressWidget;
+}
+
+using namespace aptFront;
+using namespace adept;
+
+class TestApp : public KMainWindow, Application {
+ Q_OBJECT
+public:
+ void setupActions();
+ ExtTerminalInterface *terminal();
+ TestApp();
+protected slots:
+ void start();
+ void update();
+ void postUpdate();
+ void commit();
+
+ void delayed();
+
+ void undo() { Application::undo(); }
+ void redo() { Application::redo(); }
+ void checkpoint() { Application::checkpoint(); }
+
+ void setHistoryEnabled( bool );
+
+ void disableNext();
+ void disableButtons();
+ void setNext( QString str, const char *slot,
+ QString qstr = i18n( "Forget Changes and Quit" ),
+ const char *qslot = SLOT( close() ) );
+#ifdef KUBUNTU
+ void releaseUpgrade();
+#endif
+protected:
+ friend class WaitForLister;
+
+ virtual void notifyPostChange( cache::component::Base * );
+ virtual void notifyPreChange( cache::component::Base * );
+
+ QWidgetStack *m_stack;
+ QVBox *m_all;
+ QHBox *m_buttons;
+ QLabel *m_start, *m_bye, *m_loading;
+ KPushButton *m_next, *m_quit;
+
+ // stacked widgets
+ adept::AcqProgressWidget *m_progress;
+ adept::CommitProgress *m_commitProgress;
+ adept::Browser *m_list;
+
+ // other stuff
+ std::vector<KAction *> m_actions;
+ QMap< QString, QString > m_icons;
+ KAction *m_undo, *m_redo;
+ cache::component::History< cache::component::State > *m_history;
+
+#ifdef KUBUNTU
+ UpgradeWizard* wizard;
+#endif
+};
+
+class WaitForLister : public QObject {
+ Q_OBJECT
+public:
+ WaitForLister( TestApp *a, const char *s )
+ : app( a ), slot( s )
+ {
+ waiting();
+ }
+protected slots:
+ void waiting();
+protected:
+ TestApp *app;
+ const char *slot;
+
+};
+
+#endif
diff --git a/adept/updater/hi128-app-adept_updater.png b/adept/updater/hi128-app-adept_updater.png
new file mode 100644
index 0000000..a68965f
--- /dev/null
+++ b/adept/updater/hi128-app-adept_updater.png
Binary files differ
diff --git a/adept/updater/hi16-app-adept_updater.png b/adept/updater/hi16-app-adept_updater.png
new file mode 100644
index 0000000..4952024
--- /dev/null
+++ b/adept/updater/hi16-app-adept_updater.png
Binary files differ
diff --git a/adept/updater/hi22-app-adept_updater.png b/adept/updater/hi22-app-adept_updater.png
new file mode 100644
index 0000000..3b3880c
--- /dev/null
+++ b/adept/updater/hi22-app-adept_updater.png
Binary files differ
diff --git a/adept/updater/hi32-app-adept_updater.png b/adept/updater/hi32-app-adept_updater.png
new file mode 100644
index 0000000..ee196a8
--- /dev/null
+++ b/adept/updater/hi32-app-adept_updater.png
Binary files differ
diff --git a/adept/updater/hi48-app-adept_updater.png b/adept/updater/hi48-app-adept_updater.png
new file mode 100644
index 0000000..5abac9b
--- /dev/null
+++ b/adept/updater/hi48-app-adept_updater.png
Binary files differ
diff --git a/adept/updater/hi64-app-adept_updater.png b/adept/updater/hi64-app-adept_updater.png
new file mode 100644
index 0000000..20766d9
--- /dev/null
+++ b/adept/updater/hi64-app-adept_updater.png
Binary files differ
diff --git a/adept/updater/hisc-app-adept_updater.svgz b/adept/updater/hisc-app-adept_updater.svgz
new file mode 100644
index 0000000..2c6fab6
--- /dev/null
+++ b/adept/updater/hisc-app-adept_updater.svgz
Binary files differ
diff --git a/adept/updater/main.cpp b/adept/updater/main.cpp
new file mode 100644
index 0000000..a86ee9b
--- /dev/null
+++ b/adept/updater/main.cpp
@@ -0,0 +1,56 @@
+// KDE includes
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kuniqueapplication.h>
+
+#include "app.h"
+
+static KCmdLineOptions options[] =
+{
+ KCmdLineLastOption
+};
+
+int main(int argc, char *argv[])
+{
+
+ KLocale::setMainCatalogue("adept_updater");
+
+ putenv( "QT_IM_MODULE=xim" );
+ QString description = i18n("Adept Updater");
+
+ KAboutData aboutData( "adept_updater",
+ I18N_NOOP("Adept Updater"),
+ "2.1 Cruiser",
+ description.latin1(),
+ KAboutData::License_BSD,
+ I18N_NOOP("(c) 2005, 2006 Peter Rockai"),
+ 0,
+ "http://web.mornfall.net/adept.html");
+
+ aboutData.addAuthor ( "Peter Rockai",
+ I18N_NOOP("developer"),
+ "me at mornfall dot net",
+ "http://web.mornfall.net");
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+ // if (args && args->isSet("xy")) ...
+
+ /* KConfig* config = KGlobal::config();
+ config->setGroup("General Settings");
+ QString version = config->readEntry("Version"); */
+
+ KGlobal::locale()->insertCatalogue(QString::fromUtf8("libept"));
+
+ TestApp *ta = new TestApp();
+
+ app.setMainWidget(ta);
+ ta->show();
+
+ return app.exec();
+}