summaryrefslogtreecommitdiffstats
path: root/kicker/kicker
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit4aed2c8219774f5d797760606b8489a92ddc5163 (patch)
tree3f8c130f7d269626bf6a9447407ef6c35954426a /kicker/kicker
downloadtdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz
tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kicker/kicker')
-rw-r--r--kicker/kicker/Makefile.am40
-rw-r--r--kicker/kicker/buttons/Makefile.am24
-rw-r--r--kicker/kicker/buttons/bookmarks.desktop133
-rw-r--r--kicker/kicker/buttons/bookmarksbutton.cpp72
-rw-r--r--kicker/kicker/buttons/bookmarksbutton.h58
-rw-r--r--kicker/kicker/buttons/browser.desktop125
-rw-r--r--kicker/kicker/buttons/browserbutton.cpp147
-rw-r--r--kicker/kicker/buttons/browserbutton.h66
-rw-r--r--kicker/kicker/buttons/desktop.desktop129
-rw-r--r--kicker/kicker/buttons/desktopbutton.cpp84
-rw-r--r--kicker/kicker/buttons/desktopbutton.h49
-rw-r--r--kicker/kicker/buttons/exec.desktop125
-rw-r--r--kicker/kicker/buttons/extensionbutton.cpp79
-rw-r--r--kicker/kicker/buttons/extensionbutton.h52
-rw-r--r--kicker/kicker/buttons/kbutton.cpp78
-rw-r--r--kicker/kicker/buttons/kbutton.h50
-rw-r--r--kicker/kicker/buttons/kmenu.desktop132
-rw-r--r--kicker/kicker/buttons/nonkdeappbutton.cpp287
-rw-r--r--kicker/kicker/buttons/nonkdeappbutton.h92
-rw-r--r--kicker/kicker/buttons/servicebutton.cpp262
-rw-r--r--kicker/kicker/buttons/servicebutton.h66
-rw-r--r--kicker/kicker/buttons/servicemenubutton.cpp96
-rw-r--r--kicker/kicker/buttons/servicemenubutton.h54
-rw-r--r--kicker/kicker/buttons/urlbutton.cpp201
-rw-r--r--kicker/kicker/buttons/urlbutton.h65
-rw-r--r--kicker/kicker/buttons/windowlist.desktop130
-rw-r--r--kicker/kicker/buttons/windowlistbutton.cpp47
-rw-r--r--kicker/kicker/buttons/windowlistbutton.h48
-rw-r--r--kicker/kicker/core/Makefile.am33
-rw-r--r--kicker/kicker/core/applethandle.cpp402
-rw-r--r--kicker/kicker/core/applethandle.h126
-rw-r--r--kicker/kicker/core/childpanelextension.desktop145
-rw-r--r--kicker/kicker/core/container_applet.cpp478
-rw-r--r--kicker/kicker/core/container_applet.h113
-rw-r--r--kicker/kicker/core/container_base.cpp139
-rw-r--r--kicker/kicker/core/container_base.h134
-rw-r--r--kicker/kicker/core/container_button.cpp542
-rw-r--r--kicker/kicker/core/container_button.h195
-rw-r--r--kicker/kicker/core/container_extension.cpp2067
-rw-r--r--kicker/kicker/core/container_extension.h215
-rw-r--r--kicker/kicker/core/containerarea.cpp1939
-rw-r--r--kicker/kicker/core/containerarea.h195
-rw-r--r--kicker/kicker/core/containerarealayout.cpp803
-rw-r--r--kicker/kicker/core/containerarealayout.h120
-rw-r--r--kicker/kicker/core/default-apps2
-rw-r--r--kicker/kicker/core/extensionSettings.kcfg114
-rw-r--r--kicker/kicker/core/extensionSettings.kcfgc5
-rw-r--r--kicker/kicker/core/extensionmanager.cpp773
-rw-r--r--kicker/kicker/core/extensionmanager.h92
-rw-r--r--kicker/kicker/core/kicker.cpp401
-rw-r--r--kicker/kicker/core/kicker.h131
-rw-r--r--kicker/kicker/core/kickerbindings.cpp50
-rw-r--r--kicker/kicker/core/main.cpp154
-rw-r--r--kicker/kicker/core/menumanager.cpp272
-rw-r--r--kicker/kicker/core/menumanager.h81
-rw-r--r--kicker/kicker/core/panelextension.cpp445
-rw-r--r--kicker/kicker/core/panelextension.h126
-rw-r--r--kicker/kicker/core/pluginmanager.cpp378
-rw-r--r--kicker/kicker/core/pluginmanager.h106
-rw-r--r--kicker/kicker/core/showdesktop.cpp198
-rw-r--r--kicker/kicker/core/showdesktop.h64
-rw-r--r--kicker/kicker/core/unhidetrigger.cpp137
-rw-r--r--kicker/kicker/core/unhidetrigger.h62
-rw-r--r--kicker/kicker/core/userrectsel.cpp147
-rw-r--r--kicker/kicker/core/userrectsel.h99
-rw-r--r--kicker/kicker/kcmkicker.desktop80
-rw-r--r--kicker/kicker/kicker-3.1-properSizeSetting.pl34
-rw-r--r--kicker/kicker/kicker-3.4-reverseLayout.cpp152
-rwxr-xr-xkicker/kicker/kicker-3.5-kconfigXTize.pl37
-rwxr-xr-xkicker/kicker/kicker-3.5-taskbarEnums.pl54
-rw-r--r--kicker/kicker/kickerrc.upd22
-rw-r--r--kicker/kicker/panel.desktop86
-rw-r--r--kicker/kicker/ui/Makefile.am41
-rw-r--r--kicker/kicker/ui/addapplet.cpp542
-rw-r--r--kicker/kicker/ui/addapplet.h82
-rw-r--r--kicker/kicker/ui/addapplet_mnu.cpp75
-rw-r--r--kicker/kicker/ui/addapplet_mnu.h50
-rw-r--r--kicker/kicker/ui/addappletvisualfeedback.cpp230
-rw-r--r--kicker/kicker/ui/addappletvisualfeedback.h80
-rw-r--r--kicker/kicker/ui/addbutton_mnu.cpp73
-rw-r--r--kicker/kicker/ui/addbutton_mnu.h51
-rw-r--r--kicker/kicker/ui/addextension_mnu.cpp58
-rw-r--r--kicker/kicker/ui/addextension_mnu.h47
-rw-r--r--kicker/kicker/ui/appletitem.ui129
-rw-r--r--kicker/kicker/ui/appletop_mnu.cpp208
-rw-r--r--kicker/kicker/ui/appletop_mnu.h55
-rw-r--r--kicker/kicker/ui/appletview.ui204
-rw-r--r--kicker/kicker/ui/appletwidget.h72
-rw-r--r--kicker/kicker/ui/browser_dlg.cpp114
-rw-r--r--kicker/kicker/ui/browser_dlg.h53
-rw-r--r--kicker/kicker/ui/browser_mnu.cpp552
-rw-r--r--kicker/kicker/ui/browser_mnu.h81
-rw-r--r--kicker/kicker/ui/client_mnu.cpp139
-rw-r--r--kicker/kicker/ui/client_mnu.h81
-rw-r--r--kicker/kicker/ui/dirdrop_mnu.cpp39
-rw-r--r--kicker/kicker/ui/dirdrop_mnu.h37
-rw-r--r--kicker/kicker/ui/exe_dlg.cpp204
-rw-r--r--kicker/kicker/ui/exe_dlg.h65
-rw-r--r--kicker/kicker/ui/extensionop_mnu.cpp66
-rw-r--r--kicker/kicker/ui/extensionop_mnu.h36
-rw-r--r--kicker/kicker/ui/hidebutton.cpp202
-rw-r--r--kicker/kicker/ui/hidebutton.h56
-rw-r--r--kicker/kicker/ui/k_mnu.cpp739
-rw-r--r--kicker/kicker/ui/k_mnu.h106
-rw-r--r--kicker/kicker/ui/nonKDEButtonSettings.ui221
-rw-r--r--kicker/kicker/ui/panelmenuiteminfo.h103
-rw-r--r--kicker/kicker/ui/popupmenutitle.cpp33
-rw-r--r--kicker/kicker/ui/popupmenutitle.h85
-rw-r--r--kicker/kicker/ui/quickbrowser_mnu.cpp60
-rw-r--r--kicker/kicker/ui/quickbrowser_mnu.h43
-rw-r--r--kicker/kicker/ui/recentapps.cpp172
-rw-r--r--kicker/kicker/ui/recentapps.h99
-rw-r--r--kicker/kicker/ui/removeapplet_mnu.cpp99
-rw-r--r--kicker/kicker/ui/removeapplet_mnu.h52
-rw-r--r--kicker/kicker/ui/removebutton_mnu.cpp111
-rw-r--r--kicker/kicker/ui/removebutton_mnu.h55
-rw-r--r--kicker/kicker/ui/removecontainer_mnu.cpp61
-rw-r--r--kicker/kicker/ui/removecontainer_mnu.h47
-rw-r--r--kicker/kicker/ui/removeextension_mnu.cpp108
-rw-r--r--kicker/kicker/ui/removeextension_mnu.h48
-rw-r--r--kicker/kicker/ui/service_mnu.cpp823
-rw-r--r--kicker/kicker/ui/service_mnu.h129
122 files changed, 21655 insertions, 0 deletions
diff --git a/kicker/kicker/Makefile.am b/kicker/kicker/Makefile.am
new file mode 100644
index 000000000..857ac9cff
--- /dev/null
+++ b/kicker/kicker/Makefile.am
@@ -0,0 +1,40 @@
+INCLUDES = $(all_includes)
+
+SUBDIRS = core ui buttons .
+
+bin_PROGRAMS =
+lib_LTLIBRARIES =
+kdeinit_LTLIBRARIES = kicker.la
+
+CLEANFILES = dummy.cpp
+
+kicker_la_LIBADD = core/libkicker_core.la buttons/libkicker_buttons.la \
+ ui/libkicker_ui.la ../libkicker/libkickermain.la $(LIB_KIO) $(LIB_KUTILS)
+
+kicker_la_SOURCES = dummy.cpp
+kicker_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+autostart_DATA = panel.desktop
+autostartdir = $(datadir)/autostart
+
+xdg_apps_DATA = kcmkicker.desktop
+
+messages: rc.cpp
+ $(EXTRACTRC) ui/*ui >> rc.cpp
+ $(EXTRACTRC) core/*.kcfg >> rc.cpp
+ $(XGETTEXT) buttons/*.cpp core/*.cpp ui/*.cpp *.cpp -o $(podir)/kicker.pot
+
+dummy.cpp:
+ echo > $@
+
+kconf_PROGRAMS = kicker-3.4-reverseLayout
+kconfdir = $(libdir)/kconf_update_bin
+
+kicker_3_4_reverseLayout_SOURCES = kicker-3.4-reverseLayout.cpp
+kicker_3_4_reverseLayout_LDADD = $(LIB_QT) $(LIB_KDECORE)
+kicker_3_4_reverseLayout_LDFLAGS = $(all_libraries)
+
+updatedir = $(kde_datadir)/kconf_update
+update_DATA = kickerrc.upd
+update_SCRIPTS = kicker-3.1-properSizeSetting.pl kicker-3.5-taskbarEnums.pl kicker-3.5-kconfigXTize.pl
+
diff --git a/kicker/kicker/buttons/Makefile.am b/kicker/kicker/buttons/Makefile.am
new file mode 100644
index 000000000..2ba4d20c6
--- /dev/null
+++ b/kicker/kicker/buttons/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = -I$(srcdir)/../core -I$(srcdir)/../../libkicker -I../../libkicker \
+ -I$(srcdir)/../ui -I$(top_srcdir)/libkonq $(all_includes)
+
+noinst_LTLIBRARIES = libkicker_buttons.la
+
+libkicker_buttons_la_SOURCES = servicebutton.cpp bookmarksbutton.cpp \
+ browserbutton.cpp \
+ desktopbutton.cpp extensionbutton.cpp kbutton.cpp \
+ nonkdeappbutton.cpp servicemenubutton.cpp urlbutton.cpp \
+ windowlistbutton.cpp
+
+libkicker_buttons_la_LDFLAGS = $(all_libraries)
+libkicker_buttons_la_LIBADD = $(top_builddir)/libkonq/libkonq.la $(LIB_KDEUI) $(XTESTLIB)
+libkicker_buttons_la_METASOURCES = AUTO
+
+desktopmenu_DATA = bookmarks.desktop browser.desktop desktop.desktop \
+ exec.desktop kmenu.desktop windowlist.desktop
+desktopmenudir = $(kde_datadir)/kicker/builtins
+
+browserbutton.lo: ../../libkicker/kickerSettings.h
+desktopbutton.lo: ../../libkicker/kickerSettings.h
+panelbutton.lo: ../../libkicker/kickerSettings.h
+servicebutton.lo: ../../libkicker/kickerSettings.h
+urlbutton.lo: ../../libkicker/kickerSettings.h
diff --git a/kicker/kicker/buttons/bookmarks.desktop b/kicker/kicker/buttons/bookmarks.desktop
new file mode 100644
index 000000000..2957099d1
--- /dev/null
+++ b/kicker/kicker/buttons/bookmarks.desktop
@@ -0,0 +1,133 @@
+[Desktop Entry]
+Name=Bookmarks Menu
+Name[af]=Boekmerke Kieslys
+Name[ar]=قائمة علامات مواقع
+Name[be]=Меню закладак
+Name[bg]=Отметки
+Name[bn]=বুকমার্ক মেনু
+Name[br]=Meuziad ar sinedoù
+Name[bs]=Meni zabilješki
+Name[ca]=Menú de punts
+Name[cs]=Nabídka záložek
+Name[csb]=Załóżczi
+Name[da]=Bogmærkemenu
+Name[de]=Lesezeichen
+Name[el]=Μενού σελιδοδεικτών
+Name[eo]=Legosigna Menuo
+Name[es]=Marcadores
+Name[et]=Järjehoidjate menüü
+Name[eu]=Laster-marken menua
+Name[fa]=گزینگان چوب الفها
+Name[fi]=Kirjanmerkit
+Name[fr]=Menu des signets
+Name[fy]=Blêdwizers menu
+Name[ga]=Roghchlár na Leabharmharcanna
+Name[gl]=Marcadores
+Name[he]=תפריט סימניות
+Name[hr]=Izbornik oznaka
+Name[hu]=Könyvjelzők menü
+Name[is]=Bókamerkjavalmynd
+Name[it]=Menu dei segnalibri
+Name[ja]=ブックマークメニュー
+Name[ka]=სანიშნეების მენიუ
+Name[kk]=Бетбелгілер мәзірі
+Name[km]=ម៉ឺនុយ​ចំណាំ
+Name[ko]=책갈피
+Name[lt]=Žymelių meniu
+Name[mk]=Мени со обележувачи
+Name[nb]=Bokmerkemeny
+Name[nds]=Leestekens
+Name[ne]=पुस्तकचिनो मेनु
+Name[nl]=Bladwijzermenu
+Name[nn]=Bokmerkemeny
+Name[pa]=ਬੁੱਕਮਾਰਕ ਮੇਨੂ
+Name[pl]=Zakładki
+Name[pt]=Menu de Favoritos
+Name[pt_BR]=Menu favoritos
+Name[ro]=Meniu semne de carte
+Name[ru]=Закладки
+Name[rw]=Ibikubiyemo by'Utumenyetso
+Name[se]=Girjemearkafállu
+Name[sk]=Menu záložiek
+Name[sl]=Meni z zaznamki
+Name[sr]=Мени маркера
+Name[sr@Latn]=Meni markera
+Name[sv]=Bokmärkesmeny
+Name[te]=పేజి గుర్తుల పట్టి
+Name[tg]=Менюи хатчӯбҳо
+Name[th]=ที่คั่นหน้า
+Name[tr]=Yer imleri Menüsü
+Name[tt]=Bitbilge Saylağı
+Name[uk]=Меню закладок
+Name[uz]=Xatchoʻplar menyusi
+Name[uz@cyrillic]=Хатчўплар менюси
+Name[vi]=Thực đơn có Sổ lưu liên kết
+Name[wa]=Dressêye des rmåkes
+Name[zh_CN]=书签菜单
+Name[zh_TW]=書籤選單
+Comment=Your Konqueror bookmarks
+Comment[af]=Jou Konqueror boekmerke
+Comment[ar]=علامات مواقعك لِــ Konqueror
+Comment[be]=Закладкі Konqueror
+Comment[bg]=Отметки на браузъра
+Comment[bn]=আপনার কনকরার বুকমার্ক-সমূহ
+Comment[bs]=Vaše Konqueror zabilješke
+Comment[ca]=Els vostres punts Konqueror
+Comment[cs]=Vaše záložky Konqueroru
+Comment[csb]=Załóżczi Konquerora
+Comment[da]=Dine Konqueror bogmærker
+Comment[de]=Ein Menü mit Ihren Konqueror-Lesezeichen
+Comment[el]=Οι σελιδοδείκτες σας του Konqueror
+Comment[eo]=Viaj Konkeranto-legosignoj
+Comment[es]=Sus marcadores de Konqueror
+Comment[et]=Konquerori järjehoidjad
+Comment[eu]=Zure Konquerorren laster-markak
+Comment[fa]=چوب ‌الفهای Konqueror شما
+Comment[fi]=Konquerorin kirjanmerkit
+Comment[fr]=Vos signets Konqueror
+Comment[fy]=Jo blêdwizers yn Konqueror
+Comment[ga]=Do Chuid Leabharmharcanna Konqueror
+Comment[gl]=Os seus marcadores de Konqueror
+Comment[he]=הסימניות Konqueror שלך
+Comment[hr]=Vaše Konqueror oznake
+Comment[hu]=A Konqueror könyvjelzői
+Comment[is]=Konqueror bókamerkin þín
+Comment[it]=I tuoi segnalibri di Konqueror
+Comment[ja]=Konqueror ブックマーク
+Comment[ka]=Konqueror-ის თქვენი სანიშნეები
+Comment[kk]=Konqueror шолғыштың бетбелгілері
+Comment[km]=ចំណាំ Konqueror របស់​អ្នក
+Comment[lt]=Konqueror žymelės
+Comment[mk]=Вашите обележувачи од Konqueror
+Comment[nb]=Dine bokmerker i Konqueror
+Comment[nds]=Menü mit Dien Konqueror-Leestekens
+Comment[ne]=तपाईँको कन्क्वेररका पुस्तकचिनो
+Comment[nl]=Uw bladwijzers in Konqueror
+Comment[nn]=Konqueror-bokmerka
+Comment[pa]=ਤੁਹਾਡੇ ਕੋਨਕਿਉਰੋਰ ਬੁੱਕਮਾਰਕ
+Comment[pl]=Zakładki Konquerora
+Comment[pt]=Os seus favoritos do Konqueror
+Comment[pt_BR]=Seus favoritos do Konqueror
+Comment[ro]=Semnele de carte Konqueror
+Comment[ru]=Закладки Konqueror
+Comment[rw]=Ibimenyetso bya Konqueror yawe
+Comment[se]=Konqueror:a girjemearkkat
+Comment[sk]=Konqueror záložky
+Comment[sl]=Meni z zaznamki iz Konquerorja
+Comment[sr]=Ваши маркери у Konqueror-у
+Comment[sr@Latn]=Vaši markeri u Konqueror-u
+Comment[sv]=Dina bokmärken i Konqueror
+Comment[te]=మీ కాంకెరర్ పేజి గుర్తులు
+Comment[tg]=Хатчӯбҳои Konqueror
+Comment[th]=ที่คั่นหน้าคอนเควอร์เรอร์ของคุณ
+Comment[tr]=Konqueror yer imleriniz
+Comment[tt]=Konqueror Bitbilgeläre
+Comment[uk]=Закладки з Konqueror
+Comment[uz]=Konqueror xatchoʻplari
+Comment[uz@cyrillic]=Konqueror хатчўплари
+Comment[vi]=Các liên kết đã lưu tại Konqueror của bạn
+Comment[wa]=Vos rmåkes Konqueror
+Comment[zh_CN]=您的 Konqueror 书签
+Comment[zh_TW]=您的 Konqueror 書籤
+Icon=bookmark
+X-KDE-Library=BookmarksButton
diff --git a/kicker/kicker/buttons/bookmarksbutton.cpp b/kicker/kicker/buttons/bookmarksbutton.cpp
new file mode 100644
index 000000000..b351af263
--- /dev/null
+++ b/kicker/kicker/buttons/bookmarksbutton.cpp
@@ -0,0 +1,72 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+
+#include <kaction.h>
+#include <kbookmark.h>
+#include <kbookmarkmenu.h>
+#include <konqbookmarkmanager.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+
+#include "bookmarksbutton.h"
+#include "bookmarksbutton.moc"
+
+BookmarksButton::BookmarksButton(QWidget* parent)
+ : PanelPopupButton(parent, "BookmarksButton"),
+ bookmarkParent(0),
+ bookmarkMenu(0),
+ actionCollection(0),
+ bookmarkOwner(0)
+{
+ actionCollection = new KActionCollection( this );
+ bookmarkParent = new KPopupMenu(this, "bookmarks");
+ bookmarkOwner = new KBookmarkOwner;
+ bookmarkMenu = new KBookmarkMenu(KonqBookmarkManager::self(),
+ bookmarkOwner,
+ bookmarkParent,
+ actionCollection,
+ true, false);
+ setPopup(bookmarkParent);
+ QToolTip::add(this, i18n("Bookmarks"));
+ setTitle(i18n("Bookmarks"));
+ setIcon("bookmark");
+}
+
+BookmarksButton::~BookmarksButton()
+{
+ delete bookmarkMenu;
+ delete bookmarkOwner;
+}
+
+void BookmarksButton::initPopup()
+{
+ bookmarkMenu->ensureUpToDate();
+}
+
+void BookmarksButton::properties()
+{
+ KonqBookmarkManager::self()->slotEditBookmarks();
+}
+
diff --git a/kicker/kicker/buttons/bookmarksbutton.h b/kicker/kicker/buttons/bookmarksbutton.h
new file mode 100644
index 000000000..95ffa9609
--- /dev/null
+++ b/kicker/kicker/buttons/bookmarksbutton.h
@@ -0,0 +1,58 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __bookmarksbutton_h__
+#define __bookmarksbutton_h__
+
+#include "panelbutton.h"
+
+class KPopupMenu;
+class KBookmarkMenu;
+class KActionCollection;
+class KBookmarkOwner;
+
+/**
+ * Button that contains a bookmark menu
+ */
+class BookmarksButton : public PanelPopupButton
+{
+ Q_OBJECT
+
+public:
+ BookmarksButton(QWidget* parent);
+ ~BookmarksButton();
+
+ void loadConfig(const KConfigGroup& config);
+ virtual void properties();
+
+protected:
+ virtual QString tileName() { return "WindowList"; }
+ virtual void initPopup();
+
+ KPopupMenu* bookmarkParent;
+ KBookmarkMenu* bookmarkMenu;
+ KActionCollection* actionCollection;
+ KBookmarkOwner* bookmarkOwner;
+};
+
+#endif
diff --git a/kicker/kicker/buttons/browser.desktop b/kicker/kicker/buttons/browser.desktop
new file mode 100644
index 000000000..f7236786b
--- /dev/null
+++ b/kicker/kicker/buttons/browser.desktop
@@ -0,0 +1,125 @@
+[Desktop Entry]
+Name=Quick File Browser
+Name[af]=Vinnige Lêer Blaaier
+Name[ar]=متصفح ملفات سريع
+Name[be]=Хуткі прагляд
+Name[bg]=Бърз файлов браузър
+Name[bn]=চটপট ফাইল ব্রাউজার
+Name[bs]=Brzi preglednik datoteka
+Name[ca]=Fullejador de fitxers ràpid
+Name[cs]=Rychlý prohlížeč souborů
+Name[csb]=Chùtczé przezéranié lopków
+Name[da]=Hurtig filsøgning
+Name[de]=Schnellanzeiger
+Name[el]=Γρήγορος περιηγητής αρχείων
+Name[eo]=Rapida Dosiero Legilo
+Name[es]=Navegador rápido de archivos
+Name[et]=Failide kiirbrauser
+Name[eu]=Fitxategi arakatzaile bizkorra
+Name[fa]=مرورگر پروندۀ سریع
+Name[fi]=Nopea tiedostoselain
+Name[fr]=Explorateur de fichiers rapide
+Name[fy]=Flugge triem blêder
+Name[gl]=Navegador Rápido
+Name[he]=דפדפן קבצים מהיר
+Name[hr]=Brzi pretraživač datoteka
+Name[hu]=Gyors fájlböngésző
+Name[is]=Flýti skráarvafri
+Name[it]=Browser rapido dei file
+Name[ja]=クイックファイルブラウザ
+Name[ka]=ფაილების სწრაფი ნუსხა
+Name[kk]=Жедел файл шолғышы
+Name[km]=កម្មវិធី​រុករកឯកសារ​រហ័ស
+Name[lt]=Paprasta bylų naršyklė
+Name[mk]=Брз прелистувач на датотеки
+Name[nb]=Enkel filbehandler
+Name[nds]=Fix-Dateiwieser
+Name[ne]=द्रुत फाइल ब्राउजर
+Name[nn]=Snøgglesar
+Name[pa]=ਤੇਜ਼ ਫਾਇਲ ਝਲਕਾਰਾ
+Name[pl]=Szybkie przeglądanie plików
+Name[pt]=Navegação Rápida de Ficheiros
+Name[pt_BR]=Navegador de Arquivos Rápido
+Name[ro]=Navigator de fișiere rapid
+Name[ru]=Быстрый выбор файла
+Name[rw]=Mucukumbuzi y'Idosiye Yihuta
+Name[se]=Jođánis fiilagieđahalli
+Name[sk]=Rýchly prehliadač súborov
+Name[sl]=Preprost brskalnik
+Name[sr]=Брзи прегледач фајлова
+Name[sr@Latn]=Brzi pregledač fajlova
+Name[sv]=Snabbfilbläddrare
+Name[tg]=Интихоби файлҳои тез
+Name[th]=โปรแกรมเรียกดูไฟล์อย่างรวดเร็ว
+Name[tr]=Hızlı Dosya Tarayıcı
+Name[tt]=Tiz Birem-Küzätüçe
+Name[uk]=Швидкий навігатор файлів
+Name[uz]=Tez koʻruvchi
+Name[uz@cyrillic]=Тез кўрувчи
+Name[vi]=Duyệt nhanh các tập tin
+Name[wa]=Betchteu d' fitchî simpe
+Name[zh_CN]=快速文件浏览器
+Name[zh_TW]=快速檔案瀏覽器
+Comment=A menu that lists files in a given folder
+Comment[af]='n Kieslys wat die lêers in 'n spesifieke gids vertoon
+Comment[ar]=قائمة تعرض الملفات في مجلّد معيين
+Comment[be]=Меню, якое паказвае файлы ў вызначанай тэчцы
+Comment[bg]=Меню, което показва файловете в зададена директория
+Comment[bn]=একটি মেনু যা ফোল্ডার-এর ফাইলসমূহ তালিকাবদ্ধ করে
+Comment[bs]=Meni u kojem se nalaze datoteke u datom direktoriju
+Comment[ca]=Un menú que llista els fitxers d'una carpeta
+Comment[cs]=Nabídka vypisující soubory v dané složce
+Comment[csb]=Menu pokazëwôjące lopczi w pòdónym katalogù
+Comment[da]=En menu der lister filer i en given mappe
+Comment[de]=Ein Menü, das die Dateien eines bestimmten Ordners auflistet
+Comment[el]=Ένα μενού που εμφανίζει τα αρχεία ενός δοσμένου φακέλου
+Comment[eo]=Menuo kiu listigas dosierojn en la nomita dosierujo
+Comment[es]=Un menú que le muestra los archivos de una carpeta
+Comment[et]=Menüü, mis näitab valitud kataloogi faile
+Comment[eu]=Emandako karpetako fitxategiak zerrendatzen dituen menua
+Comment[fa]=گزینگانی که پرونده‌ها را در پوشۀ داده‌شده فهرست می‌کند
+Comment[fi]=Valikko, joka listaa annetun kansion tiedostot
+Comment[fr]=Un menu affichant les fichiers d'un dossier donné
+Comment[fy]=In menu dat de triemmen út de oantsjutte map sjen lit
+Comment[ga]=Roghchlár a thaispeánann na comhaid i bhfillteán
+Comment[gl]=Un menu que lista os ficheiros dos seus cartafoles
+Comment[he]=תפריט שנותן רשימה של קבצים הקיימים בתיקייה מסוימת
+Comment[hr]=Izbornik s popisom datoteka unutar dane mape
+Comment[hu]=Egy adott könyvtár tartalmát kilistázó menü
+Comment[is]=Valmynd sem sýnir skrár í uppgefinni möppu
+Comment[it]=Un menu che elenca i file di una data cartella
+Comment[ja]=指定したフォルダのファイルのリストを表示するメニュー
+Comment[kk]=Каталогтағы файлдар тізім мәзірі
+Comment[km]=ម៉ឺនុយ​ដែល​រាយ​ឯកសារ​ក្នុង​ថត​ដែលបាន​ផ្តល់​មួយ
+Comment[lt]=Bylų sąrašą nurodytame aplanke pateikiantis meniu
+Comment[mk]=Мени што ги листа датотеките во дадена папка
+Comment[nb]=En meny som viser filene i en bestemt mappe
+Comment[nds]=Menü dat de Dateien ut en angeven Orner wiest
+Comment[ne]=दिएको फोल्डरमा फाइलहरू सूचीकृत गर्ने मेनु
+Comment[nl]=Een menu dat de bestanden uit de opgegeven map toont
+Comment[nn]=Ein meny som viser filene i ei mappe
+Comment[pa]=ਇੱਕ ਮੇਨੂ, ਜੋ ਕਿ ਦਿੱਤੇ ਫੋਲਡਰ ਵਿੱਚ ਫਾਇਲਾਂ ਵਿਖਾ ਸਕਦਾ ਹੈ
+Comment[pl]=Menu pokazujące pliki w podanym katalogu
+Comment[pt]=Um menu que mostra os ficheiros numa dada pasta
+Comment[pt_BR]=Um menu que lista arquivos em uma determinada pasta
+Comment[ro]=Un meniu care listează fișierele dintr-un folder
+Comment[ru]=Меню с быстрым выбором файла из указанной папки
+Comment[rw]=Ibikubiyemo bitanga urutonde rw'amadosiye mu bubiko butanzwe
+Comment[se]=Fállu mii čájeha fiillaid dihto máhpas
+Comment[sk]=Menu, ktoré zobrazí súbory v priečinku
+Comment[sl]=Meni, ki prikazuje seznam datotek v dani mapi
+Comment[sr]=Мени који листа фајлове у датој фасцикли
+Comment[sr@Latn]=Meni koji lista fajlove u datoj fascikli
+Comment[sv]=En meny som listar filer i en given katalog
+Comment[th]=เมนูที่แสดงรายการแฟ้มของโฟลเดอร์ที่กำหนด
+Comment[tr]=Belirlenen bir dizinde dosyaları listeleme menüsü
+Comment[tt]=Berär törgäkneñ birem tezmäsen kürsätüçe saylaq
+Comment[uk]=Меню, яке дає перелік файлів в даній теці
+Comment[uz]=Koʻrsatilgan jilddagi fayllarning roʻyxatini koʻrsatuvchi
+Comment[uz@cyrillic]=Кўрсатилган жилддаги файлларнинг рўйхатини кўрсатувчи
+Comment[vi]=Một thực đơn liệt kê các tập tin có trong thư mục
+Comment[wa]=Ene dressêye ki fwait l' lisse des fitchî dins on ridant d' diné
+Comment[zh_CN]=列出给定文件夹中文件的菜单
+Comment[zh_TW]=列出所選資料夾中檔案的選單
+Icon=kdisknav
+X-KDE-Library=BrowserButton
diff --git a/kicker/kicker/buttons/browserbutton.cpp b/kicker/kicker/buttons/browserbutton.cpp
new file mode 100644
index 000000000..9a445d218
--- /dev/null
+++ b/kicker/kicker/buttons/browserbutton.cpp
@@ -0,0 +1,147 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <qdragobject.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <konq_operations.h>
+#include <kfileitem.h>
+
+#include "kicker.h"
+#include "browser_mnu.h"
+#include "browser_dlg.h"
+#include "global.h"
+
+#include "browserbutton.h"
+#include "browserbutton.moc"
+
+BrowserButton::BrowserButton( const QString& icon, const QString& startDir, QWidget* parent )
+ : PanelPopupButton( parent, "BrowserButton" )
+ , topMenu( 0 )
+{
+ initialize( icon, startDir );
+}
+
+BrowserButton::BrowserButton( const KConfigGroup& config, QWidget* parent )
+ : PanelPopupButton( parent, "BrowserButton" )
+ , topMenu( 0 )
+{
+ initialize( config.readEntry("Icon", "kdisknav"), config.readPathEntry("Path") );
+}
+
+BrowserButton::~BrowserButton()
+{
+ delete topMenu;
+}
+
+void BrowserButton::initialize( const QString& icon, const QString& path )
+{
+ _icon = icon;
+
+ // Don't parent to this, so that the tear of menu is not always-on-top.
+ topMenu = new PanelBrowserMenu( path );
+ setPopup(topMenu);
+
+ _menuTimer = new QTimer( this );
+ connect( _menuTimer, SIGNAL(timeout()), SLOT(slotDelayedPopup()) );
+
+ QToolTip::add(this, i18n("Browse: %1").arg(path));
+ setTitle( path );
+ setIcon ( _icon );
+}
+
+void BrowserButton::saveConfig( KConfigGroup& config ) const
+{
+ config.writeEntry("Icon", _icon);
+ config.writePathEntry("Path", topMenu->path());
+}
+
+void BrowserButton::dragEnterEvent( QDragEnterEvent *ev )
+{
+ if ((ev->source() != this) && KURLDrag::canDecode(ev))
+ {
+ _menuTimer->start(500, true);
+ ev->accept();
+ }
+ else
+ {
+ ev->ignore();
+ }
+ PanelButton::dragEnterEvent(ev);
+}
+
+void BrowserButton::dragLeaveEvent( QDragLeaveEvent *ev )
+{
+ _menuTimer->stop();
+ PanelButton::dragLeaveEvent(ev);
+}
+
+void BrowserButton::dropEvent( QDropEvent *ev )
+{
+ KURL path ( topMenu->path() );
+ _menuTimer->stop();
+ KFileItem item( path, QString::fromLatin1( "inode/directory" ), KFileItem::Unknown );
+ KonqOperations::doDrop( &item, path, ev, this );
+ PanelButton::dropEvent(ev);
+}
+
+void BrowserButton::initPopup()
+{
+ topMenu->initialize();
+}
+
+void BrowserButton::slotDelayedPopup()
+{
+ topMenu->initialize();
+ topMenu->popup(KickerLib::popupPosition(popupDirection(), topMenu, this));
+ setDown(false);
+}
+
+void BrowserButton::properties()
+{
+ PanelBrowserDialog dlg( topMenu->path(), _icon, this );
+
+ if( dlg.exec() == QDialog::Accepted ){
+ _icon = dlg.icon();
+ QString path = dlg.path();
+
+ if ( path != topMenu->path() ) {
+ delete topMenu;
+ topMenu = new PanelBrowserMenu( path, this );
+ setPopup( topMenu );
+ setTitle( path );
+ }
+ setIcon( _icon );
+ emit requestSave();
+ }
+}
+
+void BrowserButton::startDrag()
+{
+ KURL url(topMenu->path());
+ emit dragme(KURL::List(url), labelIcon());
+}
+
diff --git a/kicker/kicker/buttons/browserbutton.h b/kicker/kicker/buttons/browserbutton.h
new file mode 100644
index 000000000..00ff0abea
--- /dev/null
+++ b/kicker/kicker/buttons/browserbutton.h
@@ -0,0 +1,66 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __browserbutton_h__
+#define __browserbutton_h__
+
+#include "panelbutton.h"
+
+class PanelBrowserMenu;
+
+/**
+ * Button that contains a Browser directory menu
+ */
+class BrowserButton : public PanelPopupButton
+{
+ Q_OBJECT
+
+public:
+ BrowserButton( const QString& icon, const QString& startDir, QWidget* parent );
+ BrowserButton( const KConfigGroup& config, QWidget* parent );
+ virtual ~BrowserButton();
+
+ void saveConfig( KConfigGroup& config ) const;
+
+ virtual void properties();
+
+protected slots:
+ virtual void slotDelayedPopup();
+ virtual void startDrag();
+
+protected:
+ void initialize( const QString& icon, const QString& startDir );
+ virtual QString tileName() { return "Browser"; }
+ virtual void initPopup();
+ virtual void dropEvent(QDropEvent *ev);
+ virtual void dragEnterEvent(QDragEnterEvent *ev);
+ virtual void dragLeaveEvent(QDragLeaveEvent *ev);
+ virtual QString defaultIcon() const { return "kdisknav"; };
+
+ PanelBrowserMenu* topMenu;
+ QString _icon;
+ QTimer *_menuTimer;
+};
+
+#endif
+
diff --git a/kicker/kicker/buttons/desktop.desktop b/kicker/kicker/buttons/desktop.desktop
new file mode 100644
index 000000000..f9ccbc81d
--- /dev/null
+++ b/kicker/kicker/buttons/desktop.desktop
@@ -0,0 +1,129 @@
+[Desktop Entry]
+Name=Show Desktop
+Name[af]=Vertoon Werkskerm
+Name[ar]=أعرض سطح المكتب
+Name[be]=Паказаць працоўны стол
+Name[bg]=Показване на работния плот
+Name[bn]=ডেস্কটপ দেখাও
+Name[br]=Diskouez ar burev
+Name[bs]=Prikaži desktop
+Name[ca]=Mostra l'escriptori
+Name[cs]=Zobrazit plochu
+Name[csb]=Pòkôże pùlt
+Name[da]=Vis desktop
+Name[de]=Zugriff auf Arbeitsfläche
+Name[el]=Εμφάνιση επιφάνειας εργασίας
+Name[eo]=Montri Tabulon
+Name[es]=Mostrar escritorio
+Name[et]=Näita töölauda
+Name[eu]=Erakutsi mahaigaina
+Name[fa]=نمایش رومیزی
+Name[fi]=Näytä työpöytä
+Name[fr]=Afficher le bureau
+Name[fy]=Buroblêd sjen litte
+Name[ga]=Taispeáin an Deasc
+Name[gl]=Escritório
+Name[he]=הצג שולחן עבודה
+Name[hr]=Prikaži radnu površinu
+Name[hu]=A munkaasztal megjelenítése
+Name[is]=Sýna skjáborð
+Name[it]=Mostra il desktop
+Name[ja]=デスクトップを表示
+Name[ka]=სამუშაო დაფის ჩვენება
+Name[kk]=Үстелге ауысу
+Name[km]=បង្ហាញ​ផ្ទៃតុ
+Name[ko]=데스크톱 1로 바꾸기
+Name[lt]=Rodyti darbastalį
+Name[mk]=Прикажи работна површина
+Name[nb]=Vis skrivebord
+Name[nds]=Schriefdischwieser
+Name[ne]=डेस्कटप देखाउनुहोस्
+Name[nl]=Bureaublad tonen
+Name[nn]=Vis skrivebord
+Name[pa]=ਵੇਹੜਾ ਵੇਖਾਓ
+Name[pl]=Pokaż pulpit
+Name[pt]=Mostrar o Ecrã
+Name[pt_BR]=Mostrar Área de Trabalho
+Name[ro]=Arată desktop
+Name[ru]=Свернуть все окна
+Name[rw]=Kwerekana Ibiro
+Name[se]=Čájet čállinbeavddi
+Name[sk]=Ukáže pracovnú plochu
+Name[sl]=Prikaži namizje
+Name[sr]=Прикажи радну површину
+Name[sr@Latn]=Prikaži radnu površinu
+Name[sv]=Visa skrivbord
+Name[te]=రంగస్థలాన్ని చూపు
+Name[tg]=Намоиши мизи корӣ
+Name[th]=แสดงพื้นที่หน้าจอ
+Name[tr]=Masaüstünü Göster
+Name[tt]=Östäl Kürsätü
+Name[uk]=Показати стільницю
+Name[uz]=Ish stoli
+Name[uz@cyrillic]=Иш столи
+Name[vi]=Hiển thị Màn hình nền
+Name[wa]=Mostrer l' sicribanne
+Name[zh_CN]=显示桌面
+Name[zh_TW]=顯示桌面
+Comment=A button that gives quick access to the desktop when pressed
+Comment[af]='n Knoppie wat vinnige toegang tot die werkskerm gee wanneer dit gedruk word
+Comment[ar]=زرّ يسمح بالوصول السريع إلى سطح المكتب عند ضغطه
+Comment[be]=Кнопка, якая дае хуткі доступ да працоўнага стала
+Comment[bg]=Бутон за бърз достъп до работния плот
+Comment[bn]=একটা বাটন যেটি চাপলে ডেস্কটপ ফাঁকা করে দেখানো হবে
+Comment[bs]=Dugme koje sklanja sve prozore sa ekrana i prikazuje desktop
+Comment[ca]=Un botó que dóna accés ràpid a l'escriptori en prémer-hi
+Comment[cs]=Tlačítko s rychlým přístupem k pracovní ploše
+Comment[csb]=Knąpa chùtczégò przistãpù do pùltu
+Comment[da]=En knap der giver hurtig adgang til desktoppen når den trykkes ned
+Comment[de]=Dieser Knopf ermöglicht den schnellen Zugriff auf die Arbeitsfläche
+Comment[el]=Ένα κουμπί που όταν πατηθεί δίνει γρήγορη πρόσβαση στην επιφάνεια εργασίας
+Comment[eo]=Butono kiu ebligas rapid aliron al labortabulo kiam premita
+Comment[es]=Muestra rápidamente el escritorio al pulsarlo
+Comment[et]=Nupp, mis võimaldab ühe klõpsuga kiiresti pääseda otse töölauale
+Comment[eu]=Zapatzean mahagainera sarbide bizkorra ematen duen botoia
+Comment[fa]=دکمه‌ای که وقتی فشار داده ‌شد، امکان دستیابی سریع به رومیزی را می‌دهد.
+Comment[fi]=Painike, jota painamalla pääsee nopeasti työpöydälle
+Comment[fr]=Un bouton, qui, en étant cliqué, donne un accès rapide au bureau
+Comment[fy]=In knop hokker flugge tagong ta it buroblêd jout
+Comment[gl]=Un botón que dá aceso rápido ao escritório cando se preme
+Comment[he]=כפתור הנותן גישה מהירה לשולחן העבודה כאשר נלחץ
+Comment[hr]=Gumb koji omogućuje brz pristup radnoj površini
+Comment[hu]=Ezzel a gombbal gyorsan elérhető a munkaasztal
+Comment[is]=Hnappur sem veitir hraðan aðgang að skjáborðinu
+Comment[it]=Un pulsante che da accesso rapido al desktop quando viene premuto
+Comment[ja]=デスクトップに素早くアクセスするためのボタン
+Comment[kk]=Бір басып үстелге қатынау батырмасы
+Comment[km]=ប៊ូតុង​ដែល​ផ្តល់​ការ​ចូល​ដំណើរការ​រហ័សទៅ​ផ្ទៃតុ ពេល​ចុច
+Comment[lt]=Mygtukas, kurį nuspaudus suteikiama greita prieiga prie darbastalio
+Comment[mk]=Копче што дава брз пристап кон работната површина кога е притиснато
+Comment[nb]=En knapp som gir deg rask tilgang til skrivebordet
+Comment[nds]=Disse Knoop laat Een direktemang op den Schriefdisch togriepen
+Comment[ne]=थिचेको बेलामा डेस्कटपमा द्रुत पहुँच प्रदान गर्ने बटन
+Comment[nl]=Een knop die snelle toegang tot het bureaublad geeft
+Comment[nn]=Ein knapp som gir deg rask tilgang til skrivebordet
+Comment[pa]=ਇੱਕ ਬਟਨ, ਜੋ ਕਿ ਦਬਾਉਣ ਉਪਰੰਤ ਤੁਹਾਨੂ ਵੇਹੜਾ ਉਪਲੱਬਧ ਕਰਵਾਉਦਾ ਹੈ
+Comment[pl]=Przycisk szybkiego dostępu do pulpitu
+Comment[pt]=Um botão que dá acesso rápido ao ecrã, quando for carregado
+Comment[pt_BR]=Um botão que fornece acesso rápido para a área de trabalho, quando pressionado
+Comment[ro]=Un buton care permite acces rapid la desktop la apăsare
+Comment[ru]=Кнопка перехода на заданный рабочий стол
+Comment[rw]=Buto itanga ukugera vuba ku biro igihe ikanzwe
+Comment[se]=Boallu mii čiehká buot lásiid mat leat čállinbeavddis go dan coahkkala
+Comment[sk]=Tlačidlo pre rýchly prístup na pracovnú plochu
+Comment[sl]=Klik tega gumba omogoča hiter dostop do namizja
+Comment[sr]=Дугме које по притиску даје брз приступ радној површини
+Comment[sr@Latn]=Dugme koje po pritisku daje brz pristup radnoj površini
+Comment[sv]=En knapp som ger snabb åtkomst till skrivbordet när den klickas
+Comment[th]=ปุ่มที่กดแล้วจะแสดงพื้นที่หน้าจออย่างรวดเร็ว
+Comment[tr]=Tıklandığı zaman masaüstüne hızlı erişim sağlar
+Comment[tt]=Östäl eçtälegenä tiz ireşergä birüçe töymä
+Comment[uk]=Кнопка, яка при натисканні надає швидкий доступ до стільниці
+Comment[uz]=Ish stoliga qisqa yoʻl
+Comment[uz@cyrillic]=Иш столига қисқа йўл
+Comment[vi]=Một nút cho phép bạn truy cập ngay đến màn hình nền mỗi khi ấn vào
+Comment[wa]=On boton ki dene raddimint accès å scribanne cwand il est tchôkî
+Comment[zh_CN]=按下可快速访问桌面的按钮
+Comment[zh_TW]=按下去能快速顯示桌面的按鈕
+Icon=desktop
+X-KDE-Library=DesktopButton
diff --git a/kicker/kicker/buttons/desktopbutton.cpp b/kicker/kicker/buttons/desktopbutton.cpp
new file mode 100644
index 000000000..3831303d7
--- /dev/null
+++ b/kicker/kicker/buttons/desktopbutton.cpp
@@ -0,0 +1,84 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+#include <qdragobject.h>
+
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <konq_operations.h>
+#include <kfileitem.h>
+
+#include "showdesktop.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+
+#include "desktopbutton.h"
+#include "desktopbutton.moc"
+
+DesktopButton::DesktopButton( QWidget* parent )
+ : PanelButton( parent, "DesktopButton" )
+{
+ setToggleButton(true);
+
+ QToolTip::add(this, i18n("Show desktop"));
+ setTitle(i18n("Desktop Access"));
+ setIcon("desktop");
+
+ connect( this, SIGNAL(toggled(bool)), this, SLOT(showDesktop(bool)) );
+ connect( ShowDesktop::the(), SIGNAL(desktopShown(bool)), this, SLOT(toggle(bool)) );
+
+ setOn( ShowDesktop::the()->desktopShowing() );
+}
+
+void DesktopButton::toggle(bool showDesktop)
+{
+ KickerTip::enableTipping(false);
+ setOn(showDesktop);
+ KickerTip::enableTipping(true);
+}
+
+void DesktopButton::showDesktop(bool showDesktop)
+{
+ KickerTip::enableTipping(false);
+ ShowDesktop::the()->showDesktop(showDesktop);
+ KickerTip::enableTipping(true);
+}
+
+void DesktopButton::dragEnterEvent( QDragEnterEvent *ev )
+{
+ if ((ev->source() != this) && KURLDrag::canDecode(ev))
+ ev->accept(rect());
+ else
+ ev->ignore(rect());
+ PanelButton::dragEnterEvent(ev);
+}
+
+void DesktopButton::dropEvent( QDropEvent *ev )
+{
+ KURL dPath ( KGlobalSettings::desktopPath() );
+ KFileItem item( dPath, QString::fromLatin1( "inode/directory" ), KFileItem::Unknown );
+ KonqOperations::doDrop( &item, dPath, ev, this );
+ PanelButton::dropEvent(ev);
+}
+
diff --git a/kicker/kicker/buttons/desktopbutton.h b/kicker/kicker/buttons/desktopbutton.h
new file mode 100644
index 000000000..62de4c342
--- /dev/null
+++ b/kicker/kicker/buttons/desktopbutton.h
@@ -0,0 +1,49 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __desktopbutton_h__
+#define __desktopbutton_h__
+
+#include "panelbutton.h"
+
+/**
+ * Button that shows the deskop
+ */
+class DesktopButton : public PanelButton
+{
+ Q_OBJECT
+
+public:
+ DesktopButton( QWidget* parent );
+
+protected:
+ virtual QString tileName() { return "DesktopButton"; }
+ virtual void dragEnterEvent(QDragEnterEvent *ev);
+ virtual void dropEvent(QDropEvent *ev);
+
+protected slots:
+ void toggle(bool);
+ void showDesktop(bool);
+};
+
+#endif
diff --git a/kicker/kicker/buttons/exec.desktop b/kicker/kicker/buttons/exec.desktop
new file mode 100644
index 000000000..ab30698f3
--- /dev/null
+++ b/kicker/kicker/buttons/exec.desktop
@@ -0,0 +1,125 @@
+[Desktop Entry]
+Name=Non-KDE Application Launcher
+Name[af]=Nie-KDE Program Lanseerder
+Name[ar]=مُطلِق التطبيقات اغير KDE
+Name[be]=Запускальнік праграмы не-KDE
+Name[bg]=Стартиране на програми
+Name[bn]=নন-কে.ডি.ই অ্যাপলিকেশন লঞ্চার
+Name[bs]=Pokretač ne-KDE programa
+Name[ca]=Engegador d'aplicacions no KDE
+Name[cs]=Spouštěč aplikací nepatřících do KDE
+Name[csb]=Zrëszanié programów z bùtna KDE
+Name[da]=Starter ikke-KDE-programmer
+Name[de]=Nicht-KDE-Programm
+Name[el]=Εκτελεστής μη-KDE εφαρμογών
+Name[eo]=neKDE-a Aplikaĵolanĉilo
+Name[es]=Aplicaciones No-KDE
+Name[et]=KDE-väliste rakenduste käivitaja
+Name[eu]=KDEren ez diren aplikazio abiarazlea
+Name[fa]=راه‌انداز کاربرد غیر KDE
+Name[fi]=Ei-KDE:n sovellusten käynnistäjä
+Name[fr]=Lancement des applications non KDE
+Name[fy]=Net-KDE-programma's útfierder
+Name[ga]=Tosaitheoir Feidhmchlár Neamh-KDE
+Name[gl]=Lanzador de Aplicacións Non-KDE
+Name[he]=מפעיל תוכניות שלא שייכות למשפחת KDE
+Name[hr]=Pokretač vanjskih KDE aplikacija
+Name[hu]=Programindító nem KDE-s alkalmazásokhoz
+Name[is]=Ræsir fyrir ekki-KDE forrit
+Name[it]=Lancio di applicazioni non-KDE
+Name[ja]=KDE 以外のアプリケーションランチャー
+Name[ka]=არა KDE-ს პროგრამების
+Name[kk]=KDE-ге тиесілі емес қолданбаларды жегу
+Name[km]=ឧបករណ៍​បើក​កម្មវិធី​មិន​មែន KDE
+Name[ko]=프로그램 실행기
+Name[lt]=Ne-KDE programų startavimo priedas
+Name[mk]=Стартувач на не-KDE апликации
+Name[nb]=Last ikke-KDE-programmer
+Name[nds]=Starter för Nich-KDE-Programmen
+Name[ne]=KDE बाहेकको अनुप्रयोग सुरुआतकर्ता
+Name[nl]=Niet-KDE-programma's starten
+Name[nn]=Start av ikkje-KDE-program
+Name[pa]=ਨਾ-KDE ਕਾਰਜ ਸ਼ੁਰੂਆਤੀ
+Name[pl]=Uruchamianie programów spoza KDE
+Name[pt]=Lançador de Aplicações não-KDE
+Name[pt_BR]=Lançador de aplicativos que não são do KDE
+Name[ro]=Lansator de aplicații Non-KDE
+Name[ru]=Запуск приложения не из KDE
+Name[rw]=Bitari-KDE Porogaramu Mutangiza
+Name[se]=Ii-KDE prográmmaid álggaheaddji
+Name[sk]=Spúšťač non-KDE aplikácií
+Name[sl]=Zaganjalnik ne-KDE programov
+Name[sr]=Покретач не-KDE програма
+Name[sr@Latn]=Pokretač ne-KDE programa
+Name[sv]=Start av program som inte hör till KDE
+Name[th]=ตัวเรียกใช้งานแอพพลิเคชันที่ไม่ใช่ของ KDE
+Name[tr]=KDE Dışı Uygulama Başlatıcısı
+Name[tt]=KDE-bulmağan Yazılım Cibärgeç
+Name[uk]=Запуск не-KDE програм
+Name[uz]=No-KDE dasturlarni ishga tushuruvchi
+Name[uz@cyrillic]=Но-KDE дастурларни ишга тушурувчи
+Name[vi]=Trình khởi động Chương trình không của KDE
+Name[wa]=Enondeu di programes nén KDE
+Name[zh_CN]=非 KDE 应用程序启动器
+Name[zh_TW]=非-KDE 應用程式啟動器
+Comment=A launcher for programs not in the K Menu
+Comment[af]='n Lanseerder vir programme wat nie in die K-Kieslys voorkom nie
+Comment[ar]=مُطلِق البرامج غير التابعة لِلقائمة K
+Comment[be]=Запускальнік для праграмы, якой няма ў меню KDE
+Comment[bg]=Стартиране на програми, които са извън главното меню (К)
+Comment[bn]=কে-মেনু-তে নেই এমন প্রোগ্রাম-এর চালু করার জন্য একটি লঞ্চার
+Comment[bs]=Pokretač programa koji nisu u K meniju
+Comment[ca]=Un engegador de programes que no hi són al menú K
+Comment[cs]=Spouštěč pro programy nenacházející se v hlavní nabídce KDE
+Comment[csb]=Zrëszanié programów, jaczich nie dô w K menu
+Comment[da]=En starter af programmer der ikke er i K-Menuen
+Comment[de]=Startet Programme, die sich nicht im K-Menü befinden
+Comment[el]=Ένας εκτελεστής εφαρμογών που δε βρίσκονται στο Μενού K
+Comment[eo]=Lanĉilo por programoj ne en la K Menuo
+Comment[es]=Le permite ejecutar aplicaciones que no están en el Menu K
+Comment[et]=K menüüst puuduvate rakenduste käivitaja
+Comment[eu]=K Menuan ez dauden aplikazio abiarazlea
+Comment[fa]=یک راه‌انداز برای برای برنامه‌هایی که در گزینگان K نیست
+Comment[fi]=Käynnistäjä ohjelmille, jotka eivät ole K-valikossa
+Comment[fr]=Lancement des programmes n'étant pas dans le menu K
+Comment[fy]=In útfierder foar programma's hokker net yn it K-menu stean
+Comment[gl]=Un lanzador para aplicacións que non estexan no Menu de KDE
+Comment[he]=מפעיל עבור יישומים שלא בתפריט המערכת
+Comment[hr]=Pokretač programa koji se ne nalaze na KDE izborniku
+Comment[hu]=Programindító
+Comment[is]=Ræsir fyrir forrit sem eru ekki í K valmyndinni
+Comment[it]=Per lanciare programmi che non sono nel menu K
+Comment[ja]=K メニューにないプログラムを起動
+Comment[kk]=KDE мәзрінде жоқ бағдарламаларды жегу
+Comment[km]=ឧបករណ៍​បើក​កម្មវិធី​ដែល​មិន​នៅ​ក្នុង​ម៉ឺនុយ K
+Comment[lt]=K meniu nesančių programų startavimo meniu
+Comment[mk]=Стартување на програми што не се во К-менито
+Comment[nb]=Mulighet til å starte programmer som ikke er i KDE-menyen
+Comment[nds]=En Starter för Programmen, de nich in't K-Menü staht
+Comment[ne]=के मेनुमा नभएका कार्यक्रमका लागि सुरुआतकर्ता
+Comment[nl]=Een starter voor het uitvoeren van programma's die niet in het K-menu staan
+Comment[nn]=Start av program som ikkje ligg i K-menyen
+Comment[pa]= ਕੇ(K) ਮੇਨੂ ਵਿੱਚ ਨਾ-ਮੌਜੂਦ ਕਾਰਜ ਲਈ ਸ਼ੁਰੂਆਤੀ ਹੈ
+Comment[pl]=Uruchamianie programów, które nie znajdują się w menu K
+Comment[pt]=Um lançador de programas que não estejam no Menu K
+Comment[pt_BR]=Um lançador para programas que não estão no Menu K
+Comment[ro]=Lansator de programe ce nu se află în meniul K
+Comment[ru]=Запуск приложений, не входящих в меню KDE
+Comment[rw]=Mutangiza w'amaporogaramu atari muri K Ibikubiyemo
+Comment[sk]=Spúštač programov, ktoré nie sú v KDE Menu
+Comment[sl]=Zaganjalnik programov, ki se ne nahajajo v meniju KDE-ja
+Comment[sr]=Покретач за програме којих нема у K-менију
+Comment[sr@Latn]=Pokretač za programe kojih nema u K-meniju
+Comment[sv]=Start av program som inte finns i K-menyn
+Comment[th]=ตัวเรียกใช้งานโปรแกรมที่ไม่ได้อยู่ใน K menu
+Comment[tr]=KDE menüsünde bulunmayan programlar için bir başlatıcı
+Comment[tt]=K-Saylaqta bulmağan yazılımnar cibärgeçe
+Comment[uk]=Запуск програм, яких немає в K Меню
+Comment[uz]=K-menyuga qoʻshilmagan dasturlarni ishga tushirish
+Comment[uz@cyrillic]=К-менюга қўшилмаган дастурларни ишга тушириш
+Comment[vi]=Trình khởi động các chương trình không có trong thực đơn của KDE
+Comment[wa]=On enondeu po les programes ki n' sont nén dins l' dressêye K
+Comment[zh_CN]=启动不在 K 菜单中的程序
+Comment[zh_TW]=用於不在 K 選單中的程式啟動器
+Icon=exec
+X-KDE-Library=ExecButton
diff --git a/kicker/kicker/buttons/extensionbutton.cpp b/kicker/kicker/buttons/extensionbutton.cpp
new file mode 100644
index 000000000..004e0d47b
--- /dev/null
+++ b/kicker/kicker/buttons/extensionbutton.cpp
@@ -0,0 +1,79 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+
+#include <kconfig.h>
+#include <kpanelmenu.h>
+
+#include "menuinfo.h"
+
+#include "extensionbutton.h"
+#include "extensionbutton.moc"
+
+ExtensionButton::ExtensionButton( const QString& desktopFile, QWidget* parent )
+ : PanelPopupButton( parent, "ExtensionButton" )
+ , info( 0 )
+ , menu( 0 )
+{
+ initialize( desktopFile );
+}
+
+ExtensionButton::ExtensionButton( const KConfigGroup& config, QWidget* parent )
+ : PanelPopupButton( parent, "extensionbuttton" )
+{
+ initialize( config.readPathEntry("DesktopFile") );
+}
+
+void ExtensionButton::initialize( const QString& desktopFile )
+{
+ info = new MenuInfo(desktopFile);
+ if (!info->isValid())
+ {
+ m_valid = false;
+ return;
+ }
+ menu = info->load(this);
+ setPopup(menu);
+
+ QToolTip::add(this, info->comment());
+ setTitle(info->name());
+ setIcon(info->icon());
+}
+
+ExtensionButton::~ExtensionButton()
+{
+ delete info;
+}
+
+void ExtensionButton::saveConfig( KConfigGroup& config ) const
+{
+ config.writePathEntry("DesktopFile", info->desktopFile());
+}
+
+void ExtensionButton::initPopup()
+{
+ if( !menu->initialized() ) {
+ menu->reinitialize();
+ }
+}
diff --git a/kicker/kicker/buttons/extensionbutton.h b/kicker/kicker/buttons/extensionbutton.h
new file mode 100644
index 000000000..0d489f706
--- /dev/null
+++ b/kicker/kicker/buttons/extensionbutton.h
@@ -0,0 +1,52 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __extensionbutton_h__
+#define __extensionbutton_h__
+
+#include "panelbutton.h"
+
+class MenuInfo;
+class KPanelMenu;
+
+class ExtensionButton : public PanelPopupButton
+{
+ Q_OBJECT
+
+public:
+ ExtensionButton( const QString& desktopFile, QWidget* parent );
+ ExtensionButton( const KConfigGroup& config, QWidget* parent );
+ ~ExtensionButton();
+
+ void saveConfig( KConfigGroup& config ) const;
+
+protected:
+ void initialize( const QString& desktopFile );
+ virtual QString tileName() { return "URL"; }
+ virtual void initPopup();
+
+ MenuInfo* info;
+ KPanelMenu* menu;
+};
+
+#endif
diff --git a/kicker/kicker/buttons/kbutton.cpp b/kicker/kicker/buttons/kbutton.cpp
new file mode 100644
index 000000000..071d15981
--- /dev/null
+++ b/kicker/kicker/buttons/kbutton.cpp
@@ -0,0 +1,78 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+
+#include <klocale.h>
+#include <kapplication.h>
+#include <kdebug.h>
+
+#include "kickerSettings.h"
+
+#include "config.h"
+
+#include "menumanager.h"
+#include "k_mnu.h"
+
+#include "kbutton.h"
+#include "kbutton.moc"
+
+KButton::KButton( QWidget* parent )
+ : PanelPopupButton( parent, "KButton" )
+{
+ QToolTip::add(this, i18n("Applications, tasks and desktop sessions"));
+ setTitle(i18n("K Menu"));
+
+ setPopup(MenuManager::the()->kmenu());
+ MenuManager::the()->registerKButton(this);
+ setIcon("kmenu");
+
+ if (KickerSettings::showKMenuText())
+ {
+ setButtonText(KickerSettings::kMenuText());
+ setFont(KickerSettings::buttonFont());
+ setTextColor(KickerSettings::buttonTextColor());
+ }
+}
+
+KButton::~KButton()
+{
+ MenuManager::the()->unregisterKButton(this);
+}
+
+void KButton::properties()
+{
+ KApplication::startServiceByDesktopName("kmenuedit", QStringList(),
+ 0, 0, 0, "", true);
+}
+
+void KButton::initPopup()
+{
+// kdDebug(1210) << "KButton::initPopup()" << endl;
+
+ // this hack is required to ensure the correct popup position
+ // when the size of the recent application part of the menu changes
+ // please don't remove this _again_
+ MenuManager::the()->kmenu()->initialize();
+}
+
diff --git a/kicker/kicker/buttons/kbutton.h b/kicker/kicker/buttons/kbutton.h
new file mode 100644
index 000000000..6de61181f
--- /dev/null
+++ b/kicker/kicker/buttons/kbutton.h
@@ -0,0 +1,50 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __kbutton_h__
+#define __kbutton_h__
+
+#include "panelbutton.h"
+
+/**
+ * Button that contains the PanelKMenu and client menu manager.
+ */
+class KButton : public PanelPopupButton
+{
+ Q_OBJECT
+
+public:
+ KButton( QWidget *parent );
+ ~KButton();
+
+ void loadConfig( const KConfigGroup& config );
+
+ virtual void properties();
+
+protected:
+ virtual QString tileName() { return "KMenu"; }
+ virtual void initPopup();
+ virtual QString defaultIcon() const { return "go"; }
+};
+
+#endif
diff --git a/kicker/kicker/buttons/kmenu.desktop b/kicker/kicker/buttons/kmenu.desktop
new file mode 100644
index 000000000..be9a0aa68
--- /dev/null
+++ b/kicker/kicker/buttons/kmenu.desktop
@@ -0,0 +1,132 @@
+[Desktop Entry]
+Name=K Menu
+Name[af]=K-Kieslys
+Name[ar]=قائمة K
+Name[be]=Меню KDE
+Name[bg]=Главно меню
+Name[bn]=কে মেনু
+Name[br]=Meuziad K
+Name[bs]=K meni
+Name[ca]=Menú K
+Name[cs]=Nabídka KDE
+Name[cy]=Y Ddewislen K
+Name[da]=K-Menu
+Name[de]=K-Menü
+Name[el]=Μενού K
+Name[eo]=KDEa Menuo
+Name[es]=Menú de KDE
+Name[et]=K menüü
+Name[eu]=K menua
+Name[fa]=گزینگان K
+Name[fi]=K-valikko
+Name[fr]=Menu K
+Name[fy]=K-menu
+Name[ga]=Roghchlár K
+Name[gl]=Menu de KDE
+Name[he]=תפריט K
+Name[hr]=KDE izbornik
+Name[hu]=KDE menü
+Name[is]=K valmynd
+Name[it]=Menu K
+Name[ja]=K メニュー
+Name[ka]=K მენიუ
+Name[kk]=K мәзірі
+Name[km]=ម៉ឺនុយ K
+Name[ko]=KDE 메뉴
+Name[lt]=K meniu
+Name[mk]=К-мени
+Name[nb]=KDE-meny
+Name[nds]=K-Menü
+Name[ne]=के मेनु
+Name[nl]=K-menu
+Name[nn]=K-meny
+Name[pa]=K ਮੇਨੂ
+Name[pl]=Menu K
+Name[pt]=Menu K
+Name[pt_BR]=Menu K
+Name[ro]=Meniu K
+Name[ru]=Меню KDE
+Name[rw]=K Ibikubiyemo
+Name[se]=K-fállu
+Name[sk]=Menu KDE
+Name[sl]=Meni KDE-ja
+Name[sr]=K-мени
+Name[sr@Latn]=K-meni
+Name[sv]=K-meny
+Name[te]=కె పట్టి
+Name[tg]=Менюи KDE
+Name[th]=เมนู KDE
+Name[tr]=KDE Menüsü
+Name[tt]=K-Saylaq
+Name[uk]=K Меню
+Name[uz]=K-menyu
+Name[uz@cyrillic]=К-меню
+Name[vi]=Thực đơn KDE
+Name[wa]=Dressêye K
+Name[zh_CN]=K 菜单
+Name[zh_TW]=K 選單
+Comment=Applications and common actions
+Comment[af]=Programme en algemene aksies
+Comment[ar]=تطبيقات و أعمال شائعة
+Comment[be]=Праграмы і асноўныя дзеянні
+Comment[bg]=Главното меню с програмите, системните настройки и всичко останало
+Comment[bn]=অ্যাপলিকেশন এবং সাধারণ ক্রিয়াসমূহ
+Comment[bs]=Programi i standardne akcije
+Comment[ca]=Aplicacions i accions comunes
+Comment[cs]=Aplikace a časté činnosti
+Comment[csb]=Programë ë pòpùlarné dzejania
+Comment[da]=Programmer og sædvanlige handlinger
+Comment[de]=Enthält Programme und häufig verwendete Aktionen
+Comment[el]=Εφαρμογές και τυπικές ενέργειες
+Comment[eo]=Aplikaĵoj kaj komunaj agoj
+Comment[es]=Aplicaciones y acciones comunes
+Comment[et]=Rakendused ja levinumad toimingud
+Comment[eu]=Aplikazioak eta ohiko ekintzak
+Comment[fa]=کاربردها و کنشهای مشترک
+Comment[fi]=Sovellukset ja yleiset toiminnot
+Comment[fr]=Applications et actions communes
+Comment[fy]=Applikaasjes en folle foarkommende aksjes
+Comment[ga]=Feidhmchláir agus gníomhartha coitianta
+Comment[gl]=Aplicacións e accións comuns
+Comment[he]=יישומים ופעולות מזדמנות
+Comment[hr]=Aplikacije i zajedničke aktivnosti
+Comment[hu]=Alkalmazások és általános műveletek
+Comment[is]=Forrit og algengar aðgerðir
+Comment[it]=Applicazioni e azioni comuni
+Comment[ja]=アプリケーションと一般的なアクションのメニュー
+Comment[ka]=პროგრამები და საზოგადო ქმედებები
+Comment[kk]=Қолданбалар мен жалпы амалдар
+Comment[km]=កម្មវិធី និង​អំពើ​ទូទៅ
+Comment[lt]=Programos ir įprasti veiksmai
+Comment[mk]=Апликации и општи дејства
+Comment[nb]=Programmer og vanlige handlinger
+Comment[nds]=Programmen un allgemeen Akschonen
+Comment[ne]=अनुप्रयोग र साझा कार्य
+Comment[nl]=Programma's en veelvoorkomende acties
+Comment[nn]=Program og vanlege handlingar
+Comment[pa]=ਕਾਰਜ ਅਤੇ ਆਮ ਕਾਰਵਾਈਆਂ
+Comment[pl]=Programy i popularne czynności
+Comment[pt]=Aplicações e acções comuns
+Comment[pt_BR]=Aplicativos e ações comuns
+Comment[ro]=Aplicații și acțiuni uzuale
+Comment[ru]=Приложения и действия
+Comment[rw]=Porogaramu n'ibikorwa rusange
+Comment[se]=Prográmmat ja dábálaš doaimmat
+Comment[sk]=Programy a všeobecné akcie
+Comment[sl]=KDE-jev meni s programi in pogostimi dejanji
+Comment[sr]=Програми и уобичајене акције
+Comment[sr@Latn]=Programi i uobičajene akcije
+Comment[sv]=Program och vanliga åtgärder
+Comment[tg]=Барномаҳо ва амалҳои умумӣ
+Comment[th]=แอพพลิเคชั่น และการกระทำทั่วๆไป
+Comment[tr]=Uygulamalar ve ortak eylemler
+Comment[tt]=Yazılımnar belän töp ğämällär
+Comment[uk]=Програми і загальні дії
+Comment[uz]=Dasturlar va umumiy amallar
+Comment[uz@cyrillic]=Дастурлар ва умумий амаллар
+Comment[vi]=Ứng dụng và thao tác thường làm
+Comment[wa]=Programes et comones accions
+Comment[zh_CN]=应用程序和公共操作
+Comment[zh_TW]=應用程式與一般動作
+Icon=kmenu
+X-KDE-Library=KMenuButton
diff --git a/kicker/kicker/buttons/nonkdeappbutton.cpp b/kicker/kicker/buttons/nonkdeappbutton.cpp
new file mode 100644
index 000000000..9413e8aaa
--- /dev/null
+++ b/kicker/kicker/buttons/nonkdeappbutton.cpp
@@ -0,0 +1,287 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+#include <qdragobject.h>
+
+#include <kconfig.h>
+#include <kdesktopfile.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <krun.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kiconeffect.h>
+#include <kdebug.h>
+
+// the header where the configuration dialog is defined.
+#include "exe_dlg.h"
+
+// our own definition
+#include "nonkdeappbutton.h"
+
+// we include the "moc" file so that the KDE build system knows to create it
+#include "nonkdeappbutton.moc"
+
+// this is one of the two constructors. gets called when creating a new button
+// e.g. via the "non-KDE Application" dialog, not one that was saved and then
+// restored.
+NonKDEAppButton::NonKDEAppButton(const QString& name,
+ const QString& description,
+ const QString& filePath, const QString& icon,
+ const QString &cmdLine, bool inTerm,
+ QWidget* parent)
+ : PanelButton(parent, "NonKDEAppButton") // call our superclass's constructor
+{
+ // call the initialization method
+ initialize(name, description, filePath, icon, cmdLine, inTerm);
+
+ // and connect the clicked() signal (emitted when the button is activated)
+ // to the slotExec() slot
+ // we do this here instead of in initialize(...) since initialize(...) may
+ // get called later, e.g after reconfiguring it
+ connect(this, SIGNAL(clicked()), SLOT(slotExec()));
+}
+
+// this constructor is used when restoring a button, usually at startup
+NonKDEAppButton::NonKDEAppButton( const KConfigGroup& config, QWidget* parent )
+ : PanelButton(parent, "NonKDEAppButton") // call our superclass's constructor
+{
+ // call the initialization method, this time with values from a config file
+ initialize(config.readEntry("Name"),
+ config.readEntry("Description"),
+ config.readPathEntry("Path"),
+ config.readEntry("Icon"),
+ config.readPathEntry("CommandLine"),
+ config.readBoolEntry("RunInTerminal"));
+
+ // see comment on connect in above constructor
+ connect(this, SIGNAL(clicked()), SLOT(slotExec()));
+}
+
+void NonKDEAppButton::initialize(const QString& name,
+ const QString& description,
+ const QString& filePath, const QString& icon,
+ const QString &cmdLine, bool inTerm )
+{
+ // and now we actually set up most of the member variables with the
+ // values passed in here. by doing this all in an initialize() method
+ // we avoid duplicating this code all over the place
+ nameStr = name;
+ descStr = description;
+ pathStr = filePath;
+ iconStr = icon;
+ cmdStr = cmdLine;
+ term = inTerm;
+
+ // now we set the buttons tooltip, title and icon using the appropriate
+ // set*() methods from the PanelButton class from which we subclass
+
+ // assign the name or the description to a QString called tooltip
+ QString tooltip = description.isEmpty() ? nameStr : descStr;
+
+ if (tooltip.isEmpty())
+ {
+ // we had nothing, so let's try the path
+ tooltip = pathStr;
+
+ // and add the command if we have one.
+ if (!cmdStr.isEmpty())
+ {
+ tooltip += " " + cmdStr;
+ }
+
+ // set the title to the pathStr
+ setTitle(pathStr);
+ }
+ else
+ {
+ // since we have a name or a description (assigned by the user) let's
+ // use that as the title
+ setTitle(nameStr.isEmpty() ? descStr : nameStr);
+ }
+
+ // set the tooltip
+ QToolTip::add(this, tooltip);
+
+ // set the icon
+ setIcon(iconStr);
+}
+
+void NonKDEAppButton::saveConfig( KConfigGroup& config ) const
+{
+ // this is called whenever we change something
+ // the config object sent in will already be set to the
+ // right group and file, so we can just start writing
+ config.writeEntry("Name", nameStr);
+ config.writeEntry("Description", descStr);
+ config.writeEntry("RunInTerminal", term);
+ config.writePathEntry("Path", pathStr);
+ config.writeEntry("Icon", iconStr);
+ config.writePathEntry("CommandLine", cmdStr);
+}
+
+void NonKDEAppButton::dragEnterEvent(QDragEnterEvent *ev)
+{
+ // when something is dragged onto this button, we'll accept it
+ // if we aren't dragged onto ourselves, and if it's a URL
+ if ((ev->source() != this) && KURLDrag::canDecode(ev))
+ {
+ ev->accept(rect());
+ }
+ else
+ {
+ ev->ignore(rect());
+ }
+
+ // and now let the PanelButton do as it wishes with it...
+ PanelButton::dragEnterEvent(ev);
+}
+
+void NonKDEAppButton::dropEvent(QDropEvent *ev)
+{
+ // something has been droped on us!
+ KURL::List fileList;
+ QString execStr;
+ if (KURLDrag::decode(ev, fileList))
+ {
+ // according to KURLDrag, we've successfully retrieved
+ // one or more URLs! now we iterate over them one by
+ // one ....
+ for (KURL::List::ConstIterator it = fileList.begin();
+ it != fileList.end();
+ ++it)
+ {
+ const KURL &url(*it);
+ if (KDesktopFile::isDesktopFile(url.path()))
+ {
+ // this URL is actually a .desktop file, so let's grab
+ // the URL it actually points to ...
+ KDesktopFile deskFile(url.path());
+ deskFile.setDesktopGroup();
+
+ // ... and add it to the exec string
+ execStr += KProcess::quote(deskFile.readURL()) + " ";
+ }
+ else
+ {
+ // it's just a URL of some sort, add it directly to the exec
+ execStr += KProcess::quote(url.path()) + " ";
+ }
+ }
+
+ // and now run the command
+ runCommand(execStr);
+ }
+
+ // and let PanelButton clean up
+ PanelButton::dropEvent(ev);
+}
+
+void NonKDEAppButton::slotExec()
+{
+ // the button was clicked, let's take some action
+ runCommand();
+}
+
+void NonKDEAppButton::runCommand(const QString& execStr)
+{
+ // run our command! this method is used both by the drag 'n drop
+ // facilities as well as when the button is activated (usualy w/a click)
+
+ // we'll use the "result" variable to record our success/failure
+ bool result;
+
+ // since kicker doesn't listen to or use the session manager, we have
+ // to make sure that our environment is set up correctly. this is
+ // accomlplished by doing:
+ kapp->propagateSessionManager();
+
+ if (term)
+ {
+ // run in a terminal? ok! we find this in the config file in the
+ // [misc] group (this will usually be in kdeglobal, actually, which
+ // get merged into the application config automagically for us
+ KConfig *config = KGlobal::config();
+ config->setGroup("misc");
+ QString termStr = config->readPathEntry("Terminal", "konsole");
+
+ // and now we run the darn thing and store how we fared in result
+ result = KRun::runCommand(termStr + " -e " + pathStr + " " +
+ cmdStr + " " + execStr,
+ pathStr, iconStr);
+ }
+ else
+ {
+ // just run it...
+ result = KRun::runCommand(pathStr + " " + cmdStr + " " + execStr,
+ pathStr, iconStr);
+ }
+
+ if (!result)
+ {
+ // something went wrong, so let's show an error msg to the user
+ KMessageBox::error(this, i18n("Cannot execute non-KDE application."),
+ i18n("Kicker Error"));
+ return;
+ }
+}
+
+void NonKDEAppButton::updateSettings(PanelExeDialog* dlg)
+{
+ // we were reconfigured via the confiugration dialog
+ // re-setup our member variables using initialize(...),
+ // this time using values from the dlg
+ initialize(dlg->title(), dlg->description(), dlg->command(),
+ dlg->iconPath(), dlg->commandLine(), dlg->useTerminal());
+
+ // now delete the dialog so that it doesn't leak memory
+ delete dlg;
+
+ // and emit a signal that the container that houses us
+ // listens for so it knows when to start the process to
+ // save our configuration
+ emit requestSave();
+}
+
+void NonKDEAppButton::properties()
+{
+ // the user has requested to configure this button
+ // this method gets called by the ButtonContainer that houses the button
+ // see ButtonContainer::eventFilter(QObject *o, QEvent *e), where the
+ // context menu is created and dealt with.
+
+ // so we create a new config dialog ....
+ PanelExeDialog* dlg = new PanelExeDialog(nameStr, descStr, pathStr,
+ iconStr, cmdStr, term, this);
+
+ // ... connect the signal it emits when it has data for us to save
+ // to our updateSettings slot (see above) ...
+ connect(dlg, SIGNAL(updateSettings(PanelExeDialog*)), this,
+ SLOT(updateSettings(PanelExeDialog*)));
+
+ // ... and then show it to the user
+ dlg->show();
+}
+
diff --git a/kicker/kicker/buttons/nonkdeappbutton.h b/kicker/kicker/buttons/nonkdeappbutton.h
new file mode 100644
index 000000000..bbb74c892
--- /dev/null
+++ b/kicker/kicker/buttons/nonkdeappbutton.h
@@ -0,0 +1,92 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __nonkdeappbutton_h__
+#define __nonkdeappbutton_h__
+
+// pull in the superclass's definition
+#include "panelbutton.h"
+
+// forward declare this class
+// lets the compiler know it exists without have to know all the gory details
+class PanelExeDialog;
+
+/**
+ * Button that contains a non-KDE application
+ * subclass of PanelButton
+ */
+class NonKDEAppButton : public PanelButton
+{
+ // the Q_OBJECT macro provides the magic glue for signals 'n slots
+ Q_OBJECT
+
+public:
+ // define our two constructors, one used for creating new buttons...
+ NonKDEAppButton(const QString& name, const QString& description,
+ const QString& filePath, const QString& icon,
+ const QString& cmdLine, bool inTerm, QWidget* parent);
+
+ // ... and once for restoring them at start up
+ NonKDEAppButton(const KConfigGroup& config, QWidget* parent);
+
+ // reimplemented from PanelButton
+ virtual void saveConfig(KConfigGroup& config) const;
+ virtual void properties();
+
+protected slots:
+ // called when the button is activated
+ void slotExec();
+
+ // called after the user reconfigures something
+ void updateSettings(PanelExeDialog* dlg);
+
+protected:
+ // used to set up our internal state, either when creating the button
+ // or after reconfiguration
+ void initialize(const QString& name, const QString& description,
+ const QString& filePath, const QString& icon,
+ const QString& cmdLine, bool inTerm);
+
+ // run the command!
+ // the execStr parameter, which default to an empty string,
+ // is used to provide additional command line options aside
+ // from the ones in our config file; for instance a URL drag'd onto us
+ void runCommand(const QString& execStr = QString::null);
+
+ // reimplemented from PanelButton
+ virtual QString tileName() { return "URL"; }
+ QString defaultIcon() const { return "exec"; };
+
+ // handle drag and drop actions
+ virtual void dropEvent(QDropEvent *ev);
+ virtual void dragEnterEvent(QDragEnterEvent *ev);
+
+ QString nameStr; // the name given this button by the user
+ QString descStr; // the description given this button by the user
+ QString pathStr; // the path to the command
+ QString iconStr; // the path to the icon for this button
+ QString cmdStr; // command line flags, if any
+ bool term; // whether to run this in a terminal or not
+}; // all done defining the class!
+
+#endif
diff --git a/kicker/kicker/buttons/servicebutton.cpp b/kicker/kicker/buttons/servicebutton.cpp
new file mode 100644
index 000000000..a5ec7c9a2
--- /dev/null
+++ b/kicker/kicker/buttons/servicebutton.cpp
@@ -0,0 +1,262 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qdragobject.h>
+#include <qtooltip.h>
+
+#include <kdesktopfile.h>
+#include <klocale.h>
+#include <kiconeffect.h>
+#include <kicontheme.h>
+#include <kpropertiesdialog.h>
+#include <krun.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+
+#include "global.h"
+#include "kicker.h"
+
+#include "servicebutton.h"
+#include "servicebutton.moc"
+
+ServiceButton::ServiceButton(const QString& desktopFile, QWidget* parent)
+ : PanelButton(parent, "ServiceButton"),
+ _service(0)
+{
+ loadServiceFromId(desktopFile);
+ initialize();
+}
+
+ServiceButton::ServiceButton(const KService::Ptr &service, QWidget* parent)
+ : PanelButton(parent, "ServiceButton"),
+ _service(service),
+ _id(service->storageId())
+{
+ if (_id.startsWith("/"))
+ {
+ QString tmp = KGlobal::dirs()->relativeLocation("appdata", _id);
+ if (!tmp.startsWith("/"))
+ _id = ":"+tmp;
+ }
+ initialize();
+}
+
+ServiceButton::ServiceButton( const KConfigGroup& config, QWidget* parent )
+ : PanelButton(parent, "ServiceButton"),
+ _service(0)
+{
+ QString id;
+ if (config.hasKey("StorageId"))
+ id = config.readPathEntry("StorageId");
+ else
+ id = config.readPathEntry("DesktopFile");
+ loadServiceFromId(id);
+ initialize();
+}
+
+ServiceButton::~ServiceButton()
+{
+}
+
+void ServiceButton::loadServiceFromId(const QString &id)
+{
+ _id = id;
+ /* this is a KService::Ptr
+ don't need to delete it
+ delete _service;
+ */
+ _service = 0;
+
+ if (_id.startsWith(":"))
+ {
+ _id = locate("appdata", id.mid(1));
+ if (!_id.isEmpty())
+ {
+ KDesktopFile df(_id, true);
+ _service = new KService(&df);
+ }
+ }
+ else
+ {
+ _service = KService::serviceByStorageId(_id);
+ if (_service)
+ {
+ _id = _service->storageId();
+ }
+ }
+
+ if (_service)
+ {
+ backedByFile(_service->desktopEntryPath());
+ }
+
+ if (_id.startsWith("/"))
+ {
+ QString tmp = KGlobal::dirs()->relativeLocation("appdata", _id);
+ if (!tmp.startsWith("/"))
+ _id = ":"+tmp;
+ }
+}
+
+void ServiceButton::initialize()
+{
+ readDesktopFile();
+ connect(this, SIGNAL(clicked()), SLOT(slotExec()));
+}
+
+void ServiceButton::readDesktopFile()
+{
+ if ( !_service || !_service->isValid() )
+ {
+ m_valid = false;
+ return;
+ }
+
+ if (!_service->genericName().isEmpty())
+ {
+ QToolTip::add(this, _service->genericName());
+ }
+ else if (_service->comment().isEmpty())
+ {
+ QToolTip::add(this, _service->name());
+ }
+ else
+ {
+ QToolTip::add(this, _service->name() + " - " + _service->comment());
+ }
+
+ setTitle( _service->name() );
+ setIcon( _service->icon() );
+}
+
+void ServiceButton::saveConfig( KConfigGroup& config ) const
+{
+ config.writePathEntry("StorageId", _id );
+ if (!config.hasKey("DesktopFile") && _service)
+ config.writePathEntry("DesktopFile", _service->desktopEntryPath());
+}
+
+void ServiceButton::dragEnterEvent(QDragEnterEvent *ev)
+{
+ if ((ev->source() != this) && KURLDrag::canDecode(ev))
+ ev->accept(rect());
+ else
+ ev->ignore(rect());
+ PanelButton::dragEnterEvent(ev);
+}
+
+void ServiceButton::dropEvent( QDropEvent* ev )
+{
+ KURL::List uriList;
+ if( KURLDrag::decode( ev, uriList ) && _service ) {
+ kapp->propagateSessionManager();
+ KRun::run( *_service, uriList );
+ }
+ PanelButton::dropEvent(ev);
+}
+
+void ServiceButton::startDrag()
+{
+ QString path = _service->desktopEntryPath();
+
+ // If the path to the desktop file is relative, try to get the full
+ // path from KStdDirs.
+ path = locate("apps", path);
+
+ KURL url;
+ url.setPath(path);
+ emit dragme(KURL::List(url), labelIcon());
+}
+
+void ServiceButton::slotExec()
+{
+ // this allows the button to return to a non-pressed state
+ // before launching
+ QTimer::singleShot(0, this, SLOT(performExec()));
+}
+
+void ServiceButton::performExec()
+{
+ if (!_service) return;
+
+ KURL::List uriList;
+ kapp->propagateSessionManager();
+ KRun::run( *_service, uriList );
+}
+
+void ServiceButton::properties()
+{
+ if (!_service)
+ {
+ return;
+ }
+
+ QString path = _service->desktopEntryPath();
+
+ // If the path to the desktop file is relative, try to get the full
+ // path from KStdDirs.
+ path = locate("apps", path);
+ KURL serviceURL;
+ serviceURL.setPath(path);
+
+ // the KPropertiesDialog deletes itself, so this isn't a memory leak
+ KPropertiesDialog* dialog = new KPropertiesDialog(serviceURL, 0, 0,
+ false, false);
+ dialog->setFileNameReadOnly(true);
+ connect(dialog, SIGNAL(saveAs(const KURL &, KURL &)),
+ this, SLOT(slotSaveAs(const KURL &, KURL &)));
+ connect(dialog, SIGNAL(propertiesClosed()),
+ this, SLOT(slotUpdate()));
+ dialog->show();
+}
+
+void ServiceButton::slotUpdate()
+{
+ loadServiceFromId(_id);
+ readDesktopFile();
+ emit requestSave();
+}
+
+void ServiceButton::slotSaveAs(const KURL &oldUrl, KURL &newUrl)
+{
+ QString oldPath = oldUrl.path();
+ if (locateLocal("appdata", oldUrl.fileName()) != oldPath)
+ {
+ QString path = KickerLib::newDesktopFile(oldUrl);
+ newUrl.setPath(path);
+ _id = path;
+ }
+}
+
+bool ServiceButton::checkForBackingFile()
+{
+ QString id = _id;
+ loadServiceFromId(_id);
+
+ // we need to reset the _id back to whatever it was
+ // so that when we get called again to check on it we
+ // know still know what to be looking for.
+ _id = id;
+
+ return _service != 0;
+}
diff --git a/kicker/kicker/buttons/servicebutton.h b/kicker/kicker/buttons/servicebutton.h
new file mode 100644
index 000000000..26f32791a
--- /dev/null
+++ b/kicker/kicker/buttons/servicebutton.h
@@ -0,0 +1,66 @@
+/*****************************************************************
+
+Copyright (c) 2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __ServiceButton_h__
+#define __ServiceButton_h__
+
+#include "panelbutton.h"
+
+#include <kservice.h>
+
+class ServiceButton : public PanelButton
+{
+ Q_OBJECT
+
+public:
+ ServiceButton( const QString& desktopFile, QWidget* parent );
+ ServiceButton( const KService::Ptr& service, QWidget* parent );
+ ServiceButton( const KConfigGroup& config, QWidget* parent );
+
+ ~ServiceButton();
+
+ virtual void saveConfig(KConfigGroup& config) const;
+ virtual void properties();
+
+protected slots:
+ void slotUpdate();
+ void slotSaveAs(const KURL&, KURL&);
+ void slotExec();
+ void performExec();
+
+protected:
+ void initialize();
+ void loadServiceFromId(const QString &id);
+ void readDesktopFile();
+ virtual QString tileName() { return "URL"; }
+ virtual void startDrag();
+ virtual void dropEvent(QDropEvent *);
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ QString defaultIcon() const { return "exec"; };
+ bool checkForBackingFile();
+
+ KService::Ptr _service;
+ QString _id;
+};
+
+#endif
diff --git a/kicker/kicker/buttons/servicemenubutton.cpp b/kicker/kicker/buttons/servicemenubutton.cpp
new file mode 100644
index 000000000..e3fc41185
--- /dev/null
+++ b/kicker/kicker/buttons/servicemenubutton.cpp
@@ -0,0 +1,96 @@
+/*****************************************************************
+
+Copyright (c) 1996-2002 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+
+#include <kconfig.h>
+#include <kservicegroup.h>
+#include <klocale.h>
+
+#include "service_mnu.h"
+
+#include "servicemenubutton.h"
+#include "servicemenubutton.moc"
+
+ServiceMenuButton::ServiceMenuButton( const QString& relPath, QWidget* parent )
+ : PanelPopupButton( parent, "ServiceMenuButton" )
+ , topMenu( 0 )
+{
+ initialize( relPath );
+}
+
+ServiceMenuButton::ServiceMenuButton( const KConfigGroup& config, QWidget* parent )
+ : PanelPopupButton( parent, "ServiceMenuButton" )
+ , topMenu( 0 )
+{
+ initialize( config.readPathEntry("RelPath") );
+}
+
+void ServiceMenuButton::initialize( const QString& relPath )
+{
+ KServiceGroup::Ptr group = KServiceGroup::group( relPath );
+
+ if (!group || !group->isValid())
+ {
+ m_valid = false;
+ return;
+ }
+
+ QString caption = group->caption();
+ if (caption.isEmpty())
+ {
+ caption = i18n("Applications");
+ }
+
+ QString comment = group->comment();
+ if (comment.isEmpty())
+ {
+ comment = caption;
+ }
+
+ topMenu = new PanelServiceMenu(caption, relPath);
+ setPopup(topMenu);
+ QToolTip::add(this, comment);
+ setTitle(caption);
+ setIcon(group->icon());
+}
+
+void ServiceMenuButton::saveConfig( KConfigGroup& config ) const
+{
+ if (topMenu)
+ config.writePathEntry("RelPath", topMenu->relPath());
+}
+
+void ServiceMenuButton::initPopup()
+{
+ if( !topMenu->initialized() ) {
+ topMenu->reinitialize();
+ }
+}
+
+void ServiceMenuButton::startDrag()
+{
+ KURL url("programs:/" + topMenu->relPath());
+ emit dragme(KURL::List(url), labelIcon());
+}
+
diff --git a/kicker/kicker/buttons/servicemenubutton.h b/kicker/kicker/buttons/servicemenubutton.h
new file mode 100644
index 000000000..1bd9d1885
--- /dev/null
+++ b/kicker/kicker/buttons/servicemenubutton.h
@@ -0,0 +1,54 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __servicemenubutton_h__
+#define __servicemenubutton_h__
+
+#include "panelbutton.h"
+
+class PanelServiceMenu;
+
+/**
+ * Button that contains a Service menu
+ */
+class ServiceMenuButton : public PanelPopupButton
+{
+ Q_OBJECT
+
+public:
+ ServiceMenuButton( const QString& relPath, QWidget* parent );
+ ServiceMenuButton( const KConfigGroup& config, QWidget* parent );
+
+ void saveConfig( KConfigGroup& config ) const;
+
+protected:
+ void initialize( const QString& relPath );
+ virtual QString tileName() { return "Browser"; }
+ virtual QString defaultIcon() const { return "folder"; }
+ virtual void startDrag();
+ virtual void initPopup();
+
+ PanelServiceMenu* topMenu;
+};
+
+#endif
diff --git a/kicker/kicker/buttons/urlbutton.cpp b/kicker/kicker/buttons/urlbutton.cpp
new file mode 100644
index 000000000..007b0cc00
--- /dev/null
+++ b/kicker/kicker/buttons/urlbutton.cpp
@@ -0,0 +1,201 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+#include <qfile.h>
+
+#include <kdesktopfile.h>
+#include <kfileitem.h>
+#include <konq_operations.h>
+#include <kicontheme.h>
+#include <kglobal.h>
+#include <kiconeffect.h>
+#include <kpropertiesdialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <krun.h>
+#include <klocale.h>
+
+#include <kdebug.h>
+
+#include "global.h"
+#include "kicker.h"
+
+#include "urlbutton.h"
+#include "urlbutton.moc"
+
+URLButton::URLButton( const QString& url, QWidget* parent )
+ : PanelButton( parent, "URLButton" )
+ , fileItem( 0 )
+ , pDlg( 0 )
+{
+ initialize( url );
+}
+
+URLButton::URLButton( const KConfigGroup& config, QWidget* parent )
+ : PanelButton( parent, "URLButton" )
+ , fileItem( 0 )
+ , pDlg( 0 )
+{
+ initialize( config.readPathEntry("URL") );
+}
+
+URLButton::~URLButton()
+{
+ delete fileItem;
+}
+
+void URLButton::initialize( const QString& _url )
+{
+ KURL url(_url);
+ if (!url.isLocalFile() || !url.path().endsWith(".desktop"))
+ {
+ QString file = KickerLib::newDesktopFile(url);
+ KDesktopFile df(file);
+ df.writeEntry("Encoding", "UTF-8");
+ df.writeEntry("Type","Link");
+ df.writeEntry("Name", url.prettyURL());
+ if (url.isLocalFile())
+ {
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, url );
+ df.writeEntry("Icon", item.iconName() );
+ }
+ else
+ {
+ df.writeEntry("Icon", KMimeType::favIconForURL(url));
+ }
+ df.writeEntry("URL", url.url());
+ url = KURL();
+ url.setPath(file);
+ }
+ fileItem = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, url );
+ setIcon( fileItem->iconName() );
+ connect( this, SIGNAL(clicked()), SLOT(slotExec()) );
+ setToolTip();
+
+ if (url.isLocalFile())
+ {
+ backedByFile(url.path());
+ }
+}
+
+void URLButton::saveConfig( KConfigGroup& config ) const
+{
+ config.writePathEntry("URL", fileItem->url().prettyURL());
+}
+
+void URLButton::setToolTip()
+{
+ if (fileItem->isLocalFile()
+ && KDesktopFile::isDesktopFile(fileItem->url().path()))
+ {
+ KDesktopFile df(fileItem->url().path());
+
+ if (df.readComment().isEmpty())
+ {
+ QToolTip::add(this, df.readName());
+ }
+ else
+ {
+ QToolTip::add(this, df.readName() + " - " + df.readComment());
+ }
+
+ setTitle(df.readName());
+ }
+ else
+ {
+ QToolTip::add(this, fileItem->url().prettyURL());
+ setTitle(fileItem->url().prettyURL());
+ }
+}
+
+void URLButton::dragEnterEvent(QDragEnterEvent *ev)
+{
+ if ((ev->source() != this) && fileItem->acceptsDrops() && KURLDrag::canDecode(ev))
+ ev->accept(rect());
+ else
+ ev->ignore(rect());
+ PanelButton::dragEnterEvent(ev);
+}
+
+void URLButton::dropEvent(QDropEvent *ev)
+{
+ kapp->propagateSessionManager();
+ KURL::List execList;
+ if(KURLDrag::decode(ev, execList)){
+ KURL url( fileItem->url() );
+ if(!execList.isEmpty()) {
+ if (KDesktopFile::isDesktopFile(url.path())){
+ KApplication::startServiceByDesktopPath(url.path(), execList.toStringList(),
+ 0, 0, 0, "", true);
+ }
+ else // attempt to interpret path as directory
+ {
+ KonqOperations::doDrop( fileItem, url, ev, this );
+ }
+ }
+ }
+ PanelButton::dropEvent(ev);
+}
+
+void URLButton::startDrag()
+{
+ emit dragme(KURL::List(fileItem->url()), labelIcon());
+}
+
+void URLButton::slotExec()
+{
+ kapp->propagateSessionManager();
+ fileItem->run();
+}
+
+void URLButton::updateURL()
+{
+ if (pDlg->kurl() != fileItem->url()) {
+ fileItem->setURL(pDlg->kurl());
+ setIcon(fileItem->iconName());
+ setToolTip();
+ emit requestSave();
+ } else {
+ setIcon(fileItem->iconName());
+ setToolTip();
+ }
+
+ pDlg = 0L;
+}
+
+void URLButton::properties()
+{
+ if ( (fileItem->isLocalFile() && !QFile::exists(fileItem->url().path()) )
+ || !fileItem->url().isValid())
+ {
+ KMessageBox::error( 0L, i18n("The file %1 does not exist")
+ .arg(fileItem->url().prettyURL()) );
+ return;
+ }
+
+ pDlg = new KPropertiesDialog(fileItem, 0L, 0L, false, false); // will delete itself
+ pDlg->setFileNameReadOnly(true);
+ connect(pDlg, SIGNAL(applied()), SLOT(updateURL()));
+ pDlg->show();
+}
diff --git a/kicker/kicker/buttons/urlbutton.h b/kicker/kicker/buttons/urlbutton.h
new file mode 100644
index 000000000..e6f6b12e0
--- /dev/null
+++ b/kicker/kicker/buttons/urlbutton.h
@@ -0,0 +1,65 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __urlbutton_h__
+#define __urlbutton_h__
+
+#include "panelbutton.h"
+
+class KFileItem;
+class KPropertiesDialog;
+
+/**
+ * Simple URL button (files, whatever)
+ */
+class URLButton : public PanelButton
+{
+ Q_OBJECT
+
+public:
+ URLButton( const QString& url, QWidget* parent );
+ URLButton( const KConfigGroup& config, QWidget* parent );
+
+ virtual ~URLButton();
+
+ void saveConfig( KConfigGroup& config ) const;
+
+ virtual void properties();
+
+protected slots:
+ void slotExec();
+ void updateURL();
+
+protected:
+ void initialize( const QString& url );
+ virtual QString tileName() { return "URL"; }
+ virtual void startDrag();
+ virtual void dropEvent(QDropEvent *);
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ void setToolTip();
+
+ KFileItem *fileItem;
+ KPropertiesDialog *pDlg;
+};
+
+#endif
diff --git a/kicker/kicker/buttons/windowlist.desktop b/kicker/kicker/buttons/windowlist.desktop
new file mode 100644
index 000000000..c4b7c9579
--- /dev/null
+++ b/kicker/kicker/buttons/windowlist.desktop
@@ -0,0 +1,130 @@
+[Desktop Entry]
+Name=Window List Menu
+Name[af]=Venster Lys Kieslys
+Name[ar]=قائمة عرض النوافذ
+Name[be]=Меню спіса вокнаў
+Name[bg]=Списък с прозорците
+Name[bn]=উইণ্ডো তালিকা মেনু
+Name[br]=Meuziad listenn ar prenester
+Name[bs]=Meni sa spiskom prozora
+Name[ca]=Menú de la llista de finestres
+Name[cs]=Nabídka seznamu oken
+Name[csb]=Menu z lëstą òknów
+Name[cy]=Dewislen Rhestr Ffenestri
+Name[da]=Vindueslistemenu
+Name[de]=Fensterliste
+Name[el]=Μενού λίστας παραθύρων
+Name[eo]=Fenestrolista Menuo
+Name[es]=Menú de la lista de ventanas
+Name[et]=Akende nimekirja menüü
+Name[eu]=Leiho zerrendaren menua
+Name[fa]=گزینگان فهرست پنجره
+Name[fi]=Ikkunaluettelovalikko
+Name[fr]=Liste des fenêtres
+Name[fy]=Finsterlistmenu
+Name[gl]=Lista de Fiestras
+Name[he]=תפריט רשימת חלונות
+Name[hr]=Izbornik popisa prozora
+Name[hu]=Ablaklista menü
+Name[is]=Gluggalista valmynd
+Name[it]=Menu elenco delle finestre
+Name[ja]=ウィンドウリストメニュー
+Name[ka]=ფანჯრების სიის მენიუ
+Name[kk]=Терезелер тізімінің мәзірі
+Name[km]=ម៉ឺនុយ​បញ្ជី​បង្អួច
+Name[lt]=Langų sąrašo meniu
+Name[mk]=Мени со листа на прозорци
+Name[nb]=Vinduslistemeny
+Name[nds]=Finsterlist
+Name[ne]=सञ्झ्याल सूची मेनु
+Name[nl]=Vensterlijstmenu
+Name[nn]=Vindaugslistemeny
+Name[pa]=ਝਰੋਖਾ ਸੂਚੀ ਮੇਨੂ
+Name[pl]=Menu z listą okien
+Name[pt]=Menu da Lista de Janelas
+Name[pt_BR]=Menu de Lista de Janelas
+Name[ro]=Meniu listă de ferestre
+Name[ru]=Список окон
+Name[rw]=Ibikubiyemo Rutonde by'Idirishya
+Name[se]=Láselistofállu
+Name[sk]=Menu zoznamu okien
+Name[sl]=Meni s seznamom oken
+Name[sr]=Мени листе прозора
+Name[sr@Latn]=Meni liste prozora
+Name[sv]=Fönsterlistmeny
+Name[te]=విండొల జాబితా పట్టి
+Name[tg]=Менюи рӯйхати равзанаҳо
+Name[th]=เมนูแสดงรายการหน้าต่าง
+Name[tr]=Pencere Listeleme Menüsü
+Name[tt]=Täräzä Tezmäse Saylağı
+Name[uk]=Меню списку вікон
+Name[uz]=Oynalar roʻyxati
+Name[uz@cyrillic]=Ойналар рўйхати
+Name[vi]=Thực đơn Liệt kê Cửa sổ
+Name[wa]=Dressêye del djivêye des purneas
+Name[zh_CN]=窗口列表菜单
+Name[zh_TW]=視窗列表選單
+Comment=A menu that lists all open windows
+Comment[af]='n Kieslys wat al die oop vensters vertoon
+Comment[ar]=قائمة لعرض كل النوافذ المفتوحة
+Comment[be]=Меню, якое паказвае усе адкрытыя вокны
+Comment[bg]=Меню-списък, което съдържа всички отворени прозорци
+Comment[bn]=একটি মেনু যা সমস্ত খোলা উইণ্ডো তালিকাবদ্ধ করে
+Comment[bs]=Meni u kojem su navedeni svi trenutno otvoreni prozori
+Comment[ca]=Un menú que llista totes les finestres obertes
+Comment[cs]=Nabídka se seznamem otevřených oken
+Comment[csb]=Menu pòkazëwôjącé wszëstczé otemkłé òkna
+Comment[da]=En menu der lister alle åbne vinduer
+Comment[de]=Dieses Menü zeigt alle geöffneten Fenster an
+Comment[el]=Ένα μενού που εμφανίζει όλα τα ανοικτά παράθυρα
+Comment[eo]=Menuo kiu listigas ĉiujn malfermitajn fenestrojn
+Comment[es]=Un menú que muestra todas las ventanas abiertas
+Comment[et]=Menüü, mis näitab kõiki avatud aknaid
+Comment[eu]=Leiho irekien zerrenda bistaratzen duen menua
+Comment[fa]=گزینگانی که همۀ پنجره‌های باز را فهرست می‌کند
+Comment[fi]=Valikko, jossa on luettelo kaikista avoimista ikkunoista
+Comment[fr]=Un menu affichant l'ensemble des fenêtres ouvertes
+Comment[fy]=In menu mei in list fan alle iepensteande finsters
+Comment[ga]=Roghchlár le gach fuinneog atá oscailte
+Comment[gl]=Un menu que lista todas as fiestras abertas
+Comment[he]=תפריט המציג את רשימת כל החלונות הפתוחים
+Comment[hr]=Izbornik s popisom svih otvorenih prozora
+Comment[hu]=Menü a nyitott ablakok kilistázásához
+Comment[is]=Valmynd sem sýnir alla opna glugga
+Comment[it]=Un menu che mostra tutte le finestre aperte
+Comment[ja]=開いているすべてのウィンドウのリストを表示するメニュー
+Comment[ka]=ყველა გახსნილი ფანჯრის სიის მენიუ
+Comment[kk]=Барлық ашық терезелердің мәзір тізімі
+Comment[km]=ម៉ឺនុយ​ដែល​រាយ​បង្អួច​បើក​ទាំងអស់
+Comment[lt]=Visų atvertų langų sąrašą pateikiantis meniu
+Comment[mk]=Мени што ги листа сите отворени прозорци
+Comment[nb]=En meny som viser alle åpne vinduer
+Comment[nds]=En Menü, dat all apen Finstern oplist
+Comment[ne]=सबै खुला सञ्झ्यालहरू सूचीकृत गर्ने मेनु
+Comment[nl]=Een menu met een lijst van alle geopende vensters
+Comment[nn]=Ein meny som viser alle opne vindauge
+Comment[pa]=ਸਭ ਖੁੱਲੇ ਝਰੋਖਿਆਂ ਦੀ ਸੂਚੀ ਲਈ ਇੱਕ ਮੇਨੂ ਹੈ
+Comment[pl]=Menu pokazujące wszystkie otwarte okna
+Comment[pt]=Um menu que mostra todas as janelas abertas
+Comment[pt_BR]=Um menu que lista todas as janelas abertas
+Comment[ro]=Un meniu ce listează toate ferestrele deschise
+Comment[ru]=Список всех открытых окон
+Comment[rw]=Ibikubiyemo bitanga urutonde w'amadirishya yose afunguye
+Comment[se]=Fállu mas oidnot buot rabas láset
+Comment[sk]=Menu, ktoré zobrazí zoznam okien
+Comment[sl]=Meni, ki prikazuje seznam vseh odprtih oken
+Comment[sr]=Мени који листа све отворене прозоре
+Comment[sr@Latn]=Meni koji lista sve otvorene prozore
+Comment[sv]=En meny som listar alla öppna fönster
+Comment[th]=เมนูที่แสดงรายการหน้าต่างที่เปิดอยู่ทั้งหมด
+Comment[tr]=Bütün Pencereleri listeleyen bir menü
+Comment[tt]=Bar açıq täräzä tezmäse belän saylaq
+Comment[uk]=Меню, яке дає перелік всіх відкритих вікон
+Comment[uz]=Hamma ochiq oynalar roʻyxati
+Comment[uz@cyrillic]=Ҳамма очиқ ойналар рўйхати
+Comment[vi]=Một thực đơn liệt kê tất cả các cửa sổ đang mở
+Comment[wa]=Ene dressêye ki fwait l' djivêye di tos les drovîs purneas
+Comment[zh_CN]=列出打开的全部窗口的菜单
+Comment[zh_TW]=一個列出所有開啟視窗的選單
+Icon=window_list
+X-KDE-Library=WindowListButton
diff --git a/kicker/kicker/buttons/windowlistbutton.cpp b/kicker/kicker/buttons/windowlistbutton.cpp
new file mode 100644
index 000000000..8a60ca5e8
--- /dev/null
+++ b/kicker/kicker/buttons/windowlistbutton.cpp
@@ -0,0 +1,47 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtooltip.h>
+
+#include <kwindowlistmenu.h>
+#include <klocale.h>
+
+#include "windowlistbutton.h"
+#include "windowlistbutton.moc"
+
+WindowListButton::WindowListButton( QWidget* parent )
+ : PanelPopupButton( parent, "WindowListButton" )
+ , topMenu( 0 )
+{
+ topMenu = new KWindowListMenu( this );
+ setPopup(topMenu);
+
+ setTitle(i18n("Window List"));
+ QToolTip::add(this, i18n("Window list"));
+ setIcon("window_list");
+}
+
+void WindowListButton::initPopup()
+{
+ topMenu->init();
+}
diff --git a/kicker/kicker/buttons/windowlistbutton.h b/kicker/kicker/buttons/windowlistbutton.h
new file mode 100644
index 000000000..23dc26c19
--- /dev/null
+++ b/kicker/kicker/buttons/windowlistbutton.h
@@ -0,0 +1,48 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __windowlistbutton_h__
+#define __windowlistbutton_h__
+
+#include "panelbutton.h"
+
+class KWindowListMenu;
+
+/**
+ * Button that contains a windowlist menu
+ */
+class WindowListButton : public PanelPopupButton
+{
+ Q_OBJECT
+
+public:
+ WindowListButton( QWidget* parent );
+
+protected:
+ virtual QString tileName() { return "WindowList"; }
+ virtual void initPopup();
+
+ KWindowListMenu* topMenu;
+};
+
+#endif
diff --git a/kicker/kicker/core/Makefile.am b/kicker/kicker/core/Makefile.am
new file mode 100644
index 000000000..6986af604
--- /dev/null
+++ b/kicker/kicker/core/Makefile.am
@@ -0,0 +1,33 @@
+INCLUDES = -I$(srcdir)/../../libkicker -I../../libkicker \
+ -I$(srcdir)/../ui -I$(srcdir)/../buttons -I$(top_srcdir)/libkonq \
+ $(all_includes)
+
+noinst_LTLIBRARIES = libkicker_core.la
+
+libkicker_core_la_SOURCES = extensionSettings.kcfgc \
+ main.cpp kicker.cpp kicker.skel \
+ userrectsel.cpp containerarea.cpp \
+ applethandle.cpp container_base.cpp container_button.cpp \
+ container_applet.cpp container_extension.cpp extensionmanager.cpp \
+ menumanager.cpp pluginmanager.cpp showdesktop.cpp \
+ unhidetrigger.cpp containerarealayout.cpp \
+ panelextension.cpp panelextension.skel
+
+
+libkicker_core_la_LDFLAGS = $(all_libraries)
+libkicker_core_la_LIBADD = $(top_builddir)/libkonq/libkonq.la $(LIB_KDEUI)
+libkicker_core_la_METASOURCES = AUTO
+libkicker_core_la_COMPILE_FIRST = ../../libkicker/kickerSettings.h
+
+kicker_core_data_DATA = default-apps
+kicker_core_datadir = $(kde_datadir)/kicker
+
+lnkdir = $(kde_datadir)/kicker/extensions
+lnk_DATA = childpanelextension.desktop
+
+kicker.lo: ../../libkicker/kickerSettings.h
+showdesktop.lo: ../../libkicker/kickerSettings.h
+container_applet.lo: ../../libkicker/kickerSettings.h
+containerarea.lo: ../../libkicker/kickerSettings.h
+container_extension.lo: ../../libkicker/kickerSettings.h
+
diff --git a/kicker/kicker/core/applethandle.cpp b/kicker/kicker/core/applethandle.cpp
new file mode 100644
index 000000000..cd9de3c62
--- /dev/null
+++ b/kicker/kicker/core/applethandle.cpp
@@ -0,0 +1,402 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qcursor.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qpixmapcache.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <qimage.h>
+
+#include <kpushbutton.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "global.h"
+#include "container_applet.h"
+#include "kickerSettings.h"
+
+#include "applethandle.h"
+
+AppletHandle::AppletHandle(AppletContainer* parent)
+ : QWidget(parent),
+ m_applet(parent),
+ m_menuButton(0),
+ m_drawHandle(false),
+ m_popupDirection(KPanelApplet::Up),
+ m_handleHoverTimer(0)
+{
+ setBackgroundOrigin(AncestorOrigin);
+ setMinimumSize(widthForHeight(0), heightForWidth(0));
+ m_layout = new QBoxLayout(this, QBoxLayout::BottomToTop, 0, 0);
+
+ m_dragBar = new AppletHandleDrag(this);
+ m_dragBar->installEventFilter(this);
+ m_layout->addWidget(m_dragBar);
+
+ if (kapp->authorizeKAction("kicker_rmb"))
+ {
+ m_menuButton = new AppletHandleButton( this );
+ m_menuButton->installEventFilter(this);
+ m_layout->addWidget(m_menuButton);
+
+ connect(m_menuButton, SIGNAL(pressed()),
+ this, SLOT(menuButtonPressed()));
+ QToolTip::add(m_menuButton, i18n("%1 menu").arg(parent->info().name()));
+ }
+
+ QToolTip::add(this, i18n("%1 applet handle").arg(parent->info().name()));
+ resetLayout();
+}
+
+int AppletHandle::heightForWidth( int /* w */ ) const
+{
+ int size = style().pixelMetric(QStyle::PM_DockWindowHandleExtent, this);
+
+ return size;
+}
+
+int AppletHandle::widthForHeight( int /* h */ ) const
+{
+ int size = style().pixelMetric(QStyle::PM_DockWindowHandleExtent, this);
+
+ return size;
+}
+
+void AppletHandle::setPopupDirection(KPanelApplet::Direction d)
+{
+ Qt::ArrowType a = Qt::UpArrow;
+
+ if (d == m_popupDirection || !m_menuButton)
+ {
+ return;
+ }
+
+ m_popupDirection = d;
+
+ switch (m_popupDirection)
+ {
+ case KPanelApplet::Up:
+ m_layout->setDirection(QBoxLayout::BottomToTop);
+ a = Qt::UpArrow;
+ break;
+ case KPanelApplet::Down:
+ m_layout->setDirection(QBoxLayout::TopToBottom);
+ a = Qt::DownArrow;
+ break;
+ case KPanelApplet::Left:
+ m_layout->setDirection(QBoxLayout::RightToLeft);
+ a = Qt::LeftArrow;
+ break;
+ case KPanelApplet::Right:
+ m_layout->setDirection(QBoxLayout::LeftToRight);
+ a = Qt::RightArrow;
+ break;
+ }
+
+ m_menuButton->setArrowType(a);
+ m_layout->activate();
+}
+
+void AppletHandle::resetLayout()
+{
+ if (m_handleHoverTimer && !m_drawHandle)
+ {
+ m_dragBar->hide();
+
+ if (m_menuButton)
+ {
+ m_menuButton->hide();
+ }
+ }
+ else
+ {
+ m_dragBar->show();
+
+ if (m_menuButton)
+ {
+ m_menuButton->show();
+ }
+ }
+}
+
+void AppletHandle::setFadeOutHandle(bool fadeOut)
+{
+ if (fadeOut)
+ {
+ if (!m_handleHoverTimer)
+ {
+ m_handleHoverTimer = new QTimer(this);
+ connect(m_handleHoverTimer, SIGNAL(timeout()),
+ this, SLOT(checkHandleHover()));
+ m_applet->installEventFilter(this);
+ }
+ }
+ else
+ {
+ delete m_handleHoverTimer;
+ m_handleHoverTimer = 0;
+ m_applet->removeEventFilter(this);
+ }
+
+ resetLayout();
+}
+
+bool AppletHandle::eventFilter(QObject *o, QEvent *e)
+{
+ if (o == parent())
+ {
+ switch (e->type())
+ {
+ case QEvent::Enter:
+ {
+ m_drawHandle = true;
+ resetLayout();
+
+ if (m_handleHoverTimer)
+ {
+ m_handleHoverTimer->start(250);
+ }
+ break;
+ }
+
+ case QEvent::Leave:
+ {
+ if (m_menuButton && m_menuButton->isOn())
+ {
+ break;
+ }
+
+ QWidget* w = dynamic_cast<QWidget*>(o);
+
+ bool nowDrawIt = false;
+ if (w)
+ {
+ // a hack for applets that have out-of-process
+ // elements (e.g the systray) so that the handle
+ // doesn't flicker when moving over those elements
+ if (w->rect().contains(w->mapFromGlobal(QCursor::pos())))
+ {
+ nowDrawIt = true;
+ }
+ }
+
+ if (nowDrawIt != m_drawHandle)
+ {
+ if (m_handleHoverTimer)
+ {
+ m_handleHoverTimer->stop();
+ }
+
+ m_drawHandle = nowDrawIt;
+ resetLayout();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return QWidget::eventFilter( o, e );
+ }
+ else if (o == m_dragBar)
+ {
+ if (e->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent* ev = static_cast<QMouseEvent*>(e);
+ if (ev->button() == LeftButton || ev->button() == MidButton)
+ {
+ emit moveApplet(m_applet->mapFromGlobal(ev->globalPos()));
+ }
+ }
+ }
+
+ if (m_menuButton && e->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent* ev = static_cast<QMouseEvent*>(e);
+ if (ev->button() == RightButton)
+ {
+ if (!m_menuButton->isDown())
+ {
+ m_menuButton->setDown(true);
+ menuButtonPressed();
+ }
+
+ return true;
+ }
+ }
+
+ return QWidget::eventFilter(o, e); // standard event processing
+}
+
+void AppletHandle::menuButtonPressed()
+{
+ if (!kapp->authorizeKAction("kicker_rmb"))
+ {
+ return;
+ }
+
+ emit showAppletMenu();
+
+ if (!onMenuButton(QCursor::pos()))
+ {
+ toggleMenuButtonOff();
+ }
+}
+
+void AppletHandle::checkHandleHover()
+{
+ if (!m_handleHoverTimer ||
+ (m_menuButton && m_menuButton->isOn()) ||
+ m_applet->geometry().contains(m_applet->mapToParent(
+ m_applet->mapFromGlobal(QCursor::pos()))))
+ {
+ return;
+ }
+
+ m_handleHoverTimer->stop();
+ m_drawHandle = false;
+ resetLayout();
+}
+
+bool AppletHandle::onMenuButton(const QPoint& point) const
+{
+ return m_menuButton && (childAt(mapFromGlobal(point)) == m_menuButton);
+}
+
+void AppletHandle::toggleMenuButtonOff()
+{
+ if (!m_menuButton)
+ {
+ return;
+ }
+
+ m_menuButton->setDown(false);
+}
+
+AppletHandleDrag::AppletHandleDrag(AppletHandle* parent)
+ : QWidget(parent),
+ m_parent(parent),
+ m_inside(false)
+{
+ setBackgroundOrigin( AncestorOrigin );
+}
+
+QSize AppletHandleDrag::minimumSizeHint() const
+{
+ int wh = style().pixelMetric(QStyle::PM_DockWindowHandleExtent, this);
+
+ if (m_parent->orientation() == Horizontal)
+ {
+ return QSize(wh, 0);
+ }
+
+ return QSize(0, wh);
+}
+
+QSizePolicy AppletHandleDrag::sizePolicy() const
+{
+ if (m_parent->orientation() == Horizontal)
+ {
+ return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred );
+ }
+
+ return QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
+}
+
+void AppletHandleDrag::enterEvent( QEvent *e )
+{
+ m_inside = true;
+ QWidget::enterEvent( e );
+ update();
+}
+
+void AppletHandleDrag::leaveEvent( QEvent *e )
+{
+ m_inside = false;
+ QWidget::enterEvent( e );
+ update();
+}
+
+void AppletHandleDrag::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+
+ if (!KickerSettings::transparent())
+ {
+ if (paletteBackgroundPixmap())
+ {
+ QPoint offset = backgroundOffset();
+ int ox = offset.x();
+ int oy = offset.y();
+ p.drawTiledPixmap( 0, 0, width(), height(),*paletteBackgroundPixmap(), ox, oy);
+ }
+
+ QStyle::SFlags flags = QStyle::Style_Default;
+ flags |= QStyle::Style_Enabled;
+ if (m_parent->orientation() == Horizontal)
+ {
+ flags |= QStyle::Style_Horizontal;
+ }
+
+ QRect r = rect();
+
+ style().drawPrimitive(QStyle::PE_DockWindowHandle, &p, r,
+ colorGroup(), flags);
+ }
+ else
+ {
+ KickerLib::drawBlendedRect(&p, QRect(0, 0, width(), height()), paletteForegroundColor(), m_inside ? 0x40 : 0x20);
+ }
+}
+
+AppletHandleButton::AppletHandleButton(AppletHandle *parent)
+ : SimpleArrowButton(parent),
+ m_parent(parent)
+{
+}
+
+QSize AppletHandleButton::minimumSizeHint() const
+{
+ int height = style().pixelMetric(QStyle::PM_DockWindowHandleExtent, this);
+ int width = height;
+
+ if (m_parent->orientation() == Horizontal)
+ {
+ return QSize(width, height);
+ }
+
+ return QSize(height, width);
+}
+
+QSizePolicy AppletHandleButton::sizePolicy() const
+{
+ return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+}
+
+#include "applethandle.moc"
diff --git a/kicker/kicker/core/applethandle.h b/kicker/kicker/core/applethandle.h
new file mode 100644
index 000000000..2158756cb
--- /dev/null
+++ b/kicker/kicker/core/applethandle.h
@@ -0,0 +1,126 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __applethandle_h__
+#define __applethandle_h__
+
+#include <qwidget.h>
+#include <qpushbutton.h>
+
+#include "container_applet.h"
+#include "simplebutton.h"
+
+class QBoxLayout;
+class QTimer;
+class AppletHandleDrag;
+class AppletHandleButton;
+
+class AppletHandle : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ AppletHandle(AppletContainer* parent);
+
+ void resetLayout();
+ void setFadeOutHandle(bool);
+
+ bool eventFilter (QObject *, QEvent *);
+
+ int widthForHeight( int h ) const;
+ int heightForWidth( int w ) const;
+
+ void setPopupDirection(KPanelApplet::Direction);
+ KPanelApplet::Direction popupDirection() const
+ {
+ return m_popupDirection;
+ }
+
+ KPanelApplet::Orientation orientation() const
+ {
+ return m_applet->orientation();
+ }
+
+ bool onMenuButton(const QPoint& point) const;
+
+ signals:
+ void moveApplet( const QPoint& moveOffset );
+ void showAppletMenu();
+
+ public slots:
+ void toggleMenuButtonOff();
+
+ protected slots:
+ void menuButtonPressed();
+ void checkHandleHover();
+
+ private:
+ AppletContainer* m_applet;
+ QBoxLayout* m_layout;
+ AppletHandleDrag* m_dragBar;
+ AppletHandleButton* m_menuButton;
+ bool m_drawHandle;
+ KPanelApplet::Direction m_popupDirection;
+ QTimer* m_handleHoverTimer;
+ bool m_inside;
+};
+
+class AppletHandleDrag : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ AppletHandleDrag(AppletHandle* parent);
+
+ QSize minimumSizeHint() const;
+ QSize minimumSize() const { return minimumSizeHint(); }
+ QSize sizeHint() const { return minimumSize(); }
+ QSizePolicy sizePolicy() const;
+
+ protected:
+ void paintEvent( QPaintEvent* );
+ void enterEvent( QEvent* );
+ void leaveEvent( QEvent* );
+ const AppletHandle* m_parent;
+
+ private:
+ bool m_inside;
+};
+
+class AppletHandleButton : public SimpleArrowButton
+{
+ Q_OBJECT
+
+ public:
+ AppletHandleButton(AppletHandle *parent);
+ QSize minimumSizeHint() const;
+ QSize minimumSize() const { return minimumSizeHint(); }
+ QSize sizeHint() const { return minimumSize(); }
+ QSizePolicy sizePolicy() const;
+
+ private:
+ bool m_moveMouse;
+ const AppletHandle* m_parent;
+};
+
+#endif
diff --git a/kicker/kicker/core/childpanelextension.desktop b/kicker/kicker/core/childpanelextension.desktop
new file mode 100644
index 000000000..edad98d50
--- /dev/null
+++ b/kicker/kicker/core/childpanelextension.desktop
@@ -0,0 +1,145 @@
+[Desktop Entry]
+Name=Panel
+Name[af]=Paneel
+Name[ar]=اللوح
+Name[be]=Панэль
+Name[bg]=Системен панел
+Name[bn]=প্যানেল
+Name[br]=Panell
+Name[ca]=Plafó
+Name[de]=Kontrollleiste
+Name[el]=Πίνακας
+Name[eo]=Panelo
+Name[et]=Paneel
+Name[eu]=Panela
+Name[fa]=تابلو
+Name[fi]=Paneeli
+Name[fo]=Bróst
+Name[fr]=Tableau de bord
+Name[fy]=Paniel
+Name[ga]=Painéal
+Name[gl]=Painel
+Name[he]=לוח
+Name[hi]=फलक
+Name[hr]=Ploča
+Name[is]=Spjald
+Name[it]=Pannello
+Name[ja]=パネル
+Name[ka]=პანელი
+Name[kk]=Панель
+Name[km]=បន្ទះ
+Name[ko]=패널
+Name[lo]=ถาดพาเนล
+Name[lt]=Pultas
+Name[lv]=Panelis
+Name[mk]=Панел
+Name[nds]=Paneel
+Name[ne]=प्यानल
+Name[nl]=Paneel
+Name[oc]=Panèu de contròle
+Name[pa]=ਪੈਨਲ
+Name[pt]=Painel
+Name[pt_BR]=Painel
+Name[ro]=Panou
+Name[ru]=Панель
+Name[rw]=Umwanya
+Name[se]=Panela
+Name[sl]=Pult
+Name[sr]=Панел
+Name[ta]=பலகம்
+Name[te]=పెనల్
+Name[tg]=Панел
+Name[th]=พาเนล
+Name[tt]=Tirä
+Name[uk]=Панель
+Name[uz@cyrillic]=Панел
+Name[ven]=Phanele
+Name[vi]=Bảng điều khiển
+Name[wa]=Scriftôr
+Name[xh]=Iqela lenjongo ethile
+Name[zh_CN]=面板
+Name[zh_TW]=面板
+Name[zu]=Iwindi lemininingwane
+Comment=Child panel extension.
+Comment[af]=Kind paneel uitbreiding.
+Comment[ar]=إمتداد لوح المهام الإبن.
+Comment[az]=Törəmə panel uzantısı.
+Comment[be]=Пашырэнне дадатковай панэлі.
+Comment[bg]=Разширение на системния панел
+Comment[bn]=চাইল্ড প্যানেল এক্সটেনশন
+Comment[bs]=Proširenje osnovnog panela.
+Comment[ca]=Una extensió del plafó petitet.
+Comment[cs]=Rozšíření závislého panelu.
+Comment[csb]=Rozszérzenié òtrokòwégò panelu.
+Comment[cy]=Estyniad panel plentyn
+Comment[da]=Udvidelse med underpanel.
+Comment[de]=Abhängige Kontrollleiste
+Comment[el]=Επέκταση θυγατρικού πίνακα.
+Comment[eo]=Ido-panelaldono.
+Comment[es]=Extensión Panel hijo.
+Comment[et]=Paneeli laiendus alampaneelide loomiseks
+Comment[eu]=Panel semearen hedapena
+Comment[fa]=پسوند تابلوی فرزند.
+Comment[fi]=Lapsipaaneelilaajennus
+Comment[fr]=Extension du tableau de bord
+Comment[fy]=Dochterpanielekstinsje
+Comment[gl]=Extensión de painel fillo.
+Comment[he]=הרחבת לוח צאצא.
+Comment[hi]=शिशु फलक विस्तार.
+Comment[hr]=Proširenje za dodatnu ploču
+Comment[hu]=Gyermek-panel.
+Comment[is]=Útvíkkun undirspjalds.
+Comment[it]=Estensione del pannello
+Comment[ja]=子パネル拡張
+Comment[ka]=შვილეული პანელის გაფართოვება
+Comment[kk]=Еншілес панель.
+Comment[km]=ផ្នែក​បន្ថែម​បន្ទះ​កូន ។
+Comment[lo]=ສ່ວນຂະຫຍາຍພາເນລລູກ
+Comment[lt]=Priklausomo pulto išplėtimas.
+Comment[lv]=Palīg paneļa paplašinājums.
+Comment[mk]=Екстензија - дете панел.
+Comment[mn]=Хүү удирдах самбарын өргөтгөл
+Comment[ms]=Lanjutan panel anak.
+Comment[mt]=Estensjoni sotto-pannell.
+Comment[nb]=Barnepanelutvidelse
+Comment[nds]=Verwiedern för en ünnerornt Paneel.
+Comment[ne]=शाखा प्यानल विस्तार
+Comment[nl]=Dochterpaneelextensie.
+Comment[nn]=Barnepanelutviding
+Comment[nso]=Koketso ya Panel ya Ngwana
+Comment[pa]=ਅੱਗੇ ਪੈਨਲ ਵਧਾਰਾ ਹੈ।
+Comment[pl]=Rozszerzenie panelu potomnego.
+Comment[pt]=Extensão painel filho.
+Comment[pt_BR]=Extensão de painel-filho.
+Comment[ro]=Extensie panou fiu.
+Comment[ru]=Расширение дочерней панели
+Comment[rw]=Umugereka w'umwanya mwana.
+Comment[se]=Vuollepanela viiddádus
+Comment[sk]=Rozšírenie pre potomkov panelu.
+Comment[sl]=Razširitev za podrejeni pult.
+Comment[sr]=Дечји панел, проширење панела.
+Comment[sr@Latn]=Dečji panel, proširenje panela.
+Comment[sv]=Underpanelutbyggnad
+Comment[ta]=சிறுவர் பலக விரிவாக்கம்.
+Comment[tg]=Басти сафҳаи контроли кӯдак
+Comment[th]=ส่วนขยายพาเนลลูก
+Comment[tr]=Çocuk Panel uzantısı.
+Comment[tt]=Bala taqta östämäse.
+Comment[uk]=Розширення панелі-нащадка.
+Comment[uz]=Ikkilamchi panel kengaytmasi
+Comment[uz@cyrillic]=Иккиламчи панел кенгайтмаси
+Comment[ven]=Thumanyo ya phanele ya nwana
+Comment[vi]=Các bảng điều khiển con mở rộng
+Comment[wa]=Module do scriftôr
+Comment[xh]=Ulwandiso lweqela lenjongo ethile yomntwana.
+Comment[zh_CN]=子面板扩展。
+Comment[zh_TW]=子面板延伸。
+Comment[zu]=Isandiso sewindi lemininingwane elingumntwana.
+
+Icon=kicker
+X-KDE-Library=childpanel_panelextension
+X-KDE-PanelExt-Resizeable=true
+X-KDE-PanelExt-StdSizes=true
+X-KDE-PanelExt-CustomSizeMin=24
+X-KDE-PanelExt-CustomSizeMax=300
+X-KDE-PanelExt-CustomSizeDefault=58
diff --git a/kicker/kicker/core/container_applet.cpp b/kicker/kicker/core/container_applet.cpp
new file mode 100644
index 000000000..390b934d3
--- /dev/null
+++ b/kicker/kicker/core/container_applet.cpp
@@ -0,0 +1,478 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qcursor.h>
+#include <qxembed.h>
+#include <qframe.h>
+#include <qlayout.h>
+#include <qhbox.h>
+#include <qfile.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpanelapplet.h>
+#include <kpopupmenu.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+
+#include "applethandle.h"
+#include "appletinfo.h"
+#include "appletop_mnu.h"
+#include "containerarea.h"
+#include "global.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "pluginmanager.h"
+
+#include "container_applet.h"
+#include "container_applet.moc"
+
+#define APPLET_MARGIN 1
+
+AppletContainer::AppletContainer(const AppletInfo& info,
+ QPopupMenu* opMenu,
+ bool immutable,
+ QWidget* parent )
+ : BaseContainer(opMenu,
+ parent,
+ QString(info.library() + "container").latin1()),
+ _info(info),
+ _handle(0),
+ _layout(0),
+ _type(KPanelApplet::Normal),
+ _widthForHeightHint(0),
+ _heightForWidthHint(0),
+ _firstuse(true)
+{
+ setBackgroundOrigin(AncestorOrigin);
+
+ //setup appletframe
+ _appletframe = new QHBox(this);
+ _appletframe->setBackgroundOrigin( AncestorOrigin );
+ _appletframe->setFrameStyle(QFrame::NoFrame);
+ _appletframe->installEventFilter(this);
+
+ if (orientation() == Horizontal)
+ {
+ _layout = new QBoxLayout(this, QBoxLayout::LeftToRight, 0, 0);
+ }
+ else
+ {
+ _layout = new QBoxLayout(this, QBoxLayout::TopToBottom, 0, 0);
+ }
+
+ _layout->setResizeMode( QLayout::FreeResize );
+
+ _layout->addSpacing(APPLET_MARGIN);
+ _handle = new AppletHandle(this);
+ _layout->addWidget(_handle, 0);
+ connect(_handle, SIGNAL(moveApplet(const QPoint&)),
+ this, SLOT(moveApplet(const QPoint&)));
+ connect(_handle, SIGNAL(showAppletMenu()), this, SLOT(showAppletMenu()));
+
+ _layout->addWidget(_appletframe, 1);
+ _layout->activate();
+
+ _deskFile = info.desktopFile();
+ _configFile = info.configFile();
+ _applet = PluginManager::the()->loadApplet( info, _appletframe );
+
+ if (!_applet)
+ {
+ _valid = false;
+ KMessageBox::error(this,
+ i18n("The %1 applet could not be loaded. Please check your installation.")
+ .arg(info.name().isEmpty() ? _deskFile : info.name()),
+ i18n("Applet Loading Error"));
+ return;
+ }
+
+ _valid = true;
+
+ _applet->setPosition((KPanelApplet::Position)KickerLib::directionToPosition(popupDirection()));
+ _applet->setAlignment((KPanelApplet::Alignment)alignment());
+
+ _actions = _applet->actions();
+ _type = _applet->type();
+
+ setImmutable(immutable);
+
+ connect(_applet, SIGNAL(updateLayout()), SLOT(slotUpdateLayout()));
+ connect(_applet, SIGNAL(requestFocus()), SLOT(activateWindow()));
+ connect(_applet, SIGNAL(requestFocus(bool)), SLOT(focusRequested(bool)));
+
+ connect(Kicker::the(), SIGNAL(configurationChanged()),
+ this, SLOT(slotReconfigure()));
+}
+
+void AppletContainer::configure()
+{
+ _handle->setPopupDirection(popupDirection());
+ _handle->setFadeOutHandle(KickerSettings::fadeOutAppletHandles());
+
+ if (isImmutable() ||
+ KickerSettings::hideAppletHandles() ||
+ !kapp->authorizeKAction("kicker_rmb"))
+ {
+ if (_handle->isVisibleTo(this))
+ {
+ _handle->hide();
+ setBackground();
+ }
+ }
+ else if (!_handle->isVisibleTo(this))
+ {
+ _handle->show();
+ setBackground();
+ }
+}
+
+void AppletContainer::slotReconfigure()
+{
+ configure();
+}
+
+void AppletContainer::setPopupDirection(KPanelApplet::Direction d)
+{
+ if (!_firstuse && _dir == d)
+ {
+ return;
+ }
+
+ _firstuse = false;
+
+ BaseContainer::setPopupDirection(d);
+ _handle->setPopupDirection(d);
+ resetLayout();
+
+ if (_applet)
+ {
+ _applet->setPosition((KPanelApplet::Position)KickerLib::directionToPosition(d));
+ }
+}
+
+void AppletContainer::setOrientation(KPanelExtension::Orientation o)
+{
+ if (_orient == o) return;
+
+ BaseContainer::setOrientation(o);
+ setBackground();
+ resetLayout();
+}
+
+void AppletContainer::resetLayout()
+{
+ _handle->resetLayout();
+
+ if (orientation() == Horizontal)
+ {
+ _layout->setDirection( QBoxLayout::LeftToRight );
+ }
+ else
+ {
+ _layout->setDirection( QBoxLayout::TopToBottom );
+ }
+
+ _layout->activate();
+}
+
+void AppletContainer::moveApplet( const QPoint& moveOffset )
+{
+ _moveOffset = moveOffset;
+ emit moveme(this);
+}
+
+void AppletContainer::signalToBeRemoved()
+{
+ emit removeme(this);
+}
+
+void AppletContainer::showAppletMenu()
+{
+ if (!kapp->authorizeKAction("kicker_rmb"))
+ {
+ return;
+ }
+
+ QPopupMenu *menu = opMenu();
+
+ Kicker::the()->setInsertionPoint(_handle->mapToGlobal(_handle->rect().center()));
+
+ switch(menu->exec(KickerLib::popupPosition(popupDirection(), menu, _handle)))
+ {
+ case PanelAppletOpMenu::Move:
+ moveApplet(_handle->mapToParent(_handle->rect().center()));
+ break;
+ case PanelAppletOpMenu::Remove:
+ Kicker::the()->setInsertionPoint(QPoint());
+ emit removeme(this);
+ return; // Above signal will cause this to be deleted.
+ break;
+ case PanelAppletOpMenu::Help:
+ help();
+ break;
+ case PanelAppletOpMenu::About:
+ about();
+ break;
+ case PanelAppletOpMenu::Preferences:
+ preferences();
+ break;
+ case PanelAppletOpMenu::ReportBug:
+ reportBug();
+ break;
+ default:
+ break;
+ }
+
+ Kicker::the()->setInsertionPoint(QPoint());
+ clearOpMenu();
+}
+
+void AppletContainer::slotRemoved(KConfig* config)
+{
+ BaseContainer::slotRemoved(config);
+
+ // we must delete the applet first since it may write out a config file
+ // in its dtor which can foil out plans to remove it's config file below
+ delete _applet;
+ _applet = 0;
+
+ if (_configFile.isEmpty() ||
+ _info.isUniqueApplet())
+ {
+ return;
+ }
+
+ QFile::remove(locateLocal("config", _configFile));
+}
+
+void AppletContainer::activateWindow()
+{
+ KWin::forceActiveWindow(topLevelWidget()->winId());
+}
+
+void AppletContainer::focusRequested(bool focus)
+{
+ if (focus)
+ {
+ KWin::forceActiveWindow(topLevelWidget()->winId());
+ }
+
+ emit maintainFocus(focus);
+}
+
+void AppletContainer::doLoadConfiguration( KConfigGroup& config )
+{
+ setWidthForHeightHint(config.readNumEntry("WidthForHeightHint", 0));
+ setHeightForWidthHint(config.readNumEntry("HeightForWidthHint", 0));
+}
+
+void AppletContainer::doSaveConfiguration( KConfigGroup& config,
+ bool layoutOnly ) const
+{
+ // immutability is checked by ContainerBase
+ if (orientation() == Horizontal)
+ {
+ config.writeEntry( "WidthForHeightHint", widthForHeight(height()) );
+ }
+ else
+ {
+ config.writeEntry( "HeightForWidthHint", heightForWidth(width()) );
+ }
+
+ if (!layoutOnly)
+ {
+ config.writePathEntry( "ConfigFile", _configFile );
+ config.writePathEntry( "DesktopFile", _deskFile );
+ }
+}
+
+QPopupMenu* AppletContainer::createOpMenu()
+{
+ QPopupMenu* opMenu = new PanelAppletOpMenu(_actions, appletOpMenu(),
+ appletsOwnMenu(),
+ _info.name(), _info.icon(),
+ this);
+
+ connect(opMenu, SIGNAL(escapePressed()),
+ _handle, SLOT(toggleMenuButtonOff()));
+
+ return opMenu;
+}
+
+void AppletContainer::slotRemoveApplet()
+{
+ emit removeme(this);
+}
+
+void AppletContainer::slotUpdateLayout()
+{
+ updateGeometry();
+ emit updateLayout();
+}
+
+
+const QPopupMenu* AppletContainer::appletsOwnMenu() const
+{
+ if (!_applet)
+ {
+ return 0;
+ }
+
+ return _applet->customMenu();
+}
+
+void AppletContainer::slotDelayedDestruct()
+{
+ delete this;
+}
+
+void AppletContainer::alignmentChange(KPanelExtension::Alignment a)
+{
+ if (!_applet)
+ {
+ return;
+ }
+
+ _applet->setAlignment( (KPanelApplet::Alignment)a );
+}
+
+int AppletContainer::widthForHeight(int h) const
+{
+ int handleSize = (_handle->isVisibleTo(const_cast<AppletContainer*>(this))?
+ _handle->widthForHeight(h) : 0);
+
+ if (!_applet)
+ {
+ if (_widthForHeightHint > 0)
+ {
+ return _widthForHeightHint + handleSize;
+ }
+ else
+ {
+ return h + handleSize;
+ }
+ }
+
+ return _applet->widthForHeight(h) + handleSize + APPLET_MARGIN;
+}
+
+int AppletContainer::heightForWidth(int w) const
+{
+ int handleSize = (_handle->isVisibleTo(const_cast<AppletContainer*>(this))?
+ _handle->heightForWidth(w) : 0);
+
+ if (!_applet)
+ {
+ if (_heightForWidthHint > 0)
+ {
+ return _heightForWidthHint + handleSize;
+ }
+ else
+ {
+ return w + handleSize;
+ }
+ }
+
+ return _applet->heightForWidth(w) + handleSize + APPLET_MARGIN;
+}
+
+void AppletContainer::about()
+{
+ if (!_applet) return;
+ _applet->action( KPanelApplet::About );
+}
+
+void AppletContainer::help()
+{
+ if (!_applet) return;
+ _applet->action( KPanelApplet::Help );
+}
+
+void AppletContainer::preferences()
+{
+ if (!_applet) return;
+ _applet->action( KPanelApplet::Preferences );
+}
+
+void AppletContainer::reportBug()
+{
+ if (!_applet) return;
+ _applet->action( KPanelApplet::ReportBug );
+}
+
+void AppletContainer::setBackground()
+{
+ // can happen in perverse moments when an applet isn't loaded but the contanier
+ // get's asked to update it's bground anyways
+ if (!_applet)
+ {
+ return;
+ }
+
+ _applet->unsetPalette();
+ _handle->unsetPalette();
+
+ setBackgroundOrigin(AncestorOrigin);
+ _applet->update();
+ _handle->update();
+
+ if (KickerSettings::transparent())
+ {
+ // Trick to tell applets that they must refresh their transparent background if they need.
+ QMoveEvent e(_applet->pos(), _applet->pos());
+ QApplication::sendEvent(_applet, &e);
+ }
+}
+
+void AppletContainer::setImmutable(bool immutable)
+{
+ // The menu applet must be kept immutable
+ if (_deskFile == "menuapplet.desktop" && !immutable)
+ return;
+
+ BaseContainer::setImmutable(immutable);
+ if (isImmutable() ||
+ KickerSettings::hideAppletHandles() ||
+ !kapp->authorizeKAction("kicker_rmb"))
+ {
+ if (_handle->isVisibleTo(this))
+ {
+ _handle->hide();
+ setBackground();
+ }
+ }
+ else if (!_handle->isVisibleTo(this))
+ {
+ QToolTip::add(_handle, _info.name());
+ _handle->show();
+ setBackground();
+ }
+}
diff --git a/kicker/kicker/core/container_applet.h b/kicker/kicker/core/container_applet.h
new file mode 100644
index 000000000..8c364c09f
--- /dev/null
+++ b/kicker/kicker/core/container_applet.h
@@ -0,0 +1,113 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __container_applet_h__
+#define __container_applet_h__
+
+#include <kpanelapplet.h>
+#include <dcopobject.h>
+#include <kwin.h>
+
+#include "appletinfo.h"
+#include "container_base.h"
+
+class QHBox;
+class QXEmbed;
+class QBoxLayout;
+class KConfig;
+
+class AppletHandle;
+
+class AppletContainer : public BaseContainer
+{
+ Q_OBJECT
+
+public:
+ AppletContainer(const AppletInfo& info, QPopupMenu* opMenu, bool isImmutable = false, QWidget* parent = 0);
+
+ KPanelApplet::Type type() const { return _type; }
+ const AppletInfo& info() const { return _info; }
+ const QPopupMenu* appletsOwnMenu() const;
+ bool isStretch() const { return type() == KPanelApplet::Stretch; }
+ void resetLayout();
+
+ virtual void configure();
+ virtual void about();
+ virtual void help();
+ virtual void preferences();
+ virtual void reportBug();
+ virtual void setBackground();
+ virtual bool isValid() const { return _valid; }
+ virtual QString appletType() const { return "Applet"; }
+ virtual QString icon() const { return _info.icon(); }
+ virtual QString visibleName() const { return _info.name(); }
+
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+
+ void setWidthForHeightHint(int w) { _widthForHeightHint = w; }
+ void setHeightForWidthHint(int h) { _heightForWidthHint = h; }
+
+signals:
+ void updateLayout();
+
+public slots:
+ virtual void slotRemoved(KConfig* config);
+ virtual void setPopupDirection(KPanelApplet::Direction d);
+ virtual void setOrientation(KPanelExtension::Orientation o);
+ virtual void setImmutable(bool immutable);
+ void moveApplet( const QPoint& moveOffset );
+ void showAppletMenu();
+ void slotReconfigure();
+ void activateWindow();
+
+protected:
+ virtual void doLoadConfiguration( KConfigGroup& );
+ virtual void doSaveConfiguration( KConfigGroup&, bool layoutOnly ) const;
+ virtual void alignmentChange(KPanelExtension::Alignment a);
+
+ virtual QPopupMenu* createOpMenu();
+
+ AppletInfo _info;
+ AppletHandle *_handle;
+ QHBox *_appletframe;
+ QBoxLayout *_layout;
+ KPanelApplet::Type _type;
+ int _widthForHeightHint;
+ int _heightForWidthHint;
+ QString _deskFile, _configFile;
+ bool _firstuse;
+ QCString _id;
+ KPanelApplet * _applet;
+ bool _valid;
+
+protected slots:
+ void slotRemoveApplet();
+ void slotUpdateLayout();
+ void signalToBeRemoved();
+ void slotDelayedDestruct();
+ void focusRequested(bool);
+};
+
+#endif
+
diff --git a/kicker/kicker/core/container_base.cpp b/kicker/kicker/core/container_base.cpp
new file mode 100644
index 000000000..cadbe592a
--- /dev/null
+++ b/kicker/kicker/core/container_base.cpp
@@ -0,0 +1,139 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qpopupmenu.h>
+
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "global.h"
+#include "appletop_mnu.h"
+#include "kicker.h"
+
+#include "container_base.h"
+#include "container_base.moc"
+
+BaseContainer::BaseContainer( QPopupMenu* appletOpMenu, QWidget* parent, const char * name )
+ : QWidget( parent, name )
+ , _dir(KPanelApplet::Up)
+ , _orient(Horizontal)
+ , _alignment(KPanelExtension::LeftTop)
+ , _fspace(0)
+ , _moveOffset(QPoint(0,0))
+ , _aid(QString::null)
+ , _actions(0)
+ , m_immutable(false)
+ , _opMnu(0)
+ , _appletOpMnu(appletOpMenu)
+{}
+
+BaseContainer::~BaseContainer()
+{
+ delete _opMnu;
+}
+
+void BaseContainer::reparent(QWidget* parent, WFlags f, const QPoint& p, bool showIt)
+{
+ emit takeme(this);
+ QWidget::reparent(parent, f, p, showIt);
+}
+
+bool BaseContainer::isImmutable() const
+{
+ return m_immutable || Kicker::the()->isImmutable();
+}
+
+void BaseContainer::setImmutable(bool immutable)
+{
+ m_immutable = immutable;
+ clearOpMenu();
+}
+
+void BaseContainer::loadConfiguration( KConfigGroup& group )
+{
+ setFreeSpace( QMIN( group.readDoubleNumEntry( "FreeSpace2", 0 ), 1 ) );
+ doLoadConfiguration( group );
+}
+
+void BaseContainer::saveConfiguration(KConfigGroup& group,
+ bool layoutOnly) const
+{
+ if (isImmutable())
+ {
+ return;
+ }
+
+ // write positioning info
+ group.writeEntry( "FreeSpace2", freeSpace() );
+ // write type specific info
+ doSaveConfiguration( group, layoutOnly );
+}
+
+void BaseContainer::configure(KPanelExtension::Orientation o,
+ KPanelApplet::Direction d)
+{
+ setBackgroundOrigin(AncestorOrigin);
+ setOrientation(o);
+ setPopupDirection(d);
+ configure();
+}
+
+void BaseContainer::slotRemoved(KConfig* config)
+{
+ if (!config)
+ {
+ config = KGlobal::config();
+ }
+
+ config->deleteGroup(appletId().latin1());
+ config->sync();
+}
+
+void BaseContainer::setAlignment(KPanelExtension::Alignment a)
+{
+ if (_alignment == a)
+ {
+ return;
+ }
+
+ _alignment = a;
+ alignmentChange(a);
+}
+
+QPopupMenu* BaseContainer::opMenu()
+{
+ if (_opMnu == 0)
+ {
+ _opMnu = createOpMenu();
+ }
+
+ return KickerLib::reduceMenu(_opMnu);
+}
+
+void BaseContainer::clearOpMenu()
+{
+ delete _opMnu;
+ _opMnu = 0;
+}
+
diff --git a/kicker/kicker/core/container_base.h b/kicker/kicker/core/container_base.h
new file mode 100644
index 000000000..aa3efeb98
--- /dev/null
+++ b/kicker/kicker/core/container_base.h
@@ -0,0 +1,134 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __container_base_h__
+#define __container_base_h__
+
+#include <qwidget.h>
+#include <qpoint.h>
+#include <qvaluelist.h>
+
+#include <kpanelextension.h>
+#include <kpanelapplet.h>
+
+class KConfigGroup;
+class QPopupMenu;
+
+class BaseContainer : public QWidget
+{
+ Q_OBJECT
+
+public:
+ typedef QValueList<BaseContainer*> List;
+ typedef QValueListIterator<BaseContainer*> Iterator;
+ typedef QValueListConstIterator<BaseContainer*> ConstIterator;
+
+ BaseContainer( QPopupMenu* appletOpMenu, QWidget* parent = 0, const char * name = 0 );
+ ~BaseContainer();
+
+ virtual void reparent(QWidget * parent, WFlags f, const QPoint & p, bool showIt = false);
+
+ virtual int widthForHeight(int height) const = 0;
+ virtual int heightForWidth(int width) const = 0;
+
+ virtual bool isStretch() const { return false; }
+
+ virtual void completeMoveOperation() {}
+ virtual void about() {}
+ virtual void help() {}
+ virtual void preferences() {}
+ virtual void reportBug() {}
+
+ virtual bool isValid() const { return true; }
+ bool isImmutable() const;
+ virtual void setImmutable(bool immutable);
+
+ double freeSpace() const { return _fspace; }
+ void setFreeSpace(double f) { _fspace = f; }
+
+ QString appletId() const { return _aid; }
+ void setAppletId(const QString& s) { _aid = s; }
+
+ virtual int actions() const { return _actions; }
+
+ KPanelApplet::Direction popupDirection() const { return _dir; }
+ KPanelExtension::Orientation orientation() const { return _orient; }
+ KPanelExtension::Alignment alignment() const { return _alignment; }
+
+ virtual void setBackground() {}
+
+ QPopupMenu* opMenu();
+ void clearOpMenu();
+
+ void loadConfiguration( KConfigGroup& );
+ void saveConfiguration( KConfigGroup&, bool layoutOnly = false ) const;
+
+ void configure(KPanelExtension::Orientation, KPanelApplet::Direction);
+ virtual void configure() {}
+
+ QPoint moveOffset() const { return _moveOffset; }
+
+ virtual QString appletType() const = 0;
+ virtual QString icon() const { return "unknown"; }
+ virtual QString visibleName() const = 0;
+
+public slots:
+ virtual void slotRemoved(KConfig* config);
+ virtual void setPopupDirection(KPanelApplet::Direction d) { _dir = d; }
+ virtual void setOrientation(KPanelExtension::Orientation o) { _orient = o; }
+
+ void setAlignment(KPanelExtension::Alignment a);
+
+signals:
+ void removeme(BaseContainer*);
+ void takeme(BaseContainer*);
+ void moveme(BaseContainer*);
+ void maintainFocus(bool);
+ void requestSave();
+ void focusReqested(bool);
+
+protected:
+ virtual void doLoadConfiguration( KConfigGroup& ) {}
+ virtual void doSaveConfiguration( KConfigGroup&,
+ bool /* layoutOnly */ ) const {}
+ virtual void alignmentChange(KPanelExtension::Alignment) {}
+
+ virtual QPopupMenu* createOpMenu() = 0;
+ QPopupMenu *appletOpMenu() const { return _appletOpMnu; }
+
+ KPanelApplet::Direction _dir;
+ KPanelExtension::Orientation _orient;
+ KPanelExtension::Alignment _alignment;
+ double _fspace;
+ QPoint _moveOffset;
+ QString _aid;
+ int _actions;
+ bool m_immutable;
+
+private:
+ QPopupMenu *_opMnu;
+ QPopupMenu *_appletOpMnu;
+};
+
+#endif
+
diff --git a/kicker/kicker/core/container_button.cpp b/kicker/kicker/core/container_button.cpp
new file mode 100644
index 000000000..b050f371d
--- /dev/null
+++ b/kicker/kicker/core/container_button.cpp
@@ -0,0 +1,542 @@
+/*****************************************************************
+
+Copyright (c) 1996-2003 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <algorithm>
+
+#include <qlayout.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kmultipledrag.h>
+#include <kpanelapplet.h>
+#include <kurldrag.h>
+
+#include "global.h"
+#include "appletop_mnu.h"
+
+#include "containerarea.h"
+#include "panelbutton.h"
+#include "bookmarksbutton.h"
+#include "browserbutton.h"
+#include "desktopbutton.h"
+#include "extensionbutton.h"
+#include "kbutton.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "kickertip.h"
+#include "nonkdeappbutton.h"
+#include "paneldrag.h"
+#include "servicebutton.h"
+#include "servicemenubutton.h"
+#include "urlbutton.h"
+#include "windowlistbutton.h"
+
+#include "container_button.h"
+#include "container_button.moc"
+
+ButtonContainer::ButtonContainer(QPopupMenu* opMenu, QWidget* parent)
+ : BaseContainer(opMenu, parent)
+ , _button(0)
+ , _layout(0)
+ , _oldpos(0,0)
+{
+ setBackgroundOrigin(AncestorOrigin);
+}
+
+bool ButtonContainer::isValid() const
+{
+ if (_button)
+ {
+ return _button->isValid();
+ }
+
+ return false; // Can this happen?
+}
+
+// Buttons Shouldn't be square when larger than a certain size.
+int ButtonContainer::widthForHeight(int height) const
+{
+ if (isValid())
+ {
+ return _button->widthForHeight(height);
+ }
+
+ return height;
+}
+
+int ButtonContainer::heightForWidth(int width) const
+{
+ if (isValid())
+ {
+ return _button->heightForWidth(width);
+ }
+
+ return width;
+}
+
+void ButtonContainer::setBackground()
+{
+ PanelButton* b = button();
+ if (!b)
+ return;
+
+ b->unsetPalette();
+}
+
+void ButtonContainer::configure()
+{
+ if (_button)
+ {
+ _button->configure();
+ }
+}
+
+void ButtonContainer::doSaveConfiguration(KConfigGroup& config, bool layoutOnly) const
+{
+ // immutability is checked by ContainerBase
+ if (_button && !layoutOnly)
+ {
+ _button->saveConfig(config);
+ }
+}
+
+void ButtonContainer::setPopupDirection(KPanelApplet::Direction d)
+{
+ BaseContainer::setPopupDirection(d);
+
+ if (_button)
+ {
+ _button->setPopupDirection(d);
+ }
+}
+
+void ButtonContainer::setOrientation(Orientation o)
+{
+ BaseContainer::setOrientation(o);
+
+ if(_button)
+ _button->setOrientation(o);
+}
+
+void ButtonContainer::embedButton(PanelButton* b)
+{
+ if (!b) return;
+
+ delete _layout;
+ _layout = new QVBoxLayout(this);
+ _button = b;
+
+ _button->installEventFilter(this);
+ _layout->add(_button);
+ connect(_button, SIGNAL(requestSave()), SIGNAL(requestSave()));
+ connect(_button, SIGNAL(hideme(bool)), SLOT(hideRequested(bool)));
+ connect(_button, SIGNAL(removeme()), SLOT(removeRequested()));
+ connect(_button, SIGNAL(dragme(const QPixmap)),
+ SLOT(dragButton(const QPixmap)));
+ connect(_button, SIGNAL(dragme(const KURL::List, const QPixmap)),
+ SLOT(dragButton(const KURL::List, const QPixmap)));
+}
+
+QPopupMenu* ButtonContainer::createOpMenu()
+{
+ return new PanelAppletOpMenu(_actions, appletOpMenu(), 0, _button->title(),
+ _button->icon(), this);
+}
+
+void ButtonContainer::removeRequested()
+{
+ if (isImmutable())
+ {
+ return;
+ }
+
+ emit removeme(this);
+}
+
+void ButtonContainer::hideRequested(bool shouldHide)
+{
+ if (shouldHide)
+ {
+ hide();
+ }
+ else
+ {
+ show();
+ }
+}
+
+void ButtonContainer::dragButton(const KURL::List urls, const QPixmap icon)
+{
+ if (isImmutable())
+ {
+ return;
+ }
+
+ KMultipleDrag* dd = new KMultipleDrag(this);
+ dd->addDragObject(new KURLDrag(urls, 0));
+ dd->addDragObject(new PanelDrag(this, 0));
+ dd->setPixmap(icon);
+ grabKeyboard();
+ dd->dragMove();
+ releaseKeyboard();
+}
+
+void ButtonContainer::dragButton(const QPixmap icon)
+{
+ PanelDrag* dd = new PanelDrag(this, this);
+ dd->setPixmap(icon);
+ grabKeyboard();
+ dd->drag();
+ releaseKeyboard();
+}
+
+bool ButtonContainer::eventFilter(QObject *o, QEvent *e)
+{
+ if (o == _button && e->type() == QEvent::MouseButtonPress)
+ {
+ static bool sentinal = false;
+
+ if (sentinal)
+ {
+ return false;
+ }
+
+ sentinal = true;
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ switch (me->button())
+ {
+ case MidButton:
+ {
+ if (isImmutable())
+ {
+ break;
+ }
+
+ _button->setDown(true);
+ _moveOffset = me->pos();
+ emit moveme(this);
+ sentinal = false;
+ return true;
+ }
+
+ case RightButton:
+ {
+ if (!kapp->authorizeKAction("kicker_rmb") ||
+ isImmutable())
+ {
+ break;
+ }
+
+ QPopupMenu* menu = opMenu();
+ connect( menu, SIGNAL( aboutToHide() ), this, SLOT( slotMenuClosed() ) );
+ QPoint pos = KickerLib::popupPosition(popupDirection(), menu, this,
+ (orientation() == Horizontal) ?
+ QPoint(0, 0) : me->pos());
+
+ Kicker::the()->setInsertionPoint(me->globalPos());
+
+ KickerTip::enableTipping(false);
+ switch (menu->exec(pos))
+ {
+ case PanelAppletOpMenu::Move:
+ _moveOffset = rect().center();
+ emit moveme(this);
+ break;
+ case PanelAppletOpMenu::Remove:
+ emit removeme(this);
+ break;
+ case PanelAppletOpMenu::Help:
+ help();
+ break;
+ case PanelAppletOpMenu::About:
+ about();
+ break;
+ case PanelAppletOpMenu::Preferences:
+ if (_button)
+ {
+ _button->properties();
+ }
+ break;
+ default:
+ break;
+ }
+ KickerTip::enableTipping(true);
+
+ Kicker::the()->setInsertionPoint(QPoint());
+ clearOpMenu();
+ sentinal = false;
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ sentinal = false;
+ }
+ return false;
+}
+
+void ButtonContainer::completeMoveOperation()
+{
+ if (_button)
+ {
+ _button->setDown(false);
+ setBackground();
+ }
+}
+
+void ButtonContainer::slotMenuClosed()
+{
+ if (_button)
+ _button->setDown(false);
+}
+
+void ButtonContainer::checkImmutability(const KConfigGroup& config)
+{
+ m_immutable = config.groupIsImmutable() ||
+ config.entryIsImmutable("ConfigFile") ||
+ config.entryIsImmutable("FreeSpace2");
+}
+
+// KMenuButton containerpan
+KMenuButtonContainer::KMenuButtonContainer(const KConfigGroup& config, QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new KButton(this) );
+ _actions = PanelAppletOpMenu::KMenuEditor;
+}
+
+KMenuButtonContainer::KMenuButtonContainer(QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new KButton(this) );
+ _actions = PanelAppletOpMenu::KMenuEditor;
+}
+
+int KMenuButtonContainer::heightForWidth( int width ) const
+{
+ if ( width < 32 )
+ return width + 10;
+ else
+ return ButtonContainer::heightForWidth(width);
+}
+
+// DesktopButton container
+DesktopButtonContainer::DesktopButtonContainer(QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new DesktopButton(this) );
+}
+
+DesktopButtonContainer::DesktopButtonContainer(const KConfigGroup& config,
+ QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new DesktopButton(this) );
+}
+
+// ServiceButton container
+ServiceButtonContainer::ServiceButtonContainer( const QString& desktopFile,
+ QPopupMenu* opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new ServiceButton( desktopFile, this ) );
+ _actions = KPanelApplet::Preferences;
+}
+
+ServiceButtonContainer::ServiceButtonContainer( const KService::Ptr &service,
+ QPopupMenu* opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new ServiceButton( service, this ) );
+ _actions = KPanelApplet::Preferences;
+}
+
+ServiceButtonContainer::ServiceButtonContainer( const KConfigGroup& config,
+ QPopupMenu* opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new ServiceButton( config, this ) );
+ _actions = KPanelApplet::Preferences;
+}
+
+QString ServiceButtonContainer::icon() const
+{
+ return button()->icon();
+}
+
+QString ServiceButtonContainer::visibleName() const
+{
+ return button()->title();
+}
+
+// URLButton container
+URLButtonContainer::URLButtonContainer( const QString& url, QPopupMenu* opMenu, QWidget* parent )
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new URLButton( url, this ) );
+ _actions = KPanelApplet::Preferences;
+}
+
+URLButtonContainer::URLButtonContainer( const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new URLButton( config, this ) );
+ _actions = KPanelApplet::Preferences;
+}
+
+QString URLButtonContainer::icon() const
+{
+ return button()->icon();
+}
+
+QString URLButtonContainer::visibleName() const
+{
+ return button()->title();
+}
+
+// BrowserButton container
+BrowserButtonContainer::BrowserButtonContainer(const QString &startDir, QPopupMenu* opMenu, const QString& icon, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new BrowserButton(icon, startDir, this) );
+ _actions = KPanelApplet::Preferences;
+}
+
+BrowserButtonContainer::BrowserButtonContainer( const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new BrowserButton(config, this) );
+ _actions = KPanelApplet::Preferences;
+}
+
+// ServiceMenuButton container
+ServiceMenuButtonContainer::ServiceMenuButtonContainer(const QString& relPath, QPopupMenu* opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new ServiceMenuButton(relPath, this) );
+}
+
+ServiceMenuButtonContainer::ServiceMenuButtonContainer( const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new ServiceMenuButton(config, this) );
+}
+
+QString ServiceMenuButtonContainer::icon() const
+{
+ return button()->icon();
+}
+
+QString ServiceMenuButtonContainer::visibleName() const
+{
+ return button()->title();
+}
+
+// WindowListButton container
+WindowListButtonContainer::WindowListButtonContainer(const KConfigGroup& config, QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new WindowListButton(this) );
+}
+
+WindowListButtonContainer::WindowListButtonContainer(QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new WindowListButton(this) );
+}
+
+// BookmarkButton container
+BookmarksButtonContainer::BookmarksButtonContainer(const KConfigGroup& config, QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new BookmarksButton(this) );
+ _actions = PanelAppletOpMenu::BookmarkEditor;
+}
+
+BookmarksButtonContainer::BookmarksButtonContainer(QPopupMenu *opMenu, QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new BookmarksButton(this) );
+ _actions = PanelAppletOpMenu::BookmarkEditor;
+}
+
+// NonKDEAppButton container
+NonKDEAppButtonContainer::NonKDEAppButtonContainer(const QString &name,
+ const QString &description,
+ const QString &filePath,
+ const QString &icon,
+ const QString &cmdLine,
+ bool inTerm,
+ QPopupMenu* opMenu,
+ QWidget* parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton(new NonKDEAppButton(name, description, filePath, icon, cmdLine,
+ inTerm, this));
+ _actions = KPanelApplet::Preferences;
+}
+
+NonKDEAppButtonContainer::NonKDEAppButtonContainer( const KConfigGroup& config, QPopupMenu* opMenu, QWidget *parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new NonKDEAppButton(config, this) );
+ _actions = KPanelApplet::Preferences;
+}
+
+// ExtensionButton container
+ExtensionButtonContainer::ExtensionButtonContainer(const QString& df, QPopupMenu* opMenu, QWidget *parent)
+ : ButtonContainer(opMenu, parent)
+{
+ embedButton( new ExtensionButton(df, this) );
+}
+
+ExtensionButtonContainer::ExtensionButtonContainer( const KConfigGroup& config, QPopupMenu* opMenu, QWidget *parent)
+ : ButtonContainer(opMenu, parent)
+{
+ checkImmutability(config);
+ embedButton( new ExtensionButton(config, this) );
+}
+
+QString ExtensionButtonContainer::icon() const
+{
+ return button()->icon();
+}
+
+QString ExtensionButtonContainer::visibleName() const
+{
+ return button()->title();
+}
+
diff --git a/kicker/kicker/core/container_button.h b/kicker/kicker/core/container_button.h
new file mode 100644
index 000000000..737271216
--- /dev/null
+++ b/kicker/kicker/core/container_button.h
@@ -0,0 +1,195 @@
+/*****************************************************************
+
+Copyright (c) 1996-2003 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __container_button_h__
+#define __container_button_h__
+
+#include <klocale.h>
+#include <kservice.h>
+#include <kurl.h>
+
+#include "container_base.h"
+
+class QLayout;
+class PanelButton;
+class KConfigGroup;
+
+class ButtonContainer : public BaseContainer
+{
+ Q_OBJECT
+
+public:
+ ButtonContainer(QPopupMenu* opMenu, QWidget* parent = 0);
+
+ virtual bool isValid() const;
+ virtual bool isAMenu() const { return false; }
+
+ virtual int widthForHeight(int height) const;
+ virtual int heightForWidth(int width) const;
+
+ virtual void setBackground();
+
+ virtual void configure();
+
+ bool eventFilter (QObject *, QEvent *);
+ virtual void completeMoveOperation();
+
+ PanelButton* button() const { return _button; }
+
+public slots:
+ void setPopupDirection(KPanelApplet::Direction d);
+ void setOrientation(KPanelExtension::Orientation o);
+
+protected slots:
+ void slotMenuClosed();
+ void removeRequested();
+ void hideRequested(bool);
+ void dragButton(const KURL::List urls, const QPixmap icon);
+ void dragButton(const QPixmap icon);
+
+protected:
+ virtual void doSaveConfiguration( KConfigGroup&, bool layoutOnly ) const;
+ void embedButton(PanelButton* p);
+ QPopupMenu* createOpMenu();
+ void checkImmutability(const KConfigGroup&);
+
+protected:
+ PanelButton *_button;
+ QLayout *_layout;
+ QPoint _oldpos;
+};
+
+class KMenuButtonContainer : public ButtonContainer
+{
+public:
+ KMenuButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ KMenuButtonContainer(QPopupMenu* opMenu, QWidget* parent = 0);
+ virtual QString appletType() const { return "KMenuButton"; }
+ virtual QString icon() const { return "kmenu"; }
+ virtual QString visibleName() const { return i18n("K Menu"); }
+
+ virtual int heightForWidth( int width ) const;
+ bool isAMenu() const { return true; }
+};
+
+class DesktopButtonContainer : public ButtonContainer
+{
+public:
+ DesktopButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ DesktopButtonContainer(QPopupMenu* opMenu, QWidget* parent = 0);
+ QString appletType() const { return "DesktopButton"; }
+ virtual QString icon() const { return "desktop"; }
+ virtual QString visibleName() const { return i18n("Desktop Access"); }
+};
+
+class ServiceButtonContainer : public ButtonContainer
+{
+public:
+ ServiceButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ ServiceButtonContainer(const KService::Ptr & service, QPopupMenu* opMenu,QWidget* parent = 0);
+ ServiceButtonContainer(const QString& desktopFile, QPopupMenu* opMenu,QWidget* parent = 0);
+ QString appletType() const { return "ServiceButton"; }
+ virtual QString icon() const;
+ virtual QString visibleName() const;
+};
+
+class URLButtonContainer : public ButtonContainer
+{
+public:
+ URLButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ URLButtonContainer(const QString& url, QPopupMenu* opMenu, QWidget* parent = 0);
+ QString appletType() const { return "URLButton"; }
+ virtual QString icon() const;
+ virtual QString visibleName() const;
+};
+
+class BrowserButtonContainer : public ButtonContainer
+{
+public:
+ BrowserButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ BrowserButtonContainer(const QString& startDir, QPopupMenu* opMenu, const QString& icon = "kdisknav", QWidget* parent = 0);
+ QString appletType() const { return "BrowserButton"; }
+ virtual QString icon() const { return "kdisknav"; }
+ virtual QString visibleName() const { return i18n("Quick Browser"); }
+ bool isAMenu() const { return true; }
+};
+
+class ServiceMenuButtonContainer : public ButtonContainer
+{
+public:
+ ServiceMenuButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ ServiceMenuButtonContainer(const QString& relPath, QPopupMenu* opMenu, QWidget* parent = 0);
+ QString appletType() const { return "ServiceMenuButton"; }
+ virtual QString icon() const;
+ virtual QString visibleName() const;
+ bool isAMenu() const { return true; }
+};
+
+class WindowListButtonContainer : public ButtonContainer
+{
+public:
+ WindowListButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ WindowListButtonContainer(QPopupMenu* opMenu, QWidget* parent = 0);
+ QString appletType() const { return "WindowListButton"; }
+ virtual QString icon() const { return "window_list"; }
+ virtual QString visibleName() const { return i18n("Windowlist"); }
+ bool isAMenu() const { return true; }
+};
+
+class BookmarksButtonContainer : public ButtonContainer
+{
+public:
+ BookmarksButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget* parent = 0);
+ BookmarksButtonContainer(QPopupMenu* opMenu, QWidget* parent = 0);
+ QString appletType() const { return "BookmarksButton"; }
+ virtual QString icon() const { return "bookmark"; }
+ virtual QString visibleName() const { return i18n("Bookmarks"); }
+ bool isAMenu() const { return true; }
+};
+
+class NonKDEAppButtonContainer : public ButtonContainer
+{
+public:
+ NonKDEAppButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget *parent=0);
+ NonKDEAppButtonContainer(const QString &name, const QString &description,
+ const QString &filePath, const QString &icon,
+ const QString &cmdLine, bool inTerm,
+ QPopupMenu* opMenu, QWidget* parent = 0);
+ QString appletType() const { return "ExecButton"; }
+ virtual QString icon() const { return "exec"; }
+ virtual QString visibleName() const { return i18n("Non-KDE Application"); }
+};
+
+class ExtensionButtonContainer : public ButtonContainer
+{
+public:
+ ExtensionButtonContainer(const KConfigGroup& config, QPopupMenu* opMenu, QWidget *parent=0);
+ ExtensionButtonContainer(const QString& desktopFile, QPopupMenu* opMenu, QWidget *parent= 0);
+ QString appletType() const { return "ExtensionButton"; }
+ virtual QString icon() const;
+ virtual QString visibleName() const;
+ bool isAMenu() const { return true; }
+};
+
+#endif
+
diff --git a/kicker/kicker/core/container_extension.cpp b/kicker/kicker/core/container_extension.cpp
new file mode 100644
index 000000000..694513109
--- /dev/null
+++ b/kicker/kicker/core/container_extension.cpp
@@ -0,0 +1,2067 @@
+/*****************************************************************
+
+Copyright (c) 2004-2005 Aaron J. Seigo <aseigo@kde.org>
+Copyright (c) 2000-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+#include <stdlib.h>
+#include <math.h>
+
+#include <qcursor.h>
+#include <qfile.h>
+#include <qlayout.h>
+#include <qmovie.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+#include <qxembed.h>
+#include <qcolor.h>
+
+#include <dcopclient.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kglobal.h>
+#include <kicker.h>
+#include <kstandarddirs.h>
+#include <kwin.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <kapplication.h>
+#include <netwm.h>
+#include <fixx11h.h>
+#include <kwinmodule.h>
+
+#include "container_base.h"
+#include "extensionmanager.h"
+#include "extensionop_mnu.h"
+#include "hidebutton.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "kickertip.h"
+#include "pluginmanager.h"
+#include "userrectsel.h"
+
+#include "container_extension.h"
+
+/* 1 is the initial speed, hide_show_animation is the top speed. */
+#define PANEL_SPEED(x, c) (int)((1.0-2.0*fabs((x)-(c)/2.0)/c)*m_settings.hideAnimationSpeed()+1.0)
+
+ExtensionContainer::ExtensionContainer(const AppletInfo& info,
+ const QString& extensionId,
+ QWidget *parent)
+ : QFrame(parent, ("ExtensionContainer#" + extensionId).latin1(), WStyle_Customize | WStyle_NoBorder),
+ m_settings(KSharedConfig::openConfig(info.configFile())),
+ m_hideMode(ManualHide),
+ m_unhideTriggeredAt(UnhideTrigger::None),
+ _autoHidden(false),
+ _userHidden(Unhidden),
+ _block_user_input(false),
+ _is_lmb_down(false),
+ _in_autohide(false),
+ _id(extensionId),
+ _opMnu(0),
+ _info(info),
+ _ltHB(0),
+ _rbHB(0),
+ m_extension(0),
+ m_maintainFocus(0),
+ m_panelOrder(ExtensionManager::the()->nextPanelOrder())
+{
+ // now actually try to load the extension
+ m_extension = PluginManager::the()->loadExtension(info, this);
+ init();
+}
+
+ExtensionContainer::ExtensionContainer(KPanelExtension* extension,
+ const AppletInfo& info,
+ const QString& extensionId,
+ QWidget *parent)
+ : QFrame(parent, ("ExtensionContainer#" + extensionId).latin1(), WStyle_Customize | WStyle_NoBorder),
+ m_settings(KSharedConfig::openConfig(info.configFile())),
+ _autoHidden(false),
+ _userHidden(Unhidden),
+ _block_user_input(false),
+ _is_lmb_down(false),
+ _in_autohide(false),
+ _id(extensionId),
+ _opMnu(0),
+ _info(info),
+ _ltHB(0),
+ _rbHB(0),
+ m_extension(extension),
+ m_maintainFocus(0),
+ m_panelOrder(ExtensionManager::the()->nextPanelOrder())
+{
+ m_extension->reparent(this, QPoint(0, 0));
+ init();
+}
+
+void ExtensionContainer::init()
+{
+ // panels live in the dock
+ KWin::setType(winId(), NET::Dock);
+ KWin::setState(winId(), NET::Sticky);
+ KWin::setOnAllDesktops(winId(), true);
+
+ connect(Kicker::the()->kwinModule(), SIGNAL(strutChanged()), this, SLOT(strutChanged()));
+ connect(Kicker::the()->kwinModule(), SIGNAL(currentDesktopChanged(int)),
+ this, SLOT( currentDesktopChanged(int)));
+
+ setBackgroundOrigin(AncestorOrigin);
+ setFrameStyle(NoFrame);
+ setLineWidth(0);
+ setMargin(0);
+
+ connect(UnhideTrigger::the(), SIGNAL(triggerUnhide(UnhideTrigger::Trigger,int)),
+ this, SLOT(unhideTriggered(UnhideTrigger::Trigger,int)));
+
+ _popupWidgetFilter = new PopupWidgetFilter( this );
+ connect(_popupWidgetFilter, SIGNAL(popupWidgetHiding()), SLOT(maybeStartAutoHideTimer()));
+
+ // layout
+ _layout = new QGridLayout(this, 3, 3, 0, 0);
+ _layout->setResizeMode(QLayout::FreeResize);
+ _layout->setRowStretch(1,10);
+ _layout->setColStretch(1,10);
+
+ // instantiate the autohide timer
+ _autohideTimer = new QTimer(this, "_autohideTimer");
+ connect(_autohideTimer, SIGNAL(timeout()), SLOT(autoHideTimeout()));
+
+ // instantiate the updateLayout event compressor timer
+ _updateLayoutTimer = new QTimer(this, "_updateLayoutTimer");
+ connect(_updateLayoutTimer, SIGNAL(timeout()), SLOT(actuallyUpdateLayout()));
+
+ installEventFilter(this); // for mouse event handling
+
+ connect(Kicker::the(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(updateHighlightColor()));
+ updateHighlightColor();
+
+ // if we were hidden when kicker quit, let's start out hidden as well!
+ KConfig *config = KGlobal::config();
+ config->setGroup(extensionId());
+ int tmp = config->readNumEntry("UserHidden", Unhidden);
+ if (tmp > Unhidden && tmp <= RightBottom)
+ {
+ _userHidden = static_cast<UserHidden>(tmp);
+ }
+
+ if (m_extension)
+ {
+ // if we have an extension, we need to grab the extension-specific
+ // defaults for position, size and custom size and override the
+ // defaults in the settings object since the extension may differ
+ // from the "normal" panels. for example, the universal sidebar's
+ // preferred position is the left, not the bottom/top
+ KConfigSkeleton::ItemInt* item = dynamic_cast<KConfigSkeleton::ItemInt*>(m_settings.findItem("Position"));
+ if (item)
+ {
+ KPanelExtension::Position p = m_extension->preferedPosition();
+ item->setDefaultValue(p);
+ item->readConfig(m_settings.config());
+ }
+
+ item = dynamic_cast<KConfigSkeleton::ItemInt*>(m_settings.findItem("Size"));
+ if (item)
+ {
+ item->setDefaultValue(m_extension->sizeSetting());
+ }
+
+ item = dynamic_cast<KConfigSkeleton::ItemInt*>(m_settings.findItem("CustomSize"));
+ if (item)
+ {
+ item->setDefaultValue(m_extension->customSize());
+ }
+
+ connect(m_extension, SIGNAL(updateLayout()), SLOT(updateLayout()));
+ connect(m_extension, SIGNAL(maintainFocus(bool)),
+ SLOT(maintainFocus(bool)));
+
+ _layout->addWidget(m_extension, 1, 1);
+ }
+
+ if (!m_settings.iExist())
+ {
+ m_settings.setIExist(true);
+ m_settings.writeConfig();
+ }
+}
+
+ExtensionContainer::~ExtensionContainer()
+{
+}
+
+QSize ExtensionContainer::sizeHint(KPanelExtension::Position p, const QSize &maxSize) const
+{
+ int width = 0;
+ int height = 0;
+ if (p == KPanelExtension::Top || p == KPanelExtension::Bottom)
+ {
+ if (needsBorder())
+ {
+ height += 1; // border
+ }
+
+ if (m_settings.showLeftHideButton())
+ {
+ width += m_settings.hideButtonSize();
+ }
+
+ if (m_settings.showRightHideButton())
+ {
+ width += m_settings.hideButtonSize();
+ }
+
+ // don't forget we might have a border!
+ width += _layout->colSpacing(0) + _layout->colSpacing(2);
+ }
+ else
+ {
+ if (needsBorder())
+ {
+ width += 1; // border
+ }
+
+ if (m_settings.showLeftHideButton())
+ {
+ height += m_settings.hideButtonSize();
+ }
+
+ if (m_settings.showRightHideButton())
+ {
+ height += m_settings.hideButtonSize();
+ }
+
+ // don't forget we might have a border!
+ height += _layout->rowSpacing(0) + _layout->rowSpacing(2);
+ }
+
+ QSize size(width, height);
+ size = size.boundedTo(maxSize);
+
+ if (m_extension)
+ {
+ size = m_extension->sizeHint(p, maxSize - size) + size;
+ }
+
+ return size.boundedTo(maxSize);
+}
+
+static bool isnetwm12_below()
+{
+ NETRootInfo info( qt_xdisplay(), NET::Supported );
+ return info.supportedProperties()[ NETRootInfo::STATES ] & NET::KeepBelow;
+}
+
+void ExtensionContainer::readConfig()
+{
+// kdDebug(1210) << "ExtensionContainer::readConfig()" << endl;
+ m_settings.readConfig();
+
+ if (m_settings.autoHidePanel())
+ {
+ m_hideMode = AutomaticHide;
+ }
+ else if (m_settings.backgroundHide())
+ {
+ m_hideMode = BackgroundHide;
+ }
+ else
+ {
+ m_hideMode = ManualHide;
+ }
+
+ positionChange(position());
+ alignmentChange(alignment());
+ setSize(static_cast<KPanelExtension::Size>(m_settings.size()),
+ m_settings.customSize());
+
+ if (m_hideMode != AutomaticHide)
+ {
+ autoHide(false);
+ }
+
+ static bool netwm12 = isnetwm12_below();
+ if (netwm12) // new netwm1.2 compliant way
+ {
+ if (m_hideMode == BackgroundHide)
+ {
+ KWin::setState( winId(), NET::KeepBelow );
+ UnhideTrigger::the()->setEnabled( true );
+ }
+ else
+ {
+ KWin::clearState( winId(), NET::KeepBelow );
+ }
+ }
+ else if (m_hideMode == BackgroundHide)
+ {
+ // old way
+ KWin::clearState( winId(), NET::StaysOnTop );
+ UnhideTrigger::the()->setEnabled( true );
+ }
+ else
+ {
+ // the other old way
+ KWin::setState( winId(), NET::StaysOnTop );
+ }
+
+ actuallyUpdateLayout();
+ maybeStartAutoHideTimer();
+}
+
+void ExtensionContainer::writeConfig()
+{
+// kdDebug(1210) << "ExtensionContainer::writeConfig()" << endl;
+ KConfig *config = KGlobal::config();
+ config->setGroup(extensionId());
+
+ config->writePathEntry("ConfigFile", _info.configFile());
+ config->writePathEntry("DesktopFile", _info.desktopFile());
+ config->writeEntry("UserHidden", userHidden());
+
+ m_settings.writeConfig();
+}
+
+void ExtensionContainer::showPanelMenu( const QPoint& globalPos )
+{
+ if (!kapp->authorizeKAction("kicker_rmb"))
+ {
+ return;
+ }
+
+ if (m_extension && m_extension->customMenu())
+ {
+ // use the extenion's own custom menu
+ Kicker::the()->setInsertionPoint(globalPos);
+ m_extension->customMenu()->exec(globalPos);
+ Kicker::the()->setInsertionPoint(QPoint());
+ return;
+ }
+
+ if (!_opMnu)
+ {
+ KDesktopFile f(KGlobal::dirs()->findResource("extensions", _info.desktopFile()));
+ _opMnu = new PanelExtensionOpMenu(f.readName(),
+ m_extension ? m_extension->actions() : 0,
+ this);
+ }
+
+ QPopupMenu *menu = KickerLib::reduceMenu(_opMnu);
+
+ Kicker::the()->setInsertionPoint(globalPos);
+
+ switch (menu->exec(globalPos))
+ {
+ case PanelExtensionOpMenu::Remove:
+ emit removeme(this);
+ break;
+ case PanelExtensionOpMenu::About:
+ about();
+ break;
+ case PanelExtensionOpMenu::Help:
+ help();
+ break;
+ case PanelExtensionOpMenu::Preferences:
+ preferences();
+ break;
+ case PanelExtensionOpMenu::ReportBug:
+ reportBug();
+ break;
+ default:
+ break;
+ }
+ Kicker::the()->setInsertionPoint(QPoint());
+}
+
+void ExtensionContainer::about()
+{
+ if (!m_extension)
+ {
+ return;
+ }
+
+ m_extension->action(KPanelExtension::About);
+}
+
+void ExtensionContainer::help()
+{
+ if (!m_extension)
+ {
+ return;
+ }
+
+ m_extension->action(KPanelExtension::Help);
+}
+
+void ExtensionContainer::preferences()
+{
+ if (!m_extension)
+ {
+ return;
+ }
+
+ m_extension->action(KPanelExtension::Preferences);
+}
+
+void ExtensionContainer::reportBug()
+{
+ if (!m_extension)
+ {
+ return;
+ }
+
+ m_extension->action(KPanelExtension::ReportBug);
+}
+
+void ExtensionContainer::removeSessionConfigFile()
+{
+ if (_info.configFile().isEmpty() || _info.isUniqueApplet())
+ {
+ return;
+ }
+
+ if (QFile::exists(locate("config", _info.configFile())))
+ {
+ QFile::remove(locate("config", _info.configFile()));
+ }
+}
+
+void ExtensionContainer::moveMe()
+{
+ int screen = xineramaScreen();
+ if (screen < 0)
+ {
+ screen = kapp->desktop()->screenNumber(this);
+ }
+
+ if (screen < 0)
+ {
+ // we aren't on any screen? um. ok.
+ return;
+ }
+
+ stopAutoHideTimer();
+
+ QApplication::syncX();
+ UserRectSel::RectList rects;
+
+ KPanelExtension::Position positions[] = { KPanelExtension::Left,
+ KPanelExtension::Right,
+ KPanelExtension::Top,
+ KPanelExtension::Bottom };
+ KPanelExtension::Alignment alignments[] = { KPanelExtension::LeftTop,
+ KPanelExtension::Center,
+ KPanelExtension::RightBottom };
+
+ for (int s = 0; s < QApplication::desktop()->numScreens(); s++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ // FIXME:
+ // asking for initial geometry here passes bogus heightForWidth
+ // and widthForHeight requests to applets and buttons. if they
+ // need to make layout adjustments or need to calculate based
+ // on other parameters this can lead to Bad Things(tm)
+ //
+ // we need to find a way to do this that doesn't result in
+ // sizeHint's getting called on the extension =/
+ //
+ // or else we need to change the semantics for applets so that
+ // they don't get their "you're changing position" signals through
+ // heightForWidth/widthForHeight
+ rects.append(UserRectSel::PanelStrut(initialGeometry(positions[i],
+ alignments[j], s),
+ s, positions[i], alignments[j]));
+ }
+ }
+ }
+
+ UserRectSel::PanelStrut newStrut = UserRectSel::select(rects, rect().center(), m_highlightColor);
+ arrange(newStrut.m_pos, newStrut.m_alignment, newStrut.m_screen);
+
+ _is_lmb_down = false;
+
+ // sometimes the HB's are not reset correctly
+ if (_ltHB)
+ {
+ _ltHB->setDown(false);
+ }
+
+ if (_rbHB)
+ {
+ _rbHB->setDown(false);
+ }
+
+ maybeStartAutoHideTimer();
+}
+
+void ExtensionContainer::updateLayout()
+{
+ /*
+ m_extension == 0 can happen for example if the constructor of a panel
+ extension calls adjustSize(), resulting in a sendPostedEvents on the parent (us) and
+ therefore this call. Happens with ksim for example. One can argue about ksim here, but
+ kicker shouldn't crash in any case.
+ */
+ if (!m_extension || _updateLayoutTimer->isActive())
+ {
+ return;
+ }
+
+ // don't update our layout more than once every half a second...
+ if (_in_autohide)
+ {
+ // ... unless we are autohiding
+ _updateLayoutTimer->start(0,true);
+ }
+ else
+ {
+ _updateLayoutTimer->start(500,true);
+ }
+}
+
+void ExtensionContainer::actuallyUpdateLayout()
+{
+// kdDebug(1210) << "PanelContainer::updateLayout()" << endl;
+ resetLayout();
+ updateWindowManager();
+}
+
+void ExtensionContainer::enableMouseOverEffects()
+{
+ KickerTip::enableTipping(true);
+ QPoint globalPos = QCursor::pos();
+ QPoint localPos = mapFromGlobal(globalPos);
+ QWidget* child = childAt(localPos);
+
+ if (child)
+ {
+ QMouseEvent* e = new QMouseEvent(QEvent::Enter, localPos, globalPos, 0, 0);
+ qApp->sendEvent(child, e);
+ }
+}
+
+bool ExtensionContainer::shouldUnhideForTrigger(UnhideTrigger::Trigger t) const
+{
+ int loc = m_settings.unhideLocation();
+
+ if (loc == t)
+ {
+ return true;
+ }
+
+ if (loc == UnhideTrigger::Bottom)
+ {
+ return t == UnhideTrigger::BottomLeft ||
+ t == UnhideTrigger::BottomRight;
+ }
+ else if (loc == UnhideTrigger::Top)
+ {
+ return t == UnhideTrigger::TopLeft ||
+ t == UnhideTrigger::TopRight;
+ }
+ else if (loc == UnhideTrigger::Left)
+ {
+ return t == UnhideTrigger::TopLeft ||
+ t == UnhideTrigger::BottomLeft;
+ }
+ else if (loc == UnhideTrigger::Right)
+ {
+ return t == UnhideTrigger::TopRight ||
+ t == UnhideTrigger::BottomRight;
+ }
+
+ return false;
+}
+
+void ExtensionContainer::unhideTriggered(UnhideTrigger::Trigger tr, int XineramaScreen)
+{
+ if (m_hideMode == ManualHide)
+ {
+ return;
+ }
+ else if (tr == UnhideTrigger::None)
+ {
+ if (m_settings.unhideLocation() != UnhideTrigger::None && _autoHidden)
+ {
+ UnhideTrigger::the()->setEnabled(false);
+ }
+
+ m_unhideTriggeredAt = UnhideTrigger::None;
+ return;
+ }
+
+ if (xineramaScreen() != XineramaAllScreens &&
+ XineramaScreen != xineramaScreen())
+ {
+ if (m_settings.unhideLocation() != UnhideTrigger::None)
+ {
+ m_unhideTriggeredAt = tr;
+ }
+ return;
+ }
+
+ // here we handle the case where the user has defined WHERE
+ // the pannel can be popped up from.
+ if (m_settings.unhideLocation() != UnhideTrigger::None)
+ {
+ if (_autoHidden)
+ {
+ UnhideTrigger::the()->setEnabled(true);
+ }
+
+ m_unhideTriggeredAt = tr;
+ if (shouldUnhideForTrigger(tr))
+ {
+ UnhideTrigger::the()->triggerAccepted(tr, XineramaScreen);
+
+ if (m_hideMode == BackgroundHide)
+ {
+ KWin::raiseWindow(winId());
+ }
+ else if (_autoHidden)
+ {
+ autoHide(false);
+ maybeStartAutoHideTimer();
+ }
+ }
+
+ return;
+ }
+
+ m_unhideTriggeredAt = UnhideTrigger::None;
+
+ // Otherwise hide mode is automatic. The code below is slightly
+ // complex so as to keep the same behavior as it has always had:
+ // only unhide when the cursor position is within the widget geometry.
+ // We can't just do geometry().contains(QCursor::pos()) because
+ // now we hide the panel completely off screen.
+
+ int x = QCursor::pos().x();
+ int y = QCursor::pos().y();
+ int t = geometry().top();
+ int b = geometry().bottom();
+ int r = geometry().right();
+ int l = geometry().left();
+ if (((tr == UnhideTrigger::Top ||
+ tr == UnhideTrigger::TopLeft ||
+ tr == UnhideTrigger::TopRight) &&
+ position() == KPanelExtension::Top && x >= l && x <= r) ||
+ ((tr == UnhideTrigger::Left ||
+ tr == UnhideTrigger::TopLeft ||
+ tr == UnhideTrigger::BottomLeft) &&
+ position() == KPanelExtension::Left && y >= t && y <= b) ||
+ ((tr == UnhideTrigger::Bottom ||
+ tr == UnhideTrigger::BottomLeft ||
+ tr == UnhideTrigger::BottomRight) &&
+ position() == KPanelExtension::Bottom && x >= l && x <= r ) ||
+ ((tr == UnhideTrigger::Right ||
+ tr == UnhideTrigger::TopRight ||
+ tr == UnhideTrigger::BottomRight) &&
+ position() == KPanelExtension::Right && y >= t && y <= b ))
+ {
+ UnhideTrigger::the()->triggerAccepted(tr, XineramaScreen);
+
+ if (_autoHidden)
+ {
+ autoHide(false);
+ maybeStartAutoHideTimer();
+ }
+ else if (m_hideMode == BackgroundHide)
+ {
+ KWin::raiseWindow(winId());
+ }
+ }
+}
+
+void ExtensionContainer::autoHideTimeout()
+{
+// kdDebug(1210) << "PanelContainer::autoHideTimeout() " << name() << endl;
+ // Hack: If there is a popup open, don't autohide until it closes.
+ QWidget* popup = QApplication::activePopupWidget();
+ if (popup)
+ {
+
+ // kdDebug(1210) << "popup detected" << endl;
+
+ // Remove it first in case it was already installed.
+ // Does nothing if it wasn't installed.
+ popup->removeEventFilter( _popupWidgetFilter );
+
+ // We will get a signal from the filter after the
+ // popup is hidden. At that point, maybeStartAutoHideTimer()
+ // will get called again.
+ popup->installEventFilter( _popupWidgetFilter );
+
+ // Stop the timer.
+ stopAutoHideTimer();
+ return;
+ }
+
+ if (m_hideMode != AutomaticHide ||
+ _autoHidden ||
+ _userHidden ||
+ m_maintainFocus > 0)
+ {
+ return;
+ }
+
+ QRect r = geometry();
+ QPoint p = QCursor::pos();
+ if (!r.contains(p) &&
+ (m_settings.unhideLocation() == UnhideTrigger::None ||
+ !shouldUnhideForTrigger(m_unhideTriggeredAt)))
+ {
+ stopAutoHideTimer();
+ autoHide(true);
+ UnhideTrigger::the()->resetTriggerThrottle();
+ }
+}
+
+void ExtensionContainer::hideLeft()
+{
+ animatedHide(true);
+}
+
+void ExtensionContainer::hideRight()
+{
+ animatedHide(false);
+}
+
+void ExtensionContainer::autoHide(bool hide)
+{
+// kdDebug(1210) << "PanelContainer::autoHide( " << hide << " )" << endl;
+
+ if (_in_autohide || hide == _autoHidden)
+ {
+ return;
+ }
+
+ // kdDebug(1210) << "entering autohide for real" << endl;
+
+ blockUserInput(true);
+
+ QPoint oldpos = pos();
+ QRect newextent = initialGeometry( position(), alignment(), xineramaScreen(), hide, Unhidden );
+ QPoint newpos = newextent.topLeft();
+
+ if (hide)
+ {
+ /* bail out if we are unable to hide */
+
+ for (int s=0; s < QApplication::desktop()->numScreens(); s++)
+ {
+ /* don't let it intersect with any screen in the hidden position
+ * that it doesn't intesect in the shown position. Should prevent
+ * panels from hiding by sliding onto other screens, while still
+ * letting them show reveal buttons onscreen */
+ QRect desktopGeom = QApplication::desktop()->screenGeometry(s);
+ if (desktopGeom.intersects(newextent) &&
+ !desktopGeom.intersects(geometry()))
+ {
+ blockUserInput( false );
+ return;
+ }
+ }
+ }
+
+ _in_autohide = true;
+ _autoHidden = hide;
+ UnhideTrigger::the()->setEnabled(_autoHidden);
+ KickerTip::enableTipping(false);
+
+ if (hide)
+ {
+ // So we don't cover other panels
+ lower();
+ }
+ else
+ {
+ // So we aren't covered by other panels
+ raise();
+ }
+
+ if (m_settings.hideAnimation())
+ {
+ if (position() == KPanelExtension::Left || position() == KPanelExtension::Right)
+ {
+ for (int i = 0; i < abs(newpos.x() - oldpos.x());
+ i += PANEL_SPEED(i,abs(newpos.x() - oldpos.x())))
+ {
+ if (newpos.x() > oldpos.x())
+ {
+ move(oldpos.x() + i, newpos.y());
+ }
+ else
+ {
+ move(oldpos.x() - i, newpos.y());
+ }
+
+ qApp->syncX();
+ qApp->processEvents();
+ }
+ }
+ else
+ {
+ for (int i = 0; i < abs(newpos.y() - oldpos.y());
+ i += PANEL_SPEED(i,abs(newpos.y() - oldpos.y())))
+ {
+ if (newpos.y() > oldpos.y())
+ {
+ move(newpos.x(), oldpos.y() + i);
+ }
+ else
+ {
+ move(newpos.x(), oldpos.y() - i);
+ }
+
+ qApp->syncX();
+ qApp->processEvents();
+ }
+ }
+ }
+
+ blockUserInput(false);
+
+ updateLayout();
+
+ // Sometimes tooltips don't get hidden
+ QToolTip::hide();
+
+ _in_autohide = false;
+
+ QTimer::singleShot(100, this, SLOT(enableMouseOverEffects()));
+}
+
+void ExtensionContainer::animatedHide(bool left)
+{
+// kdDebug(1210) << "PanelContainer::animatedHide()" << endl;
+ KickerTip::enableTipping(false);
+ blockUserInput(true);
+
+ UserHidden newState;
+ if (_userHidden != Unhidden)
+ {
+ newState = Unhidden;
+ }
+ else if (left)
+ {
+ newState = LeftTop;
+ }
+ else
+ {
+ newState = RightBottom;
+ }
+
+ QPoint oldpos = pos();
+ QRect newextent = initialGeometry(position(), alignment(), xineramaScreen(), false, newState);
+ QPoint newpos(newextent.topLeft());
+
+ if (newState != Unhidden)
+ {
+ /* bail out if we are unable to hide */
+ for(int s=0; s < QApplication::desktop()->numScreens(); s++)
+ {
+ /* don't let it intersect with any screen in the hidden position
+ * that it doesn't intesect in the shown position. Should prevent
+ * panels from hiding by sliding onto other screens, while still
+ * letting them show reveal buttons onscreen */
+ if (QApplication::desktop()->screenGeometry(s).intersects(newextent) &&
+ !QApplication::desktop()->screenGeometry(s).intersects(geometry()))
+ {
+ blockUserInput(false);
+ QTimer::singleShot(100, this, SLOT(enableMouseOverEffects()));
+ return;
+ }
+ }
+
+ _userHidden = newState;
+
+ // So we don't cover the mac-style menubar
+ lower();
+ }
+
+ if (m_settings.hideAnimation())
+ {
+ if (position() == KPanelExtension::Left || position() == KPanelExtension::Right)
+ {
+ for (int i = 0; i < abs(newpos.y() - oldpos.y());
+ i += PANEL_SPEED(i, abs(newpos.y() - oldpos.y())))
+ {
+ if (newpos.y() > oldpos.y())
+ {
+ move(newpos.x(), oldpos.y() + i);
+ }
+ else
+ {
+ move(newpos.x(), oldpos.y() - i);
+ }
+ qApp->syncX();
+ qApp->processEvents();
+ }
+ }
+ else
+ {
+ for (int i = 0; i < abs(newpos.x() - oldpos.x());
+ i += PANEL_SPEED(i, abs(newpos.x() - oldpos.x())))
+ {
+ if (newpos.x() > oldpos.x())
+ {
+ move(oldpos.x() + i, newpos.y());
+ }
+ else
+ {
+ move(oldpos.x() - i, newpos.y());
+ }
+ qApp->syncX();
+ qApp->processEvents();
+ }
+ }
+ }
+
+ blockUserInput( false );
+
+ _userHidden = newState;
+
+ actuallyUpdateLayout();
+ qApp->syncX();
+ qApp->processEvents();
+
+ // save our hidden status so that when kicker starts up again
+ // we'll come back in the same state
+ KConfig *config = KGlobal::config();
+ config->setGroup(extensionId());
+ config->writeEntry("UserHidden", userHidden());
+
+ QTimer::singleShot(100, this, SLOT(enableMouseOverEffects()));
+}
+
+bool ExtensionContainer::reserveStrut() const
+{
+ return !m_extension || m_extension->reserveStrut();
+}
+
+KPanelExtension::Alignment ExtensionContainer::alignment() const
+{
+ // KConfigXT really needs to get support for vars that are enums that
+ // are defined in other classes
+ return static_cast<KPanelExtension::Alignment>(m_settings.alignment());
+}
+
+void ExtensionContainer::updateWindowManager()
+{
+ NETExtendedStrut strut;
+
+ if (reserveStrut())
+ {
+ // kdDebug(1210) << "PanelContainer::updateWindowManager()" << endl;
+ // Set the relevant properties on the window.
+ int w = 0;
+ int h = 0;
+
+ QRect geom = initialGeometry(position(), alignment(), xineramaScreen());
+ QRect virtRect(QApplication::desktop()->geometry());
+ QRect screenRect(QApplication::desktop()->screenGeometry(xineramaScreen()));
+
+ if (m_hideMode == ManualHide && !userHidden())
+ {
+ w = width();
+ h = height();
+ }
+
+ switch (position())
+ {
+ case KPanelExtension::Top:
+ strut.top_width = geom.y() + h;
+ strut.top_start = x();
+ strut.top_end = x() + width() - 1;
+ break;
+
+ case KPanelExtension::Bottom:
+ // also claim the non-visible part at the bottom
+ strut.bottom_width = (virtRect.bottom() - geom.bottom()) + h;
+ strut.bottom_start = x();
+ strut.bottom_end = x() + width() - 1;
+ break;
+
+ case KPanelExtension::Right:
+ strut.right_width = (virtRect.right() - geom.right()) + w;
+ strut.right_start = y();
+ strut.right_end = y() + height() - 1;
+ break;
+
+ case KPanelExtension::Left:
+ strut.left_width = geom.x() + w;
+ strut.left_start = y();
+ strut.left_end = y() + height() - 1;
+ break;
+
+ case KPanelExtension::Floating:
+ // should never be reached, anyways
+ break;
+ }
+ }
+
+ if (strut.left_width != _strut.left_width ||
+ strut.left_start != _strut.left_start ||
+ strut.left_end != _strut.left_end ||
+ strut.right_width != _strut.right_width ||
+ strut.right_start != _strut.right_start ||
+ strut.right_end != _strut.right_end ||
+ strut.top_width != _strut.top_width ||
+ strut.top_start != _strut.top_start ||
+ strut.top_end != _strut.top_end ||
+ strut.bottom_width != _strut.bottom_width ||
+ strut.bottom_start != _strut.bottom_start ||
+ strut.bottom_end != _strut.bottom_end)
+ {
+ /*kdDebug(1210) << " === Panel sets new strut for pos " << position() << " ===" << endl;
+
+ kdDebug(1210) << "strut for " << winId() << ": " << endl <<
+ "\tleft : " << strut.left_width << " " << strut.left_start << " " << strut.left_end << endl <<
+ "\tright : " << strut.right_width << " " << strut.right_start << " " << strut.right_end << endl <<
+ "\ttop : " << strut.top_width << " " << strut.top_start << " " << strut.top_end << endl <<
+ "\tbottom: " << strut.bottom_width << " " << strut.bottom_start << " " << strut.bottom_end << endl; */
+ _strut = strut;
+
+ KWin::setExtendedStrut(winId(),
+ strut.left_width, strut.left_start, strut.left_end,
+ strut.right_width, strut.right_start, strut.right_end,
+ strut.top_width, strut.top_start, strut.top_end,
+ strut.bottom_width, strut.bottom_start, strut.bottom_end);
+ KWin::setStrut(winId(), strut.left_width, strut.right_width, strut.top_width, strut.bottom_width);
+ }
+ /*else
+ {
+ kdDebug(1210) << "Panel strut did NOT change!" << endl;
+ }*/
+}
+
+void ExtensionContainer::currentDesktopChanged(int)
+{
+ // kdDebug(1210) << "PanelContainer::currentDesktopChanged" << endl;
+ if (m_settings.autoHideSwitch())
+ {
+ if (m_hideMode == AutomaticHide)
+ {
+ autoHide(false);
+ }
+ else if (m_hideMode == BackgroundHide)
+ {
+ KWin::raiseWindow(winId());
+ }
+ }
+
+ // For some reason we don't always get leave events when the user
+ // changes desktops and moves the cursor out of the panel at the
+ // same time. Maybe always calling this will help.
+ maybeStartAutoHideTimer();
+}
+
+void ExtensionContainer::strutChanged()
+{
+ //kdDebug(1210) << "PanelContainer::strutChanged()" << endl;
+ QRect ig = currentGeometry();
+
+ if (ig != geometry())
+ {
+ setGeometry(ig);
+ updateLayout();
+ }
+}
+
+void ExtensionContainer::blockUserInput( bool block )
+{
+ if (block == _block_user_input)
+ {
+ return;
+ }
+
+ // If we don't want any user input to be possible we should catch mouse
+ // events and such. Therefore we install an eventfilter and let the
+ // eventfilter discard those events.
+ if ( block )
+ {
+ qApp->installEventFilter( this );
+ }
+ else
+ {
+ qApp->removeEventFilter( this );
+ }
+
+ _block_user_input = block;
+}
+
+void ExtensionContainer::maybeStartAutoHideTimer()
+{
+ if (m_hideMode != ManualHide &&
+ !_autoHidden &&
+ !_userHidden)
+ {
+ // kdDebug(1210) << "starting auto hide timer for " << name() << endl;
+ if (m_settings.autoHideDelay() == 0)
+ {
+ _autohideTimer->start(250);
+ }
+ else
+ {
+ _autohideTimer->start(m_settings.autoHideDelay() * 1000);
+ }
+ }
+}
+
+void ExtensionContainer::stopAutoHideTimer()
+{
+ if (_autohideTimer->isActive())
+ {
+ //kdDebug(1210) << "stopping auto hide timer for " << name() << endl;
+ _autohideTimer->stop();
+ }
+}
+
+void ExtensionContainer::maintainFocus(bool maintain)
+{
+ if (maintain)
+ {
+ ++m_maintainFocus;
+
+ if (_autoHidden)
+ {
+ autoHide(false);
+ }
+ else if (_userHidden == LeftTop)
+ {
+ animatedHide(true);
+ }
+ else if (_userHidden == RightBottom)
+ {
+ animatedHide(false);
+ }
+ }
+ else if (m_maintainFocus > 0)
+ {
+ --m_maintainFocus;
+ }
+}
+
+int ExtensionContainer::arrangeHideButtons()
+{
+ bool layoutEnabled = _layout->isEnabled();
+
+ if (layoutEnabled)
+ {
+ _layout->setEnabled(false);
+ }
+
+ if (orientation() == Vertical)
+ {
+ int maxWidth = width();
+
+ if (needsBorder())
+ {
+ --maxWidth;
+ }
+
+ if (_ltHB)
+ {
+ _ltHB->setMaximumWidth(maxWidth);
+ _ltHB->setMaximumHeight(14);
+ _layout->remove(_ltHB);
+ _layout->addWidget(_ltHB, 0, 1, Qt::AlignBottom | Qt::AlignLeft);
+ }
+
+ if (_rbHB)
+ {
+ _rbHB->setMaximumWidth(maxWidth);
+ _rbHB->setMaximumHeight(14);
+ _layout->remove(_rbHB);
+ _layout->addWidget(_rbHB, 2, 1);
+ }
+ }
+ else
+ {
+ int maxHeight = height();
+
+ if (needsBorder())
+ {
+ --maxHeight;
+ }
+
+ int vertAlignment = (position() == KPanelExtension::Top) ? Qt::AlignTop : 0;
+ int leftAlignment = Qt::AlignRight;
+
+ if (_ltHB)
+ {
+ _ltHB->setMaximumHeight(maxHeight);
+ _ltHB->setMaximumWidth(14);
+ _layout->remove(_ltHB);
+ if (kapp->reverseLayout())
+ {
+ _layout->addWidget(_ltHB, 1, 2, vertAlignment);
+ }
+ else
+ {
+ _layout->addWidget(_ltHB, 1, 0, leftAlignment | vertAlignment);
+ }
+ }
+
+ if (_rbHB)
+ {
+ _rbHB->setMaximumHeight(maxHeight);
+ _rbHB->setMaximumWidth(14);
+ _layout->remove(_rbHB);
+ if (kapp->reverseLayout())
+ {
+ _layout->addWidget(_rbHB, 1, 0, leftAlignment | vertAlignment);
+ }
+ else
+ {
+ _layout->addWidget(_rbHB, 1, 2, vertAlignment);
+ }
+ }
+ }
+
+ int layoutOffset = setupBorderSpace();
+ if (layoutEnabled)
+ {
+ _layout->setEnabled(true);
+ }
+
+ return layoutOffset;
+}
+
+int ExtensionContainer::setupBorderSpace()
+{
+ _layout->setRowSpacing(0, 0);
+ _layout->setRowSpacing(2, 0);
+ _layout->setColSpacing(0, 0);
+ _layout->setColSpacing(2, 0);
+
+ if (!needsBorder())
+ {
+ return 0;
+ }
+
+ int layoutOffset = 0;
+ QRect r = QApplication::desktop()->screenGeometry(xineramaScreen());
+ QRect h = geometry();
+
+ if (orientation() == Vertical)
+ {
+ if (h.top() > 0)
+ {
+ int topHeight = (_ltHB && _ltHB->isVisibleTo(this)) ? _ltHB->height() + 1 : 1;
+ _layout->setRowSpacing(0, topHeight);
+ ++layoutOffset;
+ }
+
+ if (h.bottom() < r.bottom())
+ {
+ int bottomHeight = (_rbHB && _rbHB->isVisibleTo(this)) ? _rbHB->height() + 1 : 1;
+ _layout->setRowSpacing(1, bottomHeight);
+ ++layoutOffset;
+ }
+ }
+ else
+ {
+ if (h.left() > 0)
+ {
+ int leftWidth = (_ltHB && _ltHB->isVisibleTo(this)) ? _ltHB->width() + 1 : 1;
+ _layout->setColSpacing(0, leftWidth);
+ ++layoutOffset;
+ }
+
+ if (h.right() < r.right())
+ {
+ int rightWidth = (_rbHB && _rbHB->isVisibleTo(this)) ? _rbHB->width() + 1 : 1;
+ _layout->setColSpacing(1, rightWidth);
+ ++layoutOffset;
+ }
+ }
+
+ switch (position())
+ {
+ case KPanelExtension::Left:
+ _layout->setColSpacing(2, 1);
+ break;
+
+ case KPanelExtension::Right:
+ _layout->setColSpacing(0, 1);
+ break;
+
+ case KPanelExtension::Top:
+ _layout->setRowSpacing(2, 1);
+ break;
+
+ case KPanelExtension::Bottom:
+ default:
+ _layout->setRowSpacing(0, 1);
+ break;
+ }
+
+ return layoutOffset;
+}
+
+void ExtensionContainer::positionChange(KPanelExtension::Position p)
+{
+ arrangeHideButtons();
+
+ if (m_extension)
+ {
+ m_extension->setPosition(p);
+ }
+
+ update();
+}
+
+void ExtensionContainer::updateHighlightColor()
+{
+ KConfig *config = KGlobal::config();
+ config->setGroup("WM");
+ QColor color = QApplication::palette().active().highlight();
+ m_highlightColor = config->readColorEntry("activeBackground", &color);
+ update();
+}
+
+void ExtensionContainer::paintEvent(QPaintEvent *e)
+{
+ QFrame::paintEvent(e);
+
+ if (needsBorder())
+ {
+ // draw border
+ QPainter p(this);
+ if (KickerSettings::useBackgroundTheme() && KickerSettings::colorizeBackground())
+ p.setPen(m_highlightColor);
+ else
+ p.setPen(palette().color(QPalette::Active, QColorGroup::Mid));
+ p.drawRect(0, 0, width(), height());
+ }
+}
+
+void ExtensionContainer::leaveEvent(QEvent*)
+{
+ maybeStartAutoHideTimer();
+}
+
+void ExtensionContainer::alignmentChange(KPanelExtension::Alignment a)
+{
+ if (!m_extension)
+ {
+ return;
+ }
+
+ m_extension->setAlignment(a);
+}
+
+void ExtensionContainer::setSize(KPanelExtension::Size size, int custom)
+{
+ if (!m_extension)
+ {
+ return;
+ }
+
+ m_settings.setSize(size);
+ m_settings.setCustomSize(custom);
+ m_extension->setSize(size, custom);
+}
+
+KPanelExtension::Size ExtensionContainer::size() const
+{
+ // KConfigXT really needs to get support for vars that are enums that
+ // are defined in other classes
+ return static_cast<KPanelExtension::Size>(m_settings.size());
+}
+
+ExtensionContainer::HideMode ExtensionContainer::hideMode() const
+{
+ return m_hideMode;
+}
+
+void ExtensionContainer::unhideIfHidden(int showForAtLeastHowManyMS)
+{
+ if (_autoHidden)
+ {
+ autoHide(false);
+ QTimer::singleShot(showForAtLeastHowManyMS,
+ this, SLOT(maybeStartAutoHideTimer()));
+ return;
+ }
+
+ if (_userHidden == LeftTop)
+ {
+ animatedHide(true);
+ }
+ else if (_userHidden == RightBottom)
+ {
+ animatedHide(false);
+ }
+}
+
+void ExtensionContainer::setHideButtons(bool showLeft, bool showRight)
+{
+ if (m_settings.showLeftHideButton() == showLeft &&
+ m_settings.showRightHideButton() == showRight)
+ {
+ return;
+ }
+
+ m_settings.setShowLeftHideButton(showLeft);
+ m_settings.setShowRightHideButton(showRight);
+ resetLayout();
+}
+
+bool ExtensionContainer::event(QEvent* e)
+{
+ // Update the layout when we receive a LayoutHint. This way we can adjust
+ // to changes of the layout of the main widget.
+ if (e->type() == QEvent::LayoutHint)
+ {
+ updateLayout();
+ }
+
+ return QFrame::event(e);
+}
+
+void ExtensionContainer::closeEvent(QCloseEvent* e)
+{
+ // Prevent being closed via Alt-F4
+ e->ignore();
+}
+
+void ExtensionContainer::arrange(KPanelExtension::Position p,
+ KPanelExtension::Alignment a,
+ int XineramaScreen)
+{
+ if (p == m_settings.position() &&
+ a == m_settings.alignment() &&
+ XineramaScreen == xineramaScreen())
+ {
+ return;
+ }
+
+ bool positionChanged = p != m_settings.position();
+ if (positionChanged)
+ {
+ m_settings.setPosition(p);
+ }
+ else if (!needsBorder())
+ {
+ // this ensures that the layout gets rejigged
+ // even if position doesn't change
+ _layout->setRowSpacing(0, 0);
+ _layout->setRowSpacing(2, 0);
+ _layout->setColSpacing(0, 0);
+ _layout->setColSpacing(2, 0);
+ }
+
+ if (a != m_settings.alignment())
+ {
+ m_settings.setAlignment(a);
+ setAlignment(a);
+ }
+
+ if (XineramaScreen != xineramaScreen())
+ {
+ m_settings.setXineramaScreen(XineramaScreen);
+ xineramaScreenChange(XineramaScreen);
+ }
+
+ actuallyUpdateLayout();
+
+ if (positionChanged)
+ {
+ positionChange(p);
+ }
+ writeConfig();
+}
+
+KPanelExtension::Orientation ExtensionContainer::orientation() const
+{
+ if (position() == KPanelExtension::Top || position() == KPanelExtension::Bottom)
+ {
+ return Horizontal;
+ }
+ else
+ {
+ return Vertical;
+ }
+}
+
+KPanelExtension::Position ExtensionContainer::position() const
+{
+ // KConfigXT really needs to get support for vars that are enums that
+ // are defined in other classes
+ return static_cast<KPanelExtension::Position>(m_settings.position());
+}
+
+void ExtensionContainer::resetLayout()
+{
+ QRect g = initialGeometry(position(), alignment(), xineramaScreen(),
+ autoHidden(), userHidden());
+
+ // Disable the layout while we rearrange the panel.
+ // Necessary because the children may be
+ // relayouted with the wrong size.
+
+ _layout->setEnabled(false);
+
+ if (geometry() != g)
+ {
+ setGeometry(g);
+ ExtensionManager::the()->extensionSizeChanged(this);
+ }
+
+ // layout
+ bool haveToArrangeButtons = false;
+ bool showLeftHideButton = m_settings.showLeftHideButton() || userHidden() == RightBottom;
+ bool showRightHideButton = m_settings.showRightHideButton() || userHidden() == LeftTop;
+
+ // left/top hide button
+ if (showLeftHideButton)
+ {
+ if (!_ltHB)
+ {
+ _ltHB = new HideButton(this);
+ _ltHB->installEventFilter(this);
+ _ltHB->setEnabled(true);
+ connect(_ltHB, SIGNAL(clicked()), this, SLOT(hideLeft()));
+ haveToArrangeButtons = true;
+ }
+
+ if (orientation() == Horizontal)
+ {
+ _ltHB->setArrowType(Qt::LeftArrow);
+ _ltHB->setFixedSize(m_settings.hideButtonSize(), height());
+ }
+ else
+ {
+ _ltHB->setArrowType(Qt::UpArrow);
+ _ltHB->setFixedSize(width(), m_settings.hideButtonSize());
+ }
+
+ _ltHB->show();
+ }
+ else if (_ltHB)
+ {
+ _ltHB->hide();
+ }
+
+ // right/bottom hide button
+ if (showRightHideButton)
+ {
+ if (!_rbHB)
+ {
+ // right/bottom hide button
+ _rbHB = new HideButton(this);
+ _rbHB->installEventFilter(this);
+ _rbHB->setEnabled(true);
+ connect(_rbHB, SIGNAL(clicked()), this, SLOT(hideRight()));
+ haveToArrangeButtons = true;
+ }
+
+ if ( orientation() == Horizontal)
+ {
+ _rbHB->setArrowType(Qt::RightArrow);
+ _rbHB->setFixedSize(m_settings.hideButtonSize(), height());
+ }
+ else
+ {
+ _rbHB->setArrowType(Qt::DownArrow);
+ _rbHB->setFixedSize(width(), m_settings.hideButtonSize());
+ }
+
+ _rbHB->show();
+ }
+ else if (_rbHB)
+ {
+ _rbHB->hide();
+ }
+
+ if (_ltHB)
+ {
+ QToolTip::remove(_ltHB);
+ if (userHidden())
+ {
+ QToolTip::add(_ltHB, i18n("Show panel"));
+ }
+ else
+ {
+ QToolTip::add(_ltHB, i18n("Hide panel"));
+ }
+ }
+
+ if (_rbHB)
+ {
+ QToolTip::remove( _rbHB );
+ if (userHidden())
+ {
+ QToolTip::add(_rbHB, i18n("Show panel"));
+ }
+ else
+ {
+ QToolTip::add(_rbHB, i18n("Hide panel"));
+ }
+ }
+
+ updateGeometry();
+ int endBorderWidth = haveToArrangeButtons ? arrangeHideButtons() : setupBorderSpace();
+
+ if (orientation() == Horizontal)
+ {
+ if (m_extension)
+ {
+ int maxWidth = width() - endBorderWidth;
+
+ if (showLeftHideButton)
+ {
+ maxWidth -= _ltHB->width();
+ }
+
+ if (showRightHideButton)
+ {
+ maxWidth -= _rbHB->width();
+ }
+
+ m_extension->setMaximumWidth(maxWidth);
+
+ if (needsBorder())
+ {
+ m_extension->setFixedHeight(height() - 1);
+ }
+ else
+ {
+ m_extension->setFixedHeight(height());
+ }
+ }
+ }
+ else if (m_extension)
+ {
+ int maxHeight = height() - endBorderWidth;
+
+ if (showLeftHideButton)
+ {
+ maxHeight -= _ltHB->height();
+ }
+
+ if (showRightHideButton)
+ {
+ maxHeight -= _rbHB->height();
+ }
+
+ m_extension->setMaximumHeight(maxHeight);
+
+ if (needsBorder())
+ {
+ m_extension->setFixedWidth(width() - 1);
+ }
+ else
+ {
+ m_extension->setFixedWidth(width());
+ }
+ }
+
+ _layout->setEnabled(true);
+}
+
+bool ExtensionContainer::needsBorder() const
+{
+ return !KickerSettings::transparent();
+ //&& !KickerSettings::useBackgroundTheme();
+}
+
+QSize ExtensionContainer::initialSize(KPanelExtension::Position p, QRect workArea) const
+{
+ /*kdDebug(1210) << "initialSize() Work Area: (" << workArea.topLeft().x() <<
+ ", " << workArea.topLeft().y() << ") to (" << workArea.bottomRight().x() <<
+ ", " << workArea.bottomRight().y() << ")" << endl;*/
+
+ QSize hint = sizeHint(p, workArea.size()).boundedTo(workArea.size());
+ int width = 0;
+ int height = 0;
+
+ if (p == KPanelExtension::Left || p == KPanelExtension::Right)
+ {
+ width = hint.width();
+ height = (workArea.height() * m_settings.sizePercentage()) / 100;
+
+ if (m_settings.expandSize())
+ {
+ height = QMAX(height, hint.height());
+ }
+ }
+ else
+ {
+ width = (workArea.width() * m_settings.sizePercentage()) / 100;
+ height = hint.height();
+
+ if (m_settings.expandSize())
+ {
+ width = QMAX( width, hint.width() );
+ }
+ }
+
+ return QSize(width, height);
+}
+
+QPoint ExtensionContainer::initialLocation(KPanelExtension::Position p,
+ KPanelExtension::Alignment a,
+ int XineramaScreen,
+ const QSize &s,
+ QRect workArea,
+ bool autohidden,
+ UserHidden userHidden) const
+{
+ QRect wholeScreen;
+ if (XineramaScreen == XineramaAllScreens)
+ {
+ wholeScreen = QApplication::desktop()->geometry();
+ }
+ else
+ {
+ wholeScreen = QApplication::desktop()->screenGeometry(XineramaScreen);
+ }
+
+ /*kdDebug(1210) << "initialLocation() Work Area: (" <<
+ workArea.topLeft().x() << ", " <<
+ area.topLeft().y() << ") to (" <<
+ workArea.bottomRight().x() << ", " <<
+ workArea.bottomRight().y() << ")" << endl;*/
+
+ int left;
+ int top;
+
+ // If the panel is horizontal
+ if (p == KPanelExtension::Top || p == KPanelExtension::Bottom)
+ {
+ // Get the X coordinate
+ switch (a)
+ {
+ case KPanelExtension::LeftTop:
+ left = workArea.left();
+ break;
+
+ case KPanelExtension::Center:
+ {
+ left = wholeScreen.left() + ( wholeScreen.width() - s.width() ) / 2;
+ int right = left + s.width();
+ if (right > workArea.right())
+ {
+ left = left - (right - workArea.right());
+ }
+
+ if (left < workArea.left())
+ {
+ left = workArea.left();
+ }
+
+ break;
+ }
+
+ case KPanelExtension::RightBottom:
+ left = workArea.right() - s.width() + 1;
+ break;
+
+ default:
+ left = workArea.left();
+ break;
+ }
+
+ // Get the Y coordinate
+ if (p == KPanelExtension::Top)
+ {
+ top = workArea.top();
+ }
+ else
+ {
+ top = workArea.bottom() - s.height() + 1;
+ }
+ }
+ else // vertical panel
+ {
+ // Get the Y coordinate
+ switch (a)
+ {
+ case KPanelExtension::LeftTop:
+ top = workArea.top();
+ break;
+
+ case KPanelExtension::Center:
+ {
+ top = wholeScreen.top() + ( wholeScreen.height() - s.height() ) / 2;
+ int bottom = top + s.height();
+ if (bottom > workArea.bottom())
+ {
+ top = top - (bottom - workArea.bottom());
+ }
+
+ if (top < workArea.top())
+ {
+ top = workArea.top();
+ }
+ break;
+ }
+
+ case KPanelExtension::RightBottom:
+ top = workArea.bottom() - s.height() + 1;
+ break;
+
+ default:
+ top = workArea.top();
+ }
+
+ // Get the X coordinate
+ if (p == KPanelExtension::Left)
+ {
+ left = workArea.left();
+ }
+ else
+ {
+ left = workArea.right() - s.width() + 1;
+ }
+ }
+
+ // Correct for auto hide
+ if (autohidden)
+ {
+ switch (position())
+ {
+ case KPanelExtension::Left:
+ left -= s.width();
+ break;
+
+ case KPanelExtension::Right:
+ left += s.width();
+ break;
+
+ case KPanelExtension::Top:
+ top -= s.height();
+ break;
+
+ case KPanelExtension::Bottom:
+ default:
+ top += s.height();
+ break;
+ }
+ // Correct for user hide
+ }
+ else if (userHidden == LeftTop)
+ {
+ if (position() == KPanelExtension::Left || position() == KPanelExtension::Right)
+ {
+ top = workArea.top() - s.height() + m_settings.hideButtonSize();
+ }
+ else
+ {
+ left = workArea.left() - s.width() + m_settings.hideButtonSize();
+ }
+ }
+ else if (userHidden == RightBottom)
+ {
+ if (position() == KPanelExtension::Left || position() == KPanelExtension::Right)
+ {
+ top = workArea.bottom() - m_settings.hideButtonSize() + 1;
+ }
+ else
+ {
+ left = workArea.right() - m_settings.hideButtonSize() + 1;
+ }
+ }
+
+ return QPoint( left, top );
+}
+
+int ExtensionContainer::xineramaScreen() const
+{
+ // sanitize at runtime only, since many Xinerama users
+ // turn it on and off and don't want kicker to lose their configs
+
+ /* -2 means all screens, -1 primary screens, the rest are valid screen numbers */
+ if (XineramaAllScreens <= m_settings.xineramaScreen() &&
+ m_settings.xineramaScreen() < QApplication::desktop()->numScreens())
+ {
+ return m_settings.xineramaScreen();
+ }
+ else
+ {
+ /* force invalid screen locations onto the primary screen */
+ return QApplication::desktop()->primaryScreen();
+ }
+}
+
+void ExtensionContainer::setXineramaScreen(int screen)
+{
+ if (m_settings.isImmutable("XineramaScreen"))
+ {
+ return;
+ }
+
+ arrange(position(),alignment(), screen);
+}
+
+QRect ExtensionContainer::currentGeometry() const
+{
+ return initialGeometry(position(), alignment(), xineramaScreen(),
+ autoHidden(), userHidden());
+}
+
+QRect ExtensionContainer::initialGeometry(KPanelExtension::Position p,
+ KPanelExtension::Alignment a,
+ int XineramaScreen,
+ bool autoHidden,
+ UserHidden userHidden) const
+{
+ //RESEARCH: is there someway to cache the results of the repeated calls to this method?
+
+ /*kdDebug(1210) << "initialGeometry() Computing geometry for " << name() <<
+ " on screen " << XineramaScreen << endl;*/
+ QRect workArea = ExtensionManager::the()->workArea(XineramaScreen, this);
+ QSize size = initialSize(p, workArea);
+ QPoint point = initialLocation(p, a, XineramaScreen,
+ size, workArea,
+ autoHidden, userHidden);
+
+ //kdDebug(1210) << "Size: " << size.width() << " x " << size.height() << endl;
+ //kdDebug(1210) << "Pos: (" << point.x() << ", " << point.y() << ")" << endl;
+
+ return QRect(point, size);
+}
+
+bool ExtensionContainer::eventFilter( QObject*, QEvent * e)
+{
+ if (autoHidden())
+ {
+ switch ( e->type() )
+ {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ return true; // ignore;
+ default:
+ break;
+ }
+ }
+
+ QEvent::Type eventType = e->type();
+ if (_block_user_input)
+ {
+ return (eventType == QEvent::MouseButtonPress ||
+ eventType == QEvent::MouseButtonRelease ||
+ eventType == QEvent::MouseButtonDblClick ||
+ eventType == QEvent::MouseMove ||
+ eventType == QEvent::KeyPress ||
+ eventType == QEvent::KeyRelease ||
+ eventType == QEvent::Enter ||
+ eventType == QEvent::Leave);
+ }
+
+ switch (eventType)
+ {
+ case QEvent::MouseButtonPress:
+ {
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ if ( me->button() == LeftButton )
+ {
+ _last_lmb_press = me->globalPos();
+ _is_lmb_down = true;
+ }
+ else if (me->button() == RightButton)
+ {
+ showPanelMenu(me->globalPos());
+ return true; // don't crash!
+ }
+ }
+ break;
+
+ case QEvent::MouseButtonRelease:
+ {
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ if ( me->button() == LeftButton )
+ {
+ _is_lmb_down = false;
+ }
+ }
+ break;
+
+ case QEvent::MouseMove:
+ {
+ QMouseEvent* me = (QMouseEvent*) e;
+ if (_is_lmb_down &&
+ ((me->state() & LeftButton) == LeftButton) &&
+ !Kicker::the()->isImmutable() &&
+ !m_settings.config()->isImmutable() &&
+ !ExtensionManager::the()->isMenuBar(this))
+ {
+ QPoint p(me->globalPos() - _last_lmb_press);
+ int x_threshold = width();
+ int y_threshold = height();
+
+ if (x_threshold > y_threshold)
+ {
+ x_threshold = x_threshold / 3;
+ y_threshold *= 2;
+ }
+ else
+ {
+ y_threshold = y_threshold / 3;
+ x_threshold *= 2;
+ }
+
+ if ((abs(p.x()) > x_threshold) ||
+ (abs(p.y()) > y_threshold))
+ {
+ moveMe();
+ return true;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+PopupWidgetFilter::PopupWidgetFilter( QObject *parent )
+ : QObject( parent, "PopupWidgetFilter" )
+{
+}
+
+bool PopupWidgetFilter::eventFilter( QObject*, QEvent* e )
+{
+ if (e->type() == QEvent::Hide)
+ {
+ emit popupWidgetHiding();
+ }
+ return false;
+}
+
+#include "container_extension.moc"
+
diff --git a/kicker/kicker/core/container_extension.h b/kicker/kicker/core/container_extension.h
new file mode 100644
index 000000000..aebe048e6
--- /dev/null
+++ b/kicker/kicker/core/container_extension.h
@@ -0,0 +1,215 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __container_extension_h__
+#define __container_extension_h__
+
+#include <qframe.h>
+#include <qptrlist.h>
+
+#include <kpanelextension.h>
+#include <dcopobject.h>
+#include <netwm_def.h>
+
+#include "global.h"
+#include "appletinfo.h"
+#include "unhidetrigger.h"
+#include "extensionSettings.h"
+
+class QBoxLayout;
+class QGridLayout;
+class QPopupMenu;
+class QTimer;
+class QVBox;
+class QXEmbed;
+class HideButton;
+class KConfig;
+class KWinModule;
+class PopupWidgetFilter;
+class PanelExtensionOpMenu;
+class QColor;
+
+class ExtensionContainer : public QFrame
+{
+ Q_OBJECT
+
+public:
+ enum UserHidden { Unhidden, LeftTop, RightBottom };
+ enum HideMode { ManualHide, AutomaticHide, BackgroundHide };
+
+ ExtensionContainer(const AppletInfo& info,
+ const QString& extensionId,
+ QWidget *parent = 0);
+ ExtensionContainer(KPanelExtension* extension,
+ const AppletInfo& info,
+ const QString& extensionId,
+ QWidget *parent = 0);
+ virtual ~ExtensionContainer();
+
+ virtual QSize sizeHint(KPanelExtension::Position, const QSize &maxSize) const;
+
+ const AppletInfo& info() const { return _info; }
+
+ QString extensionId() const { return _id; }
+
+ void readConfig();
+ void writeConfig();
+
+ virtual QString panelId() const { return extensionId(); }
+
+ virtual void about();
+ virtual void help();
+ virtual void preferences();
+ virtual void reportBug();
+
+ void removeSessionConfigFile();
+
+ KPanelExtension::Orientation orientation() const;
+ KPanelExtension::Position position() const;
+ void setPosition(KPanelExtension::Position p) { arrange( p, alignment(), xineramaScreen() ); }
+
+ int xineramaScreen() const;
+ void setXineramaScreen(int screen);
+
+ void setResizeableHandle( bool resizeablehandle=true );
+ void setHideButtons(bool showLeft, bool showRight);
+ void setSize(KPanelExtension::Size size, int custom);
+ KPanelExtension::Size size() const;
+ int customSize() const { return m_settings.customSize(); }
+ HideMode hideMode() const;
+ void unhideIfHidden(int showForHowManyMS = 0);
+ bool reserveStrut() const;
+
+ KPanelExtension::Alignment alignment() const;
+ void setAlignment(KPanelExtension::Alignment a) { arrange( position(), a, xineramaScreen() ); }
+
+ QRect currentGeometry() const;
+ QRect initialGeometry(KPanelExtension::Position p, KPanelExtension::Alignment a,
+ int XineramaScreen, bool autoHidden = false,
+ UserHidden userHidden = Unhidden) const;
+
+ bool eventFilter( QObject *, QEvent * );
+
+ int panelOrder() const { return m_panelOrder; }
+ void setPanelOrder(int order) { m_panelOrder = order; }
+
+signals:
+ void removeme(ExtensionContainer*);
+
+protected slots:
+ virtual void showPanelMenu( const QPoint& pos );
+ void moveMe();
+ void updateLayout();
+ void actuallyUpdateLayout();
+ void enableMouseOverEffects();
+ void updateHighlightColor();
+
+protected:
+ bool event(QEvent*);
+ void closeEvent( QCloseEvent* e );
+ void paintEvent(QPaintEvent*);
+ void leaveEvent(QEvent*);
+
+ void arrange(KPanelExtension::Position p, KPanelExtension::Alignment a, int XineramaScreen);
+ bool autoHidden() const { return _autoHidden; };
+ UserHidden userHidden() const { return _userHidden; };
+ void resetLayout();
+ bool needsBorder() const;
+
+private slots:
+ void unhideTriggered( UnhideTrigger::Trigger t, int XineramaScreen );
+ void autoHideTimeout();
+ void hideLeft();
+ void hideRight();
+ void autoHide(bool hide);
+ void animatedHide(bool left);
+ void updateWindowManager();
+ void currentDesktopChanged(int);
+ void strutChanged();
+ void blockUserInput( bool block );
+ void maybeStartAutoHideTimer();
+ void stopAutoHideTimer();
+ void maintainFocus(bool);
+
+private:
+ bool shouldUnhideForTrigger(UnhideTrigger::Trigger t) const;
+ void init();
+ QSize initialSize(KPanelExtension::Position p, QRect workArea) const;
+ QPoint initialLocation(KPanelExtension::Position p, KPanelExtension::Alignment a,
+ int XineramaScreen, const QSize &s, QRect workArea,
+ bool autohidden = false, UserHidden userHidden = Unhidden) const;
+ void positionChange(KPanelExtension::Position p);
+ void alignmentChange(KPanelExtension::Alignment a);
+ void xineramaScreenChange(int /*XineramaScreen*/) {}
+ int arrangeHideButtons();
+ int setupBorderSpace();
+
+ ExtensionSettings m_settings;
+ ExtensionContainer::HideMode m_hideMode;
+ UnhideTrigger::Trigger m_unhideTriggeredAt;
+
+ // State variables
+ bool _autoHidden;
+ UserHidden _userHidden;
+ bool _block_user_input;
+ QPoint _last_lmb_press;
+ bool _is_lmb_down;
+ bool _in_autohide;
+
+ // Misc objects
+ QTimer *_autohideTimer;
+ QTimer *_updateLayoutTimer;
+ NETExtendedStrut _strut;
+ PopupWidgetFilter *_popupWidgetFilter;
+
+ QString _id;
+ PanelExtensionOpMenu *_opMnu;
+ AppletInfo _info;
+ KPanelExtension::Type _type;
+
+ // Widgets
+ HideButton *_ltHB; // Left Hide Button
+ HideButton *_rbHB; // Right Hide Button
+ QGridLayout *_layout;
+
+ KPanelExtension *m_extension;
+ int m_maintainFocus;
+ int m_panelOrder;
+ QColor m_highlightColor;
+};
+
+class PopupWidgetFilter : public QObject
+{
+ Q_OBJECT
+
+ public:
+ PopupWidgetFilter( QObject *parent );
+ ~PopupWidgetFilter() {}
+ bool eventFilter( QObject *obj, QEvent* e );
+ signals:
+ void popupWidgetHiding();
+};
+
+typedef QValueList<ExtensionContainer*> ExtensionList;
+
+#endif
diff --git a/kicker/kicker/core/containerarea.cpp b/kicker/kicker/core/containerarea.cpp
new file mode 100644
index 000000000..23732e684
--- /dev/null
+++ b/kicker/kicker/core/containerarea.cpp
@@ -0,0 +1,1939 @@
+/*****************************************************************
+
+Copyright (c) 1996-2004 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <unistd.h>
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+#include <qwmatrix.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kiconloader.h>
+#include <kmimetype.h>
+#include <kprocess.h>
+#include <krootpixmap.h>
+#include <kpixmap.h>
+#include <klocale.h>
+#include <kio/netaccess.h>
+#include <kservice.h>
+#include <kurldrag.h>
+
+#include "addapplet.h"
+#include "browser_dlg.h"
+#include "container_applet.h"
+#include "container_button.h"
+#include "containerarealayout.h"
+#include "dirdrop_mnu.h"
+#include "exe_dlg.h"
+#include "extensionmanager.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "kickertip.h"
+#include "paneldrag.h"
+#include "pluginmanager.h"
+
+#include "containerarea.h"
+
+// for multihead
+extern int kicker_screen_number;
+
+ContainerArea::ContainerArea(KConfig* _c,
+ QWidget* parent,
+ QPopupMenu* opMenu,
+ const char* name)
+ : Panner(parent, name),
+ _moveAC(0),
+ _pos(KPanelExtension::Left),
+ _config(_c),
+ _dragIndicator(0),
+ _dragMoveAC(0),
+ _dragMoveOffset(QPoint(0,0)),
+ m_opMenu(opMenu),
+ _rootPixmap(0),
+ _useBgTheme(false),
+ _bgSet(false),
+ m_canAddContainers(true),
+ m_immutable(_c->isImmutable()),
+ m_updateBackgroundsCalled(false),
+ m_layout(0),
+ m_addAppletDialog(0)
+{
+ setBackgroundOrigin( WidgetOrigin );
+
+ m_contents = viewport();
+
+ m_layout = new ContainerAreaLayout(m_contents);
+
+ // Install an event filter to propagate layout hints coming from m_contents.
+ m_contents->installEventFilter(this);
+
+ setBackground();
+
+ connect(&_autoScrollTimer, SIGNAL(timeout()), SLOT(autoScroll()));
+ connect(kapp, SIGNAL(kdisplayPaletteChanged()), SLOT(setBackground()));
+ connect(Kicker::the(), SIGNAL(immutabilityChanged(bool)),
+ SLOT(immutabilityChanged(bool)));
+ connect(this, SIGNAL(contentsMoving(int, int)), SLOT(setBackground()));
+}
+
+ContainerArea::~ContainerArea()
+{
+ // don't emit signals from destructor
+ blockSignals( true );
+ // clear applets
+ removeAllContainers();
+}
+
+void ContainerArea::initialize(bool useDefaultConfig)
+{
+ // do we really need to do this?
+ removeAllContainers();
+
+ // restore applet layout or load a default panel layout
+ _config->setGroup("General");
+ if (_config->hasKey("Applets2"))
+ {
+ if (_config->groupIsImmutable("General"))
+ {
+ m_immutable = true;
+ }
+
+ m_canAddContainers = !m_immutable &&
+ !_config->entryIsImmutable("Applets2");
+ loadContainers(_config->readListEntry("Applets2"));
+ }
+ else if (useDefaultConfig)
+ {
+ defaultContainerConfig();
+ }
+
+ setAcceptDrops(!isImmutable());
+ QTimer::singleShot(0, this, SLOT(resizeContents()));
+}
+
+void ContainerArea::defaultContainerConfig()
+{
+ //FIXME: make this use a file template so it isn't hardcoded anymore
+ BaseContainer::List containers;
+
+ containers.append(new KMenuButtonContainer(m_opMenu, m_contents));
+
+ int dsize;
+ if (orientation() == Qt::Horizontal)
+ {
+ dsize = width();
+ }
+ else
+ {
+ dsize = height();
+ }
+
+ dsize -= 560;
+ QStringList buttons;
+
+ QFile f(locate("data", "kicker/default-apps"));
+ if (f.open(IO_ReadOnly))
+ {
+ QTextStream is(&f);
+
+ while (!is.eof())
+ buttons << is.readLine();
+
+ f.close();
+ }
+ else
+ {
+ buttons << "kde-Home.desktop"
+ << "kde-konqbrowser.desktop";
+ }
+
+ //int size = dsize;
+ for (QStringList::ConstIterator it = buttons.begin(); it != buttons.end(); ++it)
+ {
+ /*size -= 42;
+ if (size <= 0)
+ break;*/
+
+ BaseContainer *button = 0;
+ KService::Ptr service = KService::serviceByStorageId(*it);
+ if (!service)
+ {
+ // look for a special button
+ QString s = locate("appdata", *it);
+ if (s.isEmpty()) continue;
+ QString itExt = (*it).section('/', 1);
+ button = new ExtensionButtonContainer(itExt, m_opMenu, m_contents);
+ }
+ else
+ {
+ button = new ServiceButtonContainer(service, m_opMenu, m_contents);
+ }
+
+ if (button->isValid())
+ {
+ containers.append(button);
+ }
+ else
+ {
+ delete button;
+ }
+ }
+
+ PluginManager* manager = PluginManager::the();
+
+ // pager applet
+ AppletContainer* a = manager->createAppletContainer(
+ "minipagerapplet.desktop",
+ true,
+ QString::null,
+ m_opMenu,
+ m_contents);
+ if (a)
+ {
+ a->setFreeSpace(0.09);
+ containers.append(a);
+ }
+
+ // taskbar applet
+ a = manager->createAppletContainer(
+ "taskbarapplet.desktop",
+ true,
+ QString::null,
+ m_opMenu,
+ m_contents);
+ if (a)
+ {
+ a->setFreeSpace(0.09);
+ containers.append(a);
+ }
+
+ // system tray applet
+ a = manager->createAppletContainer(
+ "systemtrayapplet.desktop",
+ true,
+ QString::null,
+ m_opMenu,
+ m_contents );
+ if (a)
+ {
+ a->setFreeSpace(1);
+ containers.append(a);
+ }
+
+ // clock applet
+ a = manager->createAppletContainer(
+ "clockapplet.desktop",
+ true,
+ QString::null,
+ m_opMenu,
+ m_contents );
+ if (a)
+ {
+ a->setFreeSpace(1);
+ containers.append(a);
+ }
+
+ for (BaseContainer::Iterator it = containers.begin();
+ it != containers.end();
+ ++it)
+ {
+ addContainer(*it);
+ }
+
+ saveContainerConfig();
+}
+
+void ContainerArea::loadContainers(const QStringList& containers)
+{
+ // read applet list
+ bool badApplets = false;
+
+ // now restore the applets
+ QStringList::const_iterator it = containers.constBegin();
+ QStringList::const_iterator itEnd = containers.constEnd();
+ for (; it != itEnd; ++it)
+ {
+ QString appletId(*it);
+
+ // is there a config group for this applet?
+ if (!_config->hasGroup(appletId))
+ {
+ continue;
+ }
+
+ KConfigGroup group(_config, appletId.latin1());
+
+ BaseContainer* a = 0;
+
+ int sep = appletId.findRev('_');
+ Q_ASSERT(sep != -1);
+ QString appletType = appletId.left(sep);
+
+ // create a matching applet container
+ if (appletType == "KMenuButton")
+ a = new KMenuButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "DesktopButton")
+ a = new DesktopButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "WindowListButton")
+ a = new WindowListButtonContainer(group, m_opMenu, m_contents);
+ else if ((appletType == "BookmarksButton") && kapp->authorizeKAction("bookmarks"))
+ a = new BookmarksButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "ServiceButton")
+ a = new ServiceButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "URLButton")
+ a = new URLButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "BrowserButton")
+ a = new BrowserButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "ServiceMenuButton")
+ a = new ServiceMenuButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "ExecButton")
+ a = new NonKDEAppButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "ExtensionButton")
+ a = new ExtensionButtonContainer(group, m_opMenu, m_contents);
+ else if (appletType == "Applet")
+ {
+ bool immutable = Kicker::the()->isImmutable() ||
+ group.groupIsImmutable() ||
+ group.entryIsImmutable("ConfigFile");
+ a = PluginManager::the()->createAppletContainer(
+ group.readPathEntry("DesktopFile"),
+ true, // isStartup
+ group.readPathEntry("ConfigFile"),
+ m_opMenu,
+ m_contents,
+ immutable);
+ }
+
+ if (a && a->isValid())
+ {
+ a->setAppletId(appletId);
+ a->loadConfiguration(group);
+ addContainer(a);
+ }
+ else
+ {
+ badApplets = true;
+ delete a;
+ }
+ }
+
+ if (badApplets)
+ {
+ // since we may have had Bad Applets in our list
+ // let's save it again, just in case
+ saveContainerConfig();
+ }
+
+ // while this is also called in addContainer (well, resizeContents()),
+ // it gets executed too soon. we need to wait until the containers are
+ // actually resized, but we enter the event loop prior to that happening
+ // above.
+ QTimer::singleShot(0, this, SLOT(updateContainersBackground()));
+}
+
+void ContainerArea::saveContainerConfig(bool layoutOnly)
+{
+ if (!canAddContainers())
+ {
+ return;
+ }
+
+ // Save the applet list
+ QStringList alist;
+ QLayoutIterator it2 = m_layout->iterator();
+ for (; it2.current(); ++it2)
+ {
+ BaseContainer* a = dynamic_cast<BaseContainer*>(it2.current()->widget());
+ if (a)
+ {
+ KConfigGroup group(_config, a->appletId().latin1());
+ a->saveConfiguration(group, layoutOnly);
+ alist.append(a->appletId());
+ }
+ }
+
+ KConfigGroup group( _config, "General" );
+ group.writeEntry("Applets2", alist);
+
+ _config->sync();
+}
+
+void ContainerArea::removeAllContainers()
+{
+ for (BaseContainer::List::const_iterator it = m_containers.constBegin();
+ it != m_containers.constEnd();
+ ++it)
+ {
+ delete *it;
+ }
+ m_containers.clear();
+}
+
+void ContainerArea::configure()
+{
+ setBackground();
+
+ for (BaseContainer::Iterator it = m_containers.begin();
+ it != m_containers.end();
+ ++it)
+ {
+ (*it)->configure();
+ }
+
+ resizeContents();
+}
+
+const QWidget* ContainerArea::addButton(const AppletInfo& info)
+{
+ QString buttonType = info.library();
+
+ if (buttonType == "BookmarksButton")
+ {
+ if (kapp->authorizeKAction("bookmarks"))
+ {
+ return addBookmarksButton();
+ }
+ }
+ else if (buttonType == "BrowserButton")
+ {
+ return addBrowserButton();
+ }
+ else if (buttonType == "DesktopButton")
+ {
+ return addDesktopButton();
+ }
+ else if (buttonType == "ExecButton")
+ {
+ return addNonKDEAppButton();
+ }
+ else if (buttonType == "KMenuButton")
+ {
+ return addKMenuButton();
+ }
+ else if (buttonType == "WindowListButton")
+ {
+ return addWindowListButton();
+ }
+ else // ExtensionButton
+ {
+ return addExtensionButton(info.desktopFile());
+ }
+
+ return 0;
+}
+
+const QWidget* ContainerArea::addKMenuButton()
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new KMenuButtonContainer(m_opMenu, m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addDesktopButton()
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new DesktopButtonContainer(m_opMenu, m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addWindowListButton()
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new WindowListButtonContainer(m_opMenu, m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addBookmarksButton()
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new BookmarksButtonContainer(m_opMenu, m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addServiceButton(const QString& desktopFile)
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new ServiceButtonContainer(desktopFile,m_opMenu,
+ m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addURLButton(const QString &url)
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new URLButtonContainer(url, m_opMenu, m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addBrowserButton()
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ PanelBrowserDialog *dlg = new PanelBrowserDialog(QDir::home().path(),
+ "kdisknav");
+
+ if (dlg->exec() == QDialog::Accepted)
+ {
+ return addBrowserButton(dlg->path(), dlg->icon());
+ }
+
+ return 0;
+}
+
+const QWidget* ContainerArea::addBrowserButton(const QString &startDir,
+ const QString& icon)
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new BrowserButtonContainer(startDir, m_opMenu,
+ icon, m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addServiceMenuButton(const QString& relPath)
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new ServiceMenuButtonContainer(relPath, m_opMenu,
+ m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addNonKDEAppButton()
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ PanelExeDialog dlg(QString::null, QString::null, QString::null,
+ QString::null, QString::null, false, 0);
+
+ if (dlg.exec() == QDialog::Accepted)
+ {
+ return addNonKDEAppButton(dlg.title(), dlg.description(),
+ dlg.command(), dlg.iconPath(),
+ dlg.commandLine(),
+ dlg.useTerminal());
+ }
+
+ return 0;
+}
+
+const QWidget* ContainerArea::addNonKDEAppButton(const QString &name,
+ const QString &description,
+ const QString& filePath,
+ const QString &icon,
+ const QString &cmdLine,
+ bool inTerm)
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer *b = new NonKDEAppButtonContainer(name,
+ description,
+ filePath, icon,
+ cmdLine, inTerm,
+ m_opMenu, m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+const QWidget* ContainerArea::addExtensionButton(const QString& df)
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ BaseContainer* b = new ExtensionButtonContainer(df,
+ m_opMenu,
+ m_contents);
+ completeContainerAddition(b);
+ return b;
+}
+
+void ContainerArea::completeContainerAddition(BaseContainer* container,
+ int index)
+{
+ //FIXME: the original comment was:
+ // Set freespace to one since the container will be added at the end.
+ // yet this is not always true =/
+ container->setFreeSpace(1);
+ addContainer(container, true, index);
+ scrollTo(container);
+ saveContainerConfig();
+}
+
+AppletContainer* ContainerArea::addApplet(const AppletInfo& info,
+ bool isImmutable,
+ int insertionIndex)
+{
+ if (!canAddContainers())
+ {
+ return 0;
+ }
+
+ AppletContainer* a = PluginManager::the()->createAppletContainer(
+ info.desktopFile(),
+ false, // not startup
+ QString::null, // no config
+ m_opMenu,
+ m_contents,
+ isImmutable);
+
+ if (!a || !a->isValid())
+ {
+ delete a;
+ return 0;
+ }
+
+ completeContainerAddition(a, insertionIndex);
+ return a;
+}
+
+void ContainerArea::addContainer(BaseContainer* a, bool arrange, int index)
+{
+ if (!a)
+ {
+ return;
+ }
+
+ if (a->appletId().isNull())
+ {
+ a->setAppletId(createUniqueId(a->appletType()));
+ }
+
+ m_containers.append(a);
+
+ if (arrange)
+ {
+ QWidget* w = m_layout->widgetAt(index);
+ QPoint oldInsertionPoint = Kicker::the()->insertionPoint();
+ if (w)
+ {
+ // let's set the insertion point to where the widget asked to be
+ // put in front of is
+ Kicker::the()->setInsertionPoint(w->geometry().topLeft());
+ }
+
+ if (Kicker::the()->insertionPoint().isNull())
+ {
+ m_layout->insertIntoFreeSpace(a, QPoint());
+ }
+ else
+ {
+ m_layout->insertIntoFreeSpace(a, mapFromGlobal(Kicker::the()->insertionPoint()));
+ }
+
+ if (w)
+ {
+ Kicker::the()->setInsertionPoint(oldInsertionPoint);
+ }
+ }
+ else
+ {
+ m_layout->add(a);
+ }
+
+ connect(a, SIGNAL(moveme(BaseContainer*)),
+ SLOT(startContainerMove(BaseContainer*)));
+ connect(a, SIGNAL(removeme(BaseContainer*)),
+ SLOT(removeContainer(BaseContainer*)));
+ connect(a, SIGNAL(takeme(BaseContainer*)),
+ SLOT(takeContainer(BaseContainer*)));
+ connect(a, SIGNAL(requestSave()),
+ SLOT(slotSaveContainerConfig()));
+ connect(a, SIGNAL(maintainFocus(bool)),
+ this, SIGNAL(maintainFocus(bool)));
+
+ if (dynamic_cast<AppletContainer*>(a))
+ {
+ connect(a, SIGNAL(updateLayout()), SLOT(resizeContents()));
+ }
+
+ a->configure(orientation(), popupDirection());
+ a->show();
+ resizeContents();
+}
+
+bool ContainerArea::removeContainer(BaseContainer *a)
+{
+ if (!a || isImmutable() || a->isImmutable())
+ {
+ return false;
+ }
+
+ a->slotRemoved(_config);
+ m_containers.remove(a);
+ m_layout->remove(a);
+ a->deleteLater();
+ saveContainerConfig(true);
+ resizeContents();
+ return true;
+}
+
+bool ContainerArea::removeContainer(int index)
+{
+ if (isImmutable())
+ {
+ return false;
+ }
+
+ BaseContainer* a = dynamic_cast<BaseContainer*>(m_layout->widgetAt(index));
+ if (!a || a->isImmutable())
+ {
+ return false;
+ }
+
+ a->slotRemoved(_config);
+ m_containers.remove(a);
+ m_layout->remove(a);
+ a->deleteLater();
+ saveContainerConfig(true);
+ resizeContents();
+ return true;
+}
+
+void ContainerArea::removeContainers(BaseContainer::List containers)
+{
+ if (isImmutable())
+ {
+ return;
+ }
+
+ m_layout->setEnabled(false);
+
+ for (BaseContainer::List::const_iterator it = containers.constBegin();
+ it != containers.constEnd();
+ ++it)
+ {
+ BaseContainer* a = *it;
+ if (a->isImmutable())
+ {
+ continue;
+ }
+
+ a->slotRemoved(_config);
+ m_containers.remove(a);
+ m_layout->remove(a);
+ a->deleteLater();
+ }
+
+ m_layout->setEnabled(true);
+ saveContainerConfig(true);
+ resizeContents();
+}
+
+void ContainerArea::takeContainer(BaseContainer* a)
+{
+ if (!a)
+ {
+ return;
+ }
+
+ disconnect(a, SIGNAL(moveme(BaseContainer*)),
+ this, SLOT(startContainerMove(BaseContainer*)));
+ disconnect(a, SIGNAL(removeme(BaseContainer*)),
+ this, SLOT(removeContainer(BaseContainer*)));
+ disconnect(a, SIGNAL(takeme(BaseContainer*)),
+ this, SLOT(takeContainer(BaseContainer*)));
+ disconnect(a, SIGNAL(requestSave()),
+ this, SLOT(slotSaveContainerConfig()));
+ disconnect(a, SIGNAL(maintainFocus(bool)),
+ this, SIGNAL(maintainFocus(bool)));
+
+ // Just remove the group from our own config file. Leave separate config
+ // files untouched.
+ _config->deleteGroup(a->appletId().latin1());
+ _config->sync();
+ m_containers.remove(a);
+ m_layout->remove(a);
+ saveContainerConfig(true);
+ resizeContents();
+}
+
+void ContainerArea::resizeContents()
+{
+ int w = width();
+ int h = height();
+
+ if (orientation() == Qt::Horizontal)
+ {
+ int newWidth = m_layout->widthForHeight(h);
+ if (newWidth > w)
+ {
+ resizeContents(newWidth, h);
+ }
+ else
+ {
+ resizeContents(w, h);
+ }
+ }
+ else
+ {
+ int newHeight = m_layout->heightForWidth(w);
+
+ if (newHeight > h)
+ {
+ resizeContents(w, newHeight);
+ }
+ else
+ {
+ resizeContents(w, h);
+ }
+ }
+}
+
+QString ContainerArea::createUniqueId(const QString& appletType) const
+{
+ QString idBase = appletType + "_%1";
+ QString newId;
+ int i = 0;
+ bool unique = false;
+
+ while (!unique)
+ {
+ i++;
+ newId = idBase.arg(i);
+
+ unique = true;
+ for (BaseContainer::ConstIterator it = m_containers.begin();
+ it != m_containers.end();
+ ++it)
+ {
+ BaseContainer* b = *it;
+ if (b->appletId() == newId)
+ {
+ unique = false;
+ break;
+ }
+ }
+ }
+
+ return newId;
+}
+
+bool ContainerArea::canAddContainers() const
+{
+ return m_canAddContainers && Kicker::the()->canAddContainers();
+}
+
+void ContainerArea::startContainerMove(BaseContainer *a)
+{
+ if (!a || isImmutable())
+ {
+ return;
+ }
+
+ _moveAC = a;
+
+ KickerTip::enableTipping(false);
+ emit maintainFocus(true);
+ setMouseTracking(true);
+ grabMouse(sizeAllCursor);
+
+ m_layout->setStretchEnabled(false);
+ a->raise();
+}
+
+void ContainerArea::mouseReleaseEvent(QMouseEvent *)
+{
+ if (!_moveAC)
+ {
+ return;
+ }
+
+ // start container move was caled successfuly
+ // so we need to complete the move here
+ _autoScrollTimer.stop();
+ releaseMouse();
+ setCursor(arrowCursor);
+ setMouseTracking(false);
+
+ _moveAC->completeMoveOperation();
+ KickerTip::enableTipping(true);
+
+ _moveAC = 0;
+
+ emit maintainFocus(false);
+ m_layout->setStretchEnabled(true);
+ updateContainersBackground();
+ saveContainerConfig(true);
+}
+
+void ContainerArea::mouseMoveEvent(QMouseEvent *ev)
+{
+ if (!_moveAC)
+ {
+ Panner::mouseMoveEvent(ev);
+ return;
+ }
+
+ if (ev->state() == LeftButton && !rect().contains(ev->pos()))
+ {
+ // leaveEvent() doesn't work, while grabbing the mouse
+ _autoScrollTimer.stop();
+ releaseMouse();
+ setCursor(arrowCursor);
+ setMouseTracking(false);
+
+ _moveAC->completeMoveOperation();
+ KickerTip::enableTipping(true);
+
+ emit maintainFocus(false);
+ m_layout->setStretchEnabled(true);
+ updateContainersBackground();
+ saveContainerConfig(true);
+
+ PanelDrag *dd = new PanelDrag(_moveAC, this);
+ dd->setPixmap(kapp->iconLoader()->loadIcon(_moveAC->icon(), KIcon::Small));
+ grabKeyboard();
+ dd->drag();
+ releaseKeyboard();
+ return;
+ }
+
+ if (orientation() == Horizontal)
+ {
+ int oldX = _moveAC->x() + _moveAC->moveOffset().x();
+ int x = ev->pos().x() + contentsX();
+ if (ev->state() & ShiftButton)
+ {
+ m_layout->moveContainerPush(_moveAC, x - oldX);
+ }
+ else
+ {
+ m_layout->moveContainerSwitch(_moveAC, x - oldX);
+ /* FIXME: Scrolling when the container moves out of the viewport
+ bool scroll = false;
+ if (rtl)
+ if (newPos - 80 <= 0)
+ scroll = true;
+ else
+ if (newPos + 80 >= (horizontal ? geometry().width() - moving->geometry().width()
+ : geometry().height() - moving->geometry().height()))
+ scroll = true;
+ [...]
+ if (scroll) {
+ if (!_autoScrollTimer.isActive())
+ _autoScrollTimer.start(50);
+
+ if (horizontal)
+ scrollBy(dir*10, 0);
+ else
+ scrollBy(0, dir*10);
+ }
+ */
+ }
+ }
+ else
+ {
+ int oldY = _moveAC->y() + _moveAC->moveOffset().y();
+ int y = ev->pos().y() + contentsY();
+ if (ev->state() & ShiftButton)
+ {
+ m_layout->moveContainerPush(_moveAC, y - oldY);
+ }
+ else
+ {
+ m_layout->moveContainerSwitch(_moveAC, y - oldY);
+ // TODO: Scrolling
+ }
+ }
+
+ ensureVisible(ev->pos().x() + contentsX(), ev->pos().y() + contentsY());
+ updateContainersBackground();
+}
+
+int ContainerArea::position() const
+{
+ return static_cast<int>(_pos);
+}
+
+KPanelApplet::Direction ContainerArea::popupDirection() const
+{
+ return KickerLib::positionToDirection(_pos);
+}
+
+bool ContainerArea::isImmutable() const
+{
+ return m_immutable || Kicker::the()->isImmutable();
+}
+
+void ContainerArea::dragEnterEvent(QDragEnterEvent *ev)
+{
+ bool canAccept = !isImmutable() &&
+ (PanelDrag::canDecode(ev) ||
+ AppletInfoDrag::canDecode(ev) ||
+ KURLDrag::canDecode(ev));
+ ev->accept(canAccept);
+
+ if (!canAccept)
+ {
+ return;
+ }
+
+ m_layout->setStretchEnabled(false);
+
+ if (!_dragIndicator)
+ {
+ _dragIndicator = new DragIndicator(m_contents);
+ }
+
+ BaseContainer *draggedContainer = 0;
+ int preferedWidth = height();
+ int preferedHeight = width();
+ if (PanelDrag::decode(ev, &draggedContainer))
+ {
+ preferedWidth = draggedContainer->widthForHeight(height());
+ preferedHeight = draggedContainer->heightForWidth(width());
+ }
+
+ if (orientation() == Horizontal)
+ {
+ _dragIndicator->setPreferredSize(QSize(preferedWidth, height()));
+ }
+ else
+ {
+ _dragIndicator->setPreferredSize(QSize(width(), preferedHeight));
+ }
+ _dragMoveOffset = QPoint(_dragIndicator->width()/2,
+ _dragIndicator->height()/2);
+
+ // Find the container before the position of the dragindicator.
+ BaseContainer::Iterator it = m_containers.end();
+
+ if (it != m_containers.begin())
+ {
+ do
+ {
+ --it;
+ BaseContainer* a = *it;
+
+ if ((orientation() == Horizontal &&
+ a->x() < (ev->pos().x() + contentsX()) - _dragMoveOffset.x()) ||
+ (orientation() == Vertical &&
+ a->y() < (ev->pos().y() + contentsY()) - _dragMoveOffset.y()))
+ {
+ _dragMoveAC = a;
+ break;
+ }
+ } while (it != m_containers.begin());
+ }
+
+ if (orientation() == Horizontal)
+ {
+ moveDragIndicator(ev->pos().x() + contentsX() - _dragMoveOffset.x());
+ }
+ else
+ {
+ moveDragIndicator(ev->pos().y() + contentsY() - _dragMoveOffset.y());
+ }
+
+ _dragIndicator->show();
+}
+
+void ContainerArea::dragMoveEvent(QDragMoveEvent* ev)
+{
+ if (ev->source() == this)
+ {
+ // Abort the drag and go back to container sliding.
+ // Actually, this should be placed in dragEnterEvent(), but
+ // then it does work only on every second event.
+
+ // Cancel the drag by faking an Escape keystroke.
+ QKeyEvent fakedKeyPress(QEvent::KeyPress, Key_Escape, 0, 0);
+ QKeyEvent fakedKeyRelease(QEvent::KeyRelease, Key_Escape, 0, 0);
+ QApplication::sendEvent(this, &fakedKeyPress);
+ QApplication::sendEvent(this, &fakedKeyRelease);
+ qApp->processEvents();
+ startContainerMove(_moveAC);
+
+ // Align the container to the mouse position.
+ if (orientation() == Horizontal)
+ {
+ m_layout->moveContainerSwitch(_moveAC, ev->pos().x() + contentsX() - _moveAC->x());
+ }
+ else
+ {
+ m_layout->moveContainerSwitch(_moveAC, ev->pos().y() + contentsY() - _moveAC->y());
+ }
+ return;
+ }
+
+ if (!_dragIndicator)
+ {
+ return;
+ }
+
+ if (orientation() == Horizontal)
+ {
+ moveDragIndicator(ev->pos().x() + contentsX() - _dragMoveOffset.x());
+ }
+ else
+ {
+ moveDragIndicator(ev->pos().y() + contentsY() - _dragMoveOffset.y());
+ }
+}
+
+void ContainerArea::dragLeaveEvent(QDragLeaveEvent*)
+{
+ if (_dragIndicator)
+ {
+ _dragIndicator->hide();
+ }
+ m_layout->setStretchEnabled(true);
+ _dragMoveAC = 0;
+}
+
+void ContainerArea::dropEvent(QDropEvent *ev)
+{
+ if (!_dragIndicator)
+ {
+ // we assume that this is the result of a successful drag enter
+ // which means we'll have a _dragIndicator. if for
+ // some reason we don't, let's not go down this code path
+ return;
+ }
+
+ BaseContainer *a = 0;
+ if (PanelDrag::decode(ev, &a))
+ {
+ if (!a)
+ {
+ _dragMoveAC = 0;
+ _dragIndicator->hide();
+ m_layout->setStretchEnabled(true);
+ return;
+ }
+
+ QObject *parent = ev->source() ? ev->source()->parent() : 0;
+ while (parent && (parent != this))
+ {
+ parent = parent->parent();
+ }
+
+ if (parent)
+ {
+ // Move container a
+ if (orientation() == Horizontal)
+ {
+ int oldX = a->x();
+ int x = _dragIndicator->x();
+ m_layout->moveContainerSwitch(a, x - oldX);
+ }
+ else if (orientation() == Vertical)
+ {
+ int oldY = a->y();
+ int y = _dragIndicator->y();
+ m_layout->moveContainerSwitch(a, y - oldY);
+ }
+
+ _dragMoveAC = 0;
+ _dragIndicator->hide();
+ m_layout->setEnabled(true);
+ m_layout->setStretchEnabled(true);
+ saveContainerConfig(true);
+ return;
+ }
+
+ // it came from another panel
+ Kicker::the()->setInsertionPoint(_dragIndicator->pos());
+ a->reparent(m_contents, 0, _dragIndicator->pos(), true);
+ a->setAppletId(createUniqueId(a->appletType()));
+ addContainer(a, true);
+ Kicker::the()->setInsertionPoint(QPoint());
+ m_layout->updateFreeSpaceValues();
+ _dragMoveAC = 0;
+ _dragIndicator->hide();
+ m_layout->setStretchEnabled(true);
+ saveContainerConfig();
+ return;
+ }
+
+ // is it an applet info?
+ AppletInfo info;
+ if (AppletInfoDrag::decode(ev, info))
+ {
+ Kicker::the()->setInsertionPoint(_dragIndicator->pos());
+ _dragIndicator->hide();
+ m_layout->setStretchEnabled(true);
+
+ if (info.type() & AppletInfo::Button)
+ {
+ addButton(info);
+ }
+ else if (info.type() == AppletInfo::Applet)
+ {
+ addApplet(info);
+ }
+
+ Kicker::the()->setInsertionPoint(QPoint());
+ return;
+ }
+
+ // ok, let's try a KURL drag
+ KURL::List uriList;
+ if (!KURLDrag::decode(ev, uriList))
+ {
+ _dragMoveAC = 0;
+ _dragIndicator->hide();
+ m_layout->setStretchEnabled(true);
+ return;
+ }
+
+ Kicker::the()->setInsertionPoint(_dragIndicator->pos());
+
+ KURL::List::ConstIterator it(uriList.begin());
+ for (; it != uriList.end(); ++it)
+ {
+ const KURL &url = *it;
+
+ // Create a new PanelButton for this URL.
+
+ // see if it's a executable or directory
+ if (url.protocol() == "programs")
+ {
+ QString relPath = url.path();
+ if (relPath[0] == '/')
+ {
+ relPath = relPath.right(relPath.length() - 1);
+ }
+ a = new ServiceMenuButtonContainer(relPath, m_opMenu, m_contents);
+ }
+ else if (url.isLocalFile())
+ {
+ QFileInfo fi(url.path());
+ if (fi.isDir())
+ { // directory
+ switch (PanelDirDropMenu().exec(mapToGlobal(ev->pos())))
+ {
+ case PanelDirDropMenu::Browser:
+ a = new BrowserButtonContainer(url.path(), m_opMenu,
+ KMimeType::iconForURL(url), m_contents);
+ break;
+ case PanelDirDropMenu::Url:
+ a = new URLButtonContainer(url.url(), m_opMenu, m_contents);
+ break;
+ default: ;
+ }
+ }
+ else if ( KMimeType::findByURL(url)->name() == "application/x-desktop" )
+ {
+ // a local desktop file being dragged from an external program.
+ // Make a copy first.
+ KDesktopFile df(url.path());
+ KURL newUrl;
+ newUrl.setPath(KickerLib::copyDesktopFile(url));
+ if (df.readType() == "Link")
+ a = new URLButtonContainer(newUrl.url(), m_opMenu, m_contents);
+ else
+ a = new ServiceButtonContainer(newUrl.path(), m_opMenu, m_contents);
+ }
+ else if (fi.isExecutable())
+ {
+ // non-KDE executable
+ QString pixmapFile;
+ KMimeType::pixmapForURL(url, 0, KIcon::Panel, 0,
+ KIcon::DefaultState, &pixmapFile);
+ PanelExeDialog dlg(QString::null, QString::null, url.path(),
+ pixmapFile, QString::null, false, 0);
+ if (dlg.exec() == QDialog::Accepted)
+ {
+ // KIconloader returns a full path, we only want the name
+ QFileInfo iconfi(dlg.iconPath());
+ a = new NonKDEAppButtonContainer(dlg.title(),
+ dlg.description(),
+ dlg.command(),
+ iconfi.fileName(),
+ dlg.commandLine(),
+ dlg.useTerminal(),
+ m_opMenu,
+ m_contents);
+ }
+ }
+ else // some unknown local file
+ {
+ a = new URLButtonContainer(url.url(), m_opMenu, m_contents);
+ }
+ }
+ else // a internet URL
+ {
+ a = new URLButtonContainer(url.url(), m_opMenu, m_contents);
+ }
+
+ if (!a)
+ {
+ _dragIndicator->hide();
+ Kicker::the()->setInsertionPoint(QPoint());
+ m_layout->setStretchEnabled(true);
+ return;
+ }
+
+ addContainer(a, true);
+ m_layout->updateFreeSpaceValues();
+ }
+
+ saveContainerConfig();
+ _dragMoveAC = 0;
+ _dragIndicator->hide();
+ Kicker::the()->setInsertionPoint(QPoint());
+ m_layout->setStretchEnabled(true);
+}
+
+bool ContainerArea::eventFilter(QObject* o, QEvent* e)
+{
+ // Propagate the layout hints which m_contents receives. This way widgets
+ // which contain a ContainerArea can react to layout changes of its
+ // contents. For example: If an applets grows, the top level widget may
+ // want to grow as well.
+ if (o == m_contents)
+ {
+ if (e->type() == QEvent::LayoutHint)
+ {
+ updateGeometry(); // Posts a new layout hint to our parent.
+ }
+ return false;
+ }
+
+ return Panner::eventFilter(o, e);
+}
+
+void ContainerArea::resizeEvent(QResizeEvent *ev)
+{
+ Panner::resizeEvent(ev);
+ setBackground();
+}
+
+void ContainerArea::viewportResizeEvent(QResizeEvent* ev)
+{
+ Panner::viewportResizeEvent(ev);
+ if (orientation() == Horizontal)
+ {
+ m_contents->resize(kMax(widthForHeight(ev->size().height()),
+ ev->size().width()),
+ ev->size().height());
+ }
+ else
+ {
+ m_contents->resize(ev->size().width(),
+ kMax(heightForWidth(ev->size().width()),
+ ev->size().height()));
+ }
+ resizeContents(m_contents->width(), m_contents->height());
+}
+
+void ContainerArea::setBackground()
+{
+ _bgSet = false;
+ m_cachedGeometry.clear();
+
+ if (KickerSettings::transparent() &&
+ (KickerSettings::menubarPanelTransparent() ||
+ !ExtensionManager::the()->isMenuBar(topLevelWidget())))
+ {
+ if (!_rootPixmap)
+ {
+ _rootPixmap = new KRootPixmap(this);
+ _rootPixmap->setCustomPainting(true);
+ connect(_rootPixmap, SIGNAL(backgroundUpdated(const QPixmap&)),
+ SLOT(updateBackground(const QPixmap&)));
+ }
+ else
+ {
+ _rootPixmap->repaint(true);
+ }
+
+ double tint = double(KickerSettings::tintValue()) / 100;
+ _rootPixmap->setFadeEffect(tint, KickerSettings::tintColor());
+ _rootPixmap->start();
+ _bgSet = true;
+ return;
+ }
+ else if (_rootPixmap)
+ {
+ delete _rootPixmap;
+ _rootPixmap = 0;
+ }
+
+ unsetPalette();
+
+ if (KickerSettings::useBackgroundTheme())
+ {
+ // by keeping the src image static, we can share it among panels and only
+ // reload from disk when it actually changes in the config, not every time we
+ // get a resize or configure event
+ static QString bgStr;
+ static QImage srcImage;
+ QString newBgStr = locate("appdata", KickerSettings::backgroundTheme());
+
+ if (bgStr != newBgStr)
+ {
+ bgStr = newBgStr;
+ srcImage.load(bgStr);
+ }
+
+ if (srcImage.isNull())
+ {
+ KickerSettings::setUseBackgroundTheme(false);
+ }
+ else
+ {
+ QImage bgImage = srcImage;
+
+ if (orientation() == Vertical)
+ {
+ if (KickerSettings::rotateBackground())
+ {
+ QWMatrix matrix;
+ matrix.rotate(position() == KPanelExtension::Left ? 90: 270);
+ bgImage = bgImage.xForm(matrix);
+ }
+
+ bgImage = bgImage.scaleWidth( size().width() );
+ }
+ else
+ {
+ if (position() == KPanelExtension::Top &&
+ KickerSettings::rotateBackground())
+ {
+ QWMatrix matrix;
+ matrix.rotate(180);
+ bgImage = bgImage.xForm(matrix);
+ }
+
+ bgImage = bgImage.scaleHeight( size().height() );
+ }
+
+ if (KickerSettings::colorizeBackground())
+ {
+ KickerLib::colorize(bgImage);
+ }
+ setPaletteBackgroundPixmap(QPixmap(bgImage));
+ QTimer::singleShot(0, this, SLOT(updateContainersBackground()));
+ }
+ }
+
+ _bgSet = true;
+}
+
+void ContainerArea::immutabilityChanged(bool immutable)
+{
+ // we set all the child container's immutability here instead of connecting
+ // the immutabilityChanged signal up everywhere so that we can control the
+ // order of immutability changing and the background being updated. since
+ // immutability implies applet handle visibility, those things must happen
+ // first before updating our background.
+ for (BaseContainer::ConstIterator it = m_containers.constBegin();
+ it != m_containers.constEnd();
+ ++it)
+ {
+ (*it)->setImmutable(immutable);
+ }
+
+ setAcceptDrops(!isImmutable());
+ QTimer::singleShot(0, this, SLOT(setBackground()));
+}
+
+QRect ContainerArea::availableSpaceFollowing(BaseContainer* a)
+{
+ QRect availableSpace = rect();
+ BaseContainer* b = 0;
+
+ if (a)
+ {
+ BaseContainer::Iterator it = m_containers.find(a);
+ if (it != m_containers.end() &&
+ ++it != m_containers.end())
+ {
+ b = (*it);
+ }
+ }
+
+ if (!b)
+ {
+ BaseContainer::Iterator it = m_containers.begin();
+ if (it != m_containers.end())
+ {
+ b = (*it);
+ }
+ }
+
+ if (orientation() == Horizontal)
+ {
+ if (a)
+ {
+ availableSpace.setLeft(a->x() + a->width());
+ }
+
+ if (b)
+ {
+ availableSpace.setRight(b->x() - 1);
+ }
+ }
+ else
+ {
+ if (a)
+ {
+ availableSpace.setTop(a->y() + a->height());
+ }
+
+ if (b)
+ {
+ availableSpace.setBottom(b->y() - 1);
+ }
+ }
+
+ return availableSpace;
+}
+
+void ContainerArea::moveDragIndicator(int pos)
+{
+ QRect availableSpace = availableSpaceFollowing(_dragMoveAC);
+
+ // Move _dragIndicator to position pos, restricted by availableSpace.
+ // Resize _dragIndicator if necessary.
+ if (orientation() == Horizontal)
+ {
+ if (availableSpace.size().width() <
+ _dragIndicator->preferredSize().width())
+ {
+ _dragIndicator->resize(availableSpace.size());
+ _dragIndicator->move(availableSpace.topLeft());
+ }
+ else
+ {
+ int newX = pos;
+ _dragIndicator->resize(_dragIndicator->preferredSize());
+ newX = QMAX(newX, availableSpace.left());
+ newX = QMIN(newX,
+ availableSpace.right() + 1 - _dragIndicator->width() );
+ _dragIndicator->move(newX, availableSpace.top());
+ }
+ }
+ else
+ {
+ if (availableSpace.size().height() <
+ _dragIndicator->preferredSize().height())
+ {
+ _dragIndicator->resize(availableSpace.size());
+ _dragIndicator->move(availableSpace.topLeft());
+ }
+ else
+ {
+ int newY = pos;
+ _dragIndicator->resize(_dragIndicator->preferredSize());
+ newY = QMAX(newY, availableSpace.top());
+ newY = QMIN(newY,
+ availableSpace.bottom() + 1 - _dragIndicator->height() );
+ _dragIndicator->move(availableSpace.left(), newY);
+ }
+ }
+}
+
+void ContainerArea::updateBackground( const QPixmap& pm )
+{
+ QBrush bgBrush(colorGroup().background(), pm);
+ QPalette pal = kapp->palette();
+ pal.setBrush(QColorGroup::Background, bgBrush);
+ setPalette(pal);
+
+ // because the Pixmap can be smaller as the containerarea
+ // we construct a pixmap the same size as we are that every
+ // applet or button can use to cut out its background
+ _completeBg.resize(width(), height());
+ _completeBg.fill(this, 0, 0);
+
+ m_cachedGeometry.clear();
+ updateContainersBackground();
+}
+
+void ContainerArea::resizeContents(int w, int h)
+{
+ // this looks silly but is required otherwise (some?) c++ compilers can't see
+ // Panner::resizeContents(int, int) due to the overloaded ContainerArea::resizeContents()
+ Panner::resizeContents(w, h);
+
+ if (!m_updateBackgroundsCalled)
+ {
+ m_updateBackgroundsCalled = true;
+ QTimer::singleShot(0, this, SLOT(updateContainersBackground()));
+ }
+}
+
+void ContainerArea::slotSaveContainerConfig()
+{
+ saveContainerConfig();
+}
+
+void ContainerArea::setPosition(KPanelExtension::Position p)
+{
+ if (_pos == p)
+ {
+ return;
+ }
+
+ _pos = p;
+ Qt::Orientation o = (p == KPanelExtension::Top ||
+ p == KPanelExtension::Bottom) ?
+ Qt::Horizontal : Qt::Vertical;
+ bool orientationChanged = (orientation() != o);
+ m_layout->setEnabled(false);
+
+ if (orientationChanged)
+ {
+ setOrientation(o);
+ m_layout->setOrientation(o);
+
+ // when we change orientation, we will resize the "width"
+ // component down to 0, forcing a resize in resizeContents()
+ // when that gets called AFTER we've been moved
+ // it's not always safe to do the resize here, as scroll buttons
+ // from the panner may get in our way. =/
+ if (o == Horizontal)
+ {
+ resizeContents(0, height());
+ }
+ else
+ {
+ resizeContents(width(), 0);
+ }
+ }
+
+ for (BaseContainer::ConstIterator it = m_containers.constBegin();
+ it != m_containers.constEnd();
+ ++it)
+ {
+ if (orientationChanged)
+ {
+ (*it)->setOrientation(o);
+ }
+
+ (*it)->setPopupDirection( popupDirection() );
+ }
+
+ m_layout->setEnabled(true);
+
+ setContentsPos(0, 0);
+ m_contents->move(0, 0);
+ setBackground();
+
+ // container extension repaints for us!
+ //repaint();
+}
+
+void ContainerArea::setAlignment(KPanelExtension::Alignment a)
+{
+ for (BaseContainer::ConstIterator it = m_containers.begin();
+ it != m_containers.end();
+ ++it)
+ {
+ (*it)->setAlignment(a);
+ }
+}
+
+void ContainerArea::autoScroll()
+{
+ if(!_moveAC) return;
+
+ if(orientation() == Horizontal) {
+ if(_moveAC->pos().x() <= 80)
+ scrollBy(-10, 0);
+ else if(_moveAC->pos().x() >= width() - _moveAC->width() - 80)
+ scrollBy(10, 0);
+ }
+ else {
+ if(_moveAC->pos().y() <= 80)
+ scrollBy(0, -10);
+ else if(_moveAC->pos().y() >= height() - _moveAC->height() - 80)
+ scrollBy(0, 10);
+ }
+}
+
+void ContainerArea::scrollTo(BaseContainer* b)
+{
+ if (!b)
+ {
+ return;
+ }
+
+ int x, y;
+ viewportToContents(b->pos().x(), b->pos().y(), x, y);
+ ensureVisible(x, y);
+}
+
+void ContainerArea::updateContainersBackground()
+{
+ m_updateBackgroundsCalled = false;
+
+ if (!_bgSet)
+ {
+ return;
+ }
+
+ for (BaseContainer::ConstIterator it = m_containers.constBegin();
+ it != m_containers.constEnd();
+ ++it)
+ {
+ // A rather ugly hack. The code calls updateContainersBackground() all over
+ // the place even when nothing in fact has changed. Updating the background
+ // on every single unrelated change however means that e.g. the systray
+ // flickers when a new window is opened/closed (because the taskbar is relayouted,
+ // which triggers updateContainersBackground() even though the geometry
+ // of the taskbar does not change in fact. I'm apparently unable to fix this
+ // properly, so just cache the geometry and update background only when
+ // the geometry changes or when the background really changes (in which
+ // case the cached is cleared).
+ if( !m_cachedGeometry.contains( *it ))
+ {
+ m_cachedGeometry[ *it ] = QRect();
+ connect( *it, SIGNAL( destroyed()), SLOT( destroyCachedGeometry()));
+ }
+ if( m_cachedGeometry[ *it ] != (*it)->geometry())
+ {
+ (*it)->setBackground();
+ m_cachedGeometry[ *it ] = (*it)->geometry();
+ }
+ }
+}
+
+void ContainerArea::destroyCachedGeometry()
+{
+ m_cachedGeometry.remove(const_cast<QWidget*>(static_cast<const QWidget*>(sender())));
+}
+
+BaseContainer::List ContainerArea::containers(const QString& type) const
+{
+ if (type.isEmpty() || type == "All")
+ {
+ return m_containers;
+ }
+
+ BaseContainer::List list;
+
+ if (type == "Special Button")
+ {
+ for (BaseContainer::ConstIterator it = m_containers.constBegin();
+ it != m_containers.constEnd();
+ ++it)
+ {
+ QString type = (*it)->appletType();
+ if (type == "KMenuButton" ||
+ type == "WindowListButton" ||
+ type == "BookmarksButton" ||
+ type == "DesktopButton" ||
+ type == "BrowserButton" ||
+ type == "ExecButton" ||
+ type == "ExtensionButton")
+ {
+ list.append(*it);
+ }
+ }
+
+ return list;
+ }
+
+ for (BaseContainer::ConstIterator it = m_containers.constBegin();
+ it != m_containers.constEnd();
+ ++it)
+ {
+ if ((*it)->appletType() == type)
+ {
+ list.append(*it);
+ }
+ }
+
+ return list;
+}
+
+int ContainerArea::containerCount(const QString& type) const
+{
+ if (type.isEmpty() || type == "All")
+ {
+ return m_containers.count();
+ }
+
+ int count = 0;
+ if (type == "Special Button")
+ {
+ for (BaseContainer::ConstIterator it = m_containers.begin();
+ it != m_containers.end();
+ ++it)
+ {
+ QString type = (*it)->appletType();
+ if (type == "KMenuButton" ||
+ type == "WindowListButton" ||
+ type == "BookmarksButton" ||
+ type == "DesktopButton" ||
+ type == "BrowserButton" ||
+ type == "ExecButton" ||
+ type == "ExtensionButton")
+ {
+ ++count;
+ }
+ }
+
+ return count;
+ }
+
+ for (BaseContainer::ConstIterator it = m_containers.begin();
+ it != m_containers.end();
+ ++it)
+ {
+ if ((*it)->appletType() == type)
+ {
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+QStringList ContainerArea::listContainers() const
+{
+ return m_layout->listItems();
+}
+
+void ContainerArea::repaint()
+{
+ Panner::repaint();
+}
+
+void ContainerArea::showAddAppletDialog()
+{
+ if (!m_addAppletDialog)
+ {
+ m_addAppletDialog = new AddAppletDialog(this, this, 0);
+ connect(m_addAppletDialog, SIGNAL(finished()), this, SLOT(addAppletDialogDone()));
+ }
+ else
+ {
+ // this ensures that if we get shown again via the menu
+ // that the dialog picks up
+ // the new place to insert things
+ m_addAppletDialog->updateInsertionPoint();
+ }
+
+ KWin::setOnDesktop(m_addAppletDialog->winId(), KWin::currentDesktop());
+ m_addAppletDialog->show();
+ m_addAppletDialog->raise();
+}
+
+void ContainerArea::addAppletDialogDone()
+{
+ m_addAppletDialog->deleteLater();
+ m_addAppletDialog = 0;
+}
+
+const QPixmap* ContainerArea::completeBackgroundPixmap() const
+{
+ return &_completeBg;
+}
+
+int ContainerArea::widthForHeight(int h) const
+{
+ return m_layout->widthForHeight(h);
+}
+
+int ContainerArea::heightForWidth(int w) const
+{
+ return m_layout->heightForWidth(w);
+}
+
+
+DragIndicator::DragIndicator(QWidget* parent, const char* name)
+ : QWidget(parent, name)
+{
+ setBackgroundOrigin(AncestorOrigin);
+}
+
+
+void DragIndicator::paintEvent(QPaintEvent*)
+{
+ QPainter painter(this);
+ QRect rect(0, 0, width(), height());
+ style().drawPrimitive( QStyle::PE_FocusRect, &painter, rect, colorGroup(),
+ QStyle::Style_Default, colorGroup().base() );
+}
+
+void DragIndicator::mousePressEvent(QMouseEvent*)
+{
+ hide();
+}
+
+#include "containerarea.moc"
diff --git a/kicker/kicker/core/containerarea.h b/kicker/kicker/core/containerarea.h
new file mode 100644
index 000000000..8b17c8ae9
--- /dev/null
+++ b/kicker/kicker/core/containerarea.h
@@ -0,0 +1,195 @@
+/*****************************************************************
+
+Copyright (c) 1996-2004 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __containerarea_h__
+#define __containerarea_h__
+
+#include <qpixmap.h>
+#include <qptrlist.h>
+#include <qtimer.h>
+
+#include <appletinfo.h>
+
+#include "global.h"
+#include "panner.h"
+#include "container_base.h"
+
+class KConfig;
+class DragIndicator;
+class PanelContainer;
+class KRootPixmap;
+
+class AppletContainer;
+class ContainerAreaLayout;
+class AddAppletDialog;
+
+class ContainerArea : public Panner
+{
+ Q_OBJECT
+
+public:
+ ContainerArea( KConfig* config, QWidget* parent, QPopupMenu* opMenu, const char* name = 0 );
+ ~ContainerArea();
+
+ void initialize(bool useDefaultConfig);
+ int position() const;
+ KPanelApplet::Direction popupDirection() const;
+ bool isImmutable() const;
+
+ const QWidget* addButton(const AppletInfo& info);
+ const QWidget* addKMenuButton();
+ const QWidget* addDesktopButton();
+ const QWidget* addWindowListButton();
+ const QWidget* addBookmarksButton();
+ const QWidget* addServiceButton(const QString& desktopFile);
+ const QWidget* addURLButton(const QString &url);
+ const QWidget* addBrowserButton();
+ const QWidget* addBrowserButton(const QString &startDir,
+ const QString& icon = QString("kdisknav"));
+ const QWidget* addServiceMenuButton(const QString& relPath);
+ const QWidget* addNonKDEAppButton();
+ const QWidget* addNonKDEAppButton(const QString &name,
+ const QString &description,
+ const QString &filePath,
+ const QString &icon,
+ const QString &cmdLine, bool inTerm);
+ const QWidget* addExtensionButton(const QString& desktopFile);
+ AppletContainer* addApplet(const AppletInfo& info,
+ bool isImmutable = false,
+ int insertionIndex = -1);
+
+ void configure();
+
+ bool inMoveOperation() const { return (_moveAC != 0); }
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+
+ const QPixmap* completeBackgroundPixmap() const;
+
+ BaseContainer::List containers(const QString& type) const;
+ int containerCount(const QString& type) const;
+ QStringList listContainers() const;
+ bool canAddContainers() const;
+
+signals:
+ void maintainFocus(bool);
+
+public slots:
+ void resizeContents(int w, int h);
+ bool removeContainer(BaseContainer* a);
+ bool removeContainer(int index);
+ void removeContainers(BaseContainer::List containers);
+ void takeContainer(BaseContainer* a);
+ void setPosition(KPanelExtension::Position p);
+ void setAlignment(KPanelExtension::Alignment a);
+ void slotSaveContainerConfig();
+ void repaint();
+ void showAddAppletDialog();
+ void addAppletDialogDone();
+
+protected:
+ QString createUniqueId(const QString& appletType) const;
+ void completeContainerAddition(BaseContainer* container,
+ int insertionIndex = -1);
+
+ bool eventFilter(QObject*, QEvent*);
+ void mouseMoveEvent(QMouseEvent*);
+ void mouseReleaseEvent(QMouseEvent *);
+ void dragEnterEvent(QDragEnterEvent*);
+ void dragMoveEvent(QDragMoveEvent*);
+ void dragLeaveEvent(QDragLeaveEvent*);
+ void dropEvent(QDropEvent*);
+ void resizeEvent(QResizeEvent*);
+ void viewportResizeEvent(QResizeEvent*);
+
+ void defaultContainerConfig();
+ void loadContainers(const QStringList& containers);
+ void saveContainerConfig(bool layoutOnly = false);
+
+ QRect availableSpaceFollowing(BaseContainer*);
+ void moveDragIndicator(int pos);
+
+ void scrollTo(BaseContainer*);
+
+ void addContainer(BaseContainer* a,
+ bool arrange = false,
+ int insertionIndex = -1);
+ void removeAllContainers();
+
+protected slots:
+ void autoScroll();
+ void updateBackground(const QPixmap&);
+ void setBackground();
+ void immutabilityChanged(bool);
+ void updateContainersBackground();
+ void startContainerMove(BaseContainer*);
+ void resizeContents();
+ void destroyCachedGeometry();
+
+private:
+ BaseContainer::List m_containers;
+ BaseContainer* _moveAC;
+ KPanelExtension::Position _pos;
+ KConfig* _config;
+ DragIndicator* _dragIndicator;
+ BaseContainer* _dragMoveAC;
+ QPoint _dragMoveOffset;
+ QPopupMenu* m_opMenu;
+ KRootPixmap* _rootPixmap;
+ bool _transparent;
+ bool _useBgTheme;
+ bool _bgSet;
+ QPixmap _completeBg;
+ QTimer _autoScrollTimer;
+ bool m_canAddContainers;
+ bool m_immutable;
+ bool m_updateBackgroundsCalled;
+
+ QWidget* m_contents;
+ ContainerAreaLayout* m_layout;
+ AddAppletDialog* m_addAppletDialog;
+ QMap< QWidget*, QRect > m_cachedGeometry;
+};
+
+
+class DragIndicator : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DragIndicator(QWidget* parent = 0, const char* name = 0);
+ ~DragIndicator() {}
+
+ QSize preferredSize() const { return _preferredSize; }
+ void setPreferredSize(const QSize& size) { _preferredSize = size; }
+
+protected:
+ void paintEvent(QPaintEvent*);
+ void mousePressEvent(QMouseEvent*);
+
+private:
+ QSize _preferredSize;
+};
+
+#endif
+
diff --git a/kicker/kicker/core/containerarealayout.cpp b/kicker/kicker/core/containerarealayout.cpp
new file mode 100644
index 000000000..a865bec86
--- /dev/null
+++ b/kicker/kicker/core/containerarealayout.cpp
@@ -0,0 +1,803 @@
+/*****************************************************************
+
+Copyright (c) 1996-2004 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include <qapplication.h>
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include "containerarea.h"
+#include "containerarealayout.h"
+#include "container_applet.h"
+#include "container_button.h"
+
+class ContainerAreaLayoutIterator : public QGLayoutIterator
+{
+ public:
+ ContainerAreaLayoutIterator(ContainerAreaLayout::ItemList *l)
+ : m_idx(0), m_list(l)
+ {
+ }
+
+ QLayoutItem* current()
+ {
+ return m_idx < int(m_list->count()) ? (*m_list->at(m_idx))->item : 0;
+ }
+
+ QLayoutItem* next()
+ {
+ m_idx++;
+ return current();
+ }
+
+ QLayoutItem* takeCurrent()
+ {
+ QLayoutItem* item = 0;
+ ContainerAreaLayout::ItemList::iterator b = m_list->at(m_idx);
+ if (b != m_list->end())
+ {
+ ContainerAreaLayoutItem* layoutItem = *b;
+ item = layoutItem->item;
+ layoutItem->item = 0;
+ m_list->erase(b);
+ delete layoutItem;
+ }
+ return item;
+ }
+
+ private:
+ int m_idx;
+ ContainerAreaLayout::ItemList* m_list;
+};
+
+
+int ContainerAreaLayoutItem::heightForWidth(int w) const
+{
+ BaseContainer* container = dynamic_cast<BaseContainer*>(item->widget());
+ if (container)
+ {
+ return container->heightForWidth(w);
+ }
+ else
+ {
+ return item->sizeHint().height();
+ }
+}
+
+int ContainerAreaLayoutItem::widthForHeight(int h) const
+{
+ BaseContainer* container = dynamic_cast<BaseContainer*>(item->widget());
+ if (container)
+ {
+ return container->widthForHeight(h);
+ }
+ else
+ {
+ return item->sizeHint().width();
+ }
+}
+
+bool ContainerAreaLayoutItem::isStretch() const
+{
+ BaseContainer* container = dynamic_cast<BaseContainer*>(item->widget());
+ return container ? container->isStretch() : false;
+}
+
+double ContainerAreaLayoutItem::freeSpaceRatio() const
+{
+ BaseContainer* container = dynamic_cast<BaseContainer*>(item->widget());
+ if (container)
+ return kClamp(container->freeSpace(), 0.0, 1.0);
+ else
+ return m_freeSpaceRatio;
+}
+
+void ContainerAreaLayoutItem::setFreeSpaceRatio(double ratio)
+{
+ BaseContainer* container = dynamic_cast<BaseContainer*>(item->widget());
+ if (container)
+ container->setFreeSpace(ratio);
+ else
+ m_freeSpaceRatio = ratio;
+}
+
+Qt::Orientation ContainerAreaLayoutItem::orientation() const
+{
+ return m_layout->orientation();
+}
+
+QRect ContainerAreaLayoutItem::geometryR() const
+{
+ return m_layout->transform(geometry());
+}
+
+void ContainerAreaLayoutItem::setGeometryR(const QRect& r)
+{
+ setGeometry(m_layout->transform(r));
+}
+
+int ContainerAreaLayoutItem::widthForHeightR(int h) const
+{
+ if (orientation() == Horizontal)
+ {
+ return widthForHeight(h);
+ }
+ else
+ {
+ return heightForWidth(h);
+ }
+}
+
+int ContainerAreaLayoutItem::widthR() const
+{
+ if (orientation() == Horizontal)
+ {
+ return geometry().width();
+ }
+ else
+ {
+ return geometry().height();
+ }
+}
+
+int ContainerAreaLayoutItem::heightR() const
+{
+ if (orientation() == Horizontal)
+ {
+ return geometry().height();
+ }
+ else
+ {
+ return geometry().width();
+ }
+}
+
+int ContainerAreaLayoutItem::leftR() const
+{
+ if (orientation() == Horizontal)
+ {
+ if (QApplication::reverseLayout())
+ return m_layout->geometry().right() - geometry().right();
+ else
+ return geometry().left();
+ }
+ else
+ {
+ return geometry().top();
+ }
+}
+
+int ContainerAreaLayoutItem::rightR() const
+{
+ if (orientation() == Horizontal)
+ {
+ if (QApplication::reverseLayout())
+ return m_layout->geometry().right() - geometry().left();
+ else
+ return geometry().right();
+ }
+ else
+ {
+ return geometry().bottom();
+ }
+}
+
+
+ContainerAreaLayout::ContainerAreaLayout(QWidget* parent)
+ : QLayout(parent),
+ m_orientation(Horizontal),
+ m_stretchEnabled(true)
+{
+}
+
+void ContainerAreaLayout::addItem(QLayoutItem* item)
+{
+ m_items.append(new ContainerAreaLayoutItem(item, this));
+}
+
+void ContainerAreaLayout::insertIntoFreeSpace(QWidget* widget, QPoint insertionPoint)
+{
+ if (!widget)
+ {
+ return;
+ }
+
+ add(widget);
+ ContainerAreaLayoutItem* item = m_items.last();
+
+ if (!item)
+ {
+ // this should never happen as we just added the item above
+ // but we do this to be safe.
+ return;
+ }
+
+ ItemList::iterator currentIt = m_items.begin();
+ if (currentIt == m_items.end())
+ {
+ // this shouldn't happen either, but again... we try and be safe
+ return;
+ }
+
+ ItemList::iterator nextIt = m_items.begin();
+ ++nextIt;
+
+ if (nextIt == m_items.end())
+ {
+ // first item in!
+ item->setGeometryR(QRect(insertionPoint.x(), insertionPoint.y(), widget->width(), widget->height()));
+ updateFreeSpaceValues();
+ return;
+ }
+
+ int insPos = (orientation() == Horizontal) ? insertionPoint.x(): insertionPoint.y();
+ Item* current = *currentIt;
+ Item* next = *nextIt;
+
+ for (; nextIt != m_items.end(); ++currentIt, ++nextIt)
+ {
+ next = *nextIt;
+ current = *currentIt;
+ if (current == item || next == item)
+ {
+ continue;
+ }
+
+ if (insPos == 0)
+ {
+ if (current->rightR() + 3 < next->leftR())
+ {
+ insPos = current->rightR();
+ break;
+ }
+ }
+ else
+ {
+ if (currentIt == m_items.begin() &&
+ (current->leftR() > insPos ||
+ (current->leftR() <= insPos) &&
+ (current->rightR() > insPos)))
+ {
+ break;
+ }
+
+ if ((current->rightR() < insPos) && (next->leftR() > insPos))
+ {
+ // Free space available at insertion point!
+ if (insPos + item->widthR() > next->leftR())
+ {
+ // We have overlap on the right, move to the left
+ insPos = next->leftR() - item->widthR();
+ if (insPos < current->rightR())
+ {
+ // We have overlap on the left as well, move to the right
+ insPos = current->rightR();
+ // We don't fit entirely, let updateFreeSpaceValues sort it out
+ }
+ }
+ current = next;
+ break;
+ }
+
+ if ((next->leftR() <= insPos) && (next->rightR() > insPos))
+ {
+ // Insert at the location of next
+ current = next;
+ insPos = next->leftR();
+ break;
+ }
+ }
+ }
+
+ QRect geom = item->geometryR();
+ geom.moveLeft(insPos);
+ item->setGeometryR(geom);
+ widget->setGeometry(transform(geom)); // widget isn't shown, layout not active yet
+
+ if (current)
+ {
+ m_items.erase(m_items.fromLast());
+ ItemList::iterator insertIt = m_items.find(current);
+
+ if (insertIt == m_items.begin())
+ {
+ m_items.push_front(item);
+ }
+ else if (insertIt == m_items.end())
+ {
+ // yes, we just removed it from the end, but
+ // if we remove it afterwards and it insertIt
+ // was our item then we end up with a bad iterator
+ m_items.append(item);
+ }
+ else
+ {
+ m_items.insert(insertIt, item);
+ }
+ }
+
+ updateFreeSpaceValues();
+}
+
+QStringList ContainerAreaLayout::listItems() const
+{
+ QStringList items;
+ for (ItemList::const_iterator it = m_items.constBegin();
+ it != m_items.constEnd(); ++it)
+ {
+ QLayoutItem* item = (*it)->item;
+ BaseContainer* container = dynamic_cast<BaseContainer*>(item->widget());
+
+ if (!container)
+ {
+ continue;
+ }
+
+ AppletContainer* applet = dynamic_cast<AppletContainer*>(container);
+ if (applet)
+ {
+ items.append(applet->info().desktopFile());
+ }
+ else
+ {
+ // button containers don't give us anything useful that isn't
+ // i18n'd (e.g. all service buttons and url buttons simply report
+ // "URL" as their tileName()) which would require that we
+ // extend PanelButton to be more expressive to get something more
+ // instead i just cop'd out and use the visible name. good enough.
+ items.append(container->visibleName());
+ }
+ }
+
+ return items;
+}
+
+QWidget* ContainerAreaLayout::widgetAt(int index) const
+{
+ if (index < 0 || index >= (int)m_items.count())
+ {
+ return 0;
+ }
+
+ return m_items[index]->item->widget();
+}
+
+QSize ContainerAreaLayout::sizeHint() const
+{
+ const int size = KickerLib::sizeValue(KPanelExtension::SizeNormal);
+
+ if (orientation() == Horizontal)
+ {
+ return QSize(widthForHeight(size), size);
+ }
+ else
+ {
+ return QSize(size, heightForWidth(size));
+ }
+}
+
+QSize ContainerAreaLayout::minimumSize() const
+{
+ const int size = KickerLib::sizeValue(KPanelExtension::SizeTiny);
+
+ if (orientation() == Horizontal)
+ {
+ return QSize(widthForHeight(size), size);
+ }
+ else
+ {
+ return QSize(size, heightForWidth(size));
+ }
+}
+
+QLayoutIterator ContainerAreaLayout::iterator()
+{
+ return QLayoutIterator(new ContainerAreaLayoutIterator(&m_items));
+}
+
+void ContainerAreaLayout::setGeometry(const QRect& rect)
+{
+ //RESEARCH: when can we short curcuit this?
+ // maybe a dirty flag to be set when we have containers
+ // that needs laying out?
+
+ QLayout::setGeometry(rect);
+
+ float totalFreeSpace = kMax(0, widthR() - widthForHeightR(heightR()));
+ int occupiedSpace = 0;
+
+ ItemList::const_iterator it = m_items.constBegin();
+ while (it != m_items.constEnd())
+ {
+ ContainerAreaLayoutItem* cur = *it;
+ ++it;
+ ContainerAreaLayoutItem* next = (it != m_items.constEnd()) ? *it : 0;
+
+ double fs = cur->freeSpaceRatio();
+ double freeSpace = fs * totalFreeSpace;
+ int pos = int(rint(freeSpace)) + occupiedSpace;
+
+ int w = cur->widthForHeightR(heightR());
+ occupiedSpace += w;
+ if (m_stretchEnabled && cur->isStretch())
+ {
+ if (next)
+ {
+ double nfs = next->freeSpaceRatio();
+ w += int((nfs - fs)*totalFreeSpace);
+ }
+ else
+ {
+ w = widthR() - pos;
+ }
+ }
+ cur->setGeometryR(QRect(pos, 0, w, heightR()));
+ }
+}
+
+int ContainerAreaLayout::widthForHeight(int h) const
+{
+ int width = 0;
+ ItemList::const_iterator it = m_items.constBegin();
+ for (; it != m_items.constEnd(); ++it)
+ {
+ width += kMax(0, (*it)->widthForHeight(h));
+ }
+ return width;
+}
+
+int ContainerAreaLayout::heightForWidth(int w) const
+{
+ int height = 0;
+ ItemList::const_iterator it = m_items.constBegin();
+ for (; it != m_items.constEnd(); ++it)
+ {
+ height += kMax(0, (*it)->heightForWidth(w));
+ }
+ return height;
+}
+
+void ContainerAreaLayout::setStretchEnabled(bool enable)
+{
+ if (m_stretchEnabled != enable)
+ {
+ m_stretchEnabled = enable;
+ activate();
+ }
+}
+
+void ContainerAreaLayout::updateFreeSpaceValues()
+{
+ int freeSpace =
+ kMax(0, widthR() - widthForHeightR(heightR()));
+
+ double fspace = 0;
+ for (ItemList::const_iterator it = m_items.constBegin();
+ it != m_items.constEnd();
+ ++it)
+ {
+ int distance = distanceToPreviousItem(it);
+ if (distance < 0) distance = 0;
+ fspace += distance;
+ double ssf = ( freeSpace == 0 ? 0 : fspace/freeSpace );
+ if (ssf > 1) ssf = 1;
+ if (ssf < 0) ssf = 0;
+ (*it)->setFreeSpaceRatio(ssf);
+ }
+}
+
+int ContainerAreaLayout::distanceToPreviousItem(ItemList::const_iterator it) const
+{
+ assert(it != m_items.constEnd());
+
+ ContainerAreaLayoutItem* cur = *it;
+ --it;
+ ContainerAreaLayoutItem* prev = (it != m_items.constEnd()) ? *it : 0;
+
+ return prev ? cur->leftR() - prev->leftR() - prev->widthForHeightR(heightR()) :
+ cur->leftR() - leftR();
+}
+
+void ContainerAreaLayout::moveContainerSwitch(QWidget* container, int distance)
+{
+ const bool horizontal = orientation() == Horizontal;
+ const bool reverseLayout = QApplication::reverseLayout();
+
+ if (horizontal && reverseLayout)
+ distance = - distance;
+
+ const bool forward = distance > 0;
+
+ // Get the iterator 'it' pointing to 'moving'.
+ ItemList::const_iterator it = m_items.constBegin();
+ while (it != m_items.constEnd() && (*it)->item->widget() != container)
+ {
+ ++it;
+ }
+
+ if (it == m_items.constEnd())
+ {
+ return;
+ }
+
+ ContainerAreaLayoutItem* moving = *it;
+ forward ? ++it : --it;
+ ContainerAreaLayoutItem* next = (it != m_items.constEnd()) ? *it : 0;
+ ContainerAreaLayoutItem* last = moving;
+
+ while (next)
+ {
+ // Calculate the position and width of the virtual container
+ // containing 'moving' and 'next'.
+ int tpos = forward ? next->leftR() - moving->widthR()
+ : next->leftR();
+ int tsize = moving->widthR() + next->widthR();
+
+ // Determine the middle of the containers.
+ int tmiddle = tpos + tsize / 2;
+ int movingMiddle = moving->leftR() + distance + moving->widthR() / 2;
+
+ // Check if the middle of 'moving' has moved past the middle of the
+ // virtual container.
+ if (!forward && movingMiddle > tmiddle
+ || forward && movingMiddle < tmiddle)
+ break;
+
+ // Move 'next' to the other side of 'moving'.
+ QRect geom = next->geometryR();
+ if (forward)
+ geom.moveLeft(geom.left() - moving->widthR());
+ else
+ geom.moveLeft(geom.left() + moving->widthR());
+ next->setGeometryR(geom);
+
+ // Store 'next'. It may become null in the next iteration, but we
+ // need its value later.
+ last = next;
+ forward ? ++it : --it;
+ next = (it != m_items.constEnd()) ? *it : 0;
+ }
+
+ int newPos = moving->leftR() + distance;
+ if (last != moving)
+ {
+ // The case that moving has switched position with at least one other container.
+ newPos = forward ? kMax(newPos, last->rightR() + 1)
+ : kMin(newPos, last->leftR() - moving->widthR());
+
+ // Move 'moving' to its new position in the container list.
+ ItemList::iterator itMoving = m_items.find(moving);
+
+ if (itMoving != m_items.end())
+ {
+ ItemList::iterator itLast = itMoving;
+ if (forward)
+ {
+ ++itLast;
+ ++itLast;
+ }
+ else
+ {
+ --itLast;
+ }
+
+ m_items.erase(itMoving);
+
+ if (itLast == m_items.end())
+ {
+ if (forward)
+ {
+ m_items.append(moving);
+ }
+ else
+ {
+ m_items.push_front(moving);
+ }
+ }
+ else
+ {
+ m_items.insert(itLast, moving);
+ }
+ }
+ }
+ else if (next)
+ {
+ // Make sure that the moving container will not overlap the next one.
+ newPos = forward ? kMin(newPos, next->leftR() - moving->widthR())
+ : kMax(newPos, next->rightR() + 1);
+ }
+
+ // Move the container to its new position and prevent it from moving outside the panel.
+ QRect geom = moving->geometryR();
+ distance = kClamp(newPos, 0, widthR() - moving->widthR());
+ geom.moveLeft(distance);
+ moving->setGeometryR(geom);
+
+ // HACK - since the menuapplet is not movable by the user, make sure it's always left-aligned
+ ItemList::const_iterator prev = m_items.constEnd();
+ for( ItemList::const_iterator it = m_items.constBegin();
+ it != m_items.constEnd();
+ ( prev = it ), ++it )
+ {
+ if( BaseContainer* container = dynamic_cast<BaseContainer*>((*it)->item->widget()))
+ if(AppletContainer* applet = dynamic_cast<AppletContainer*>(container))
+ if( applet->info().desktopFile() == "menuapplet.desktop" )
+ {
+ QRect geom = (*it)->geometryR();
+ if( prev != m_items.constEnd())
+ geom.moveLeft( (*prev)->rightR() + 1 );
+ else
+ geom.moveLeft( 0 );
+ (*it)->setGeometryR( geom );
+ }
+ }
+
+ updateFreeSpaceValues();
+}
+
+int ContainerAreaLayout::moveContainerPush(QWidget* a, int distance)
+{
+ const bool horizontal = orientation() == Horizontal;
+ const bool reverseLayout = QApplication::reverseLayout();
+
+ // Get the iterator 'it' pointing to the layoutitem representing 'a'.
+ ItemList::const_iterator it = m_items.constBegin();
+ while (it != m_items.constEnd() && (*it)->item->widget() != a)
+ {
+ ++it;
+ }
+
+ if (it != m_items.constEnd())
+ {
+ if (horizontal && reverseLayout)
+ {
+ distance = -distance;
+ }
+
+ int retVal = moveContainerPushRecursive(it, distance);
+ updateFreeSpaceValues();
+ if (horizontal && reverseLayout)
+ {
+ retVal = -retVal;
+ }
+ return retVal;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int ContainerAreaLayout::moveContainerPushRecursive(ItemList::const_iterator it,
+ int distance)
+{
+ if (distance == 0)
+ return 0;
+
+ const bool forward = distance > 0;
+
+ int available; // Space available for the container to move.
+ int moved; // The actual distance the container will move.
+ ContainerAreaLayoutItem* cur = *it;
+ forward ? ++it : --it;
+ ContainerAreaLayoutItem* next = (it != m_items.constEnd()) ? *it : 0;
+
+ if (!next)
+ {
+ available = forward ? rightR() - cur->rightR()
+ : -cur->leftR();
+ }
+ else
+ {
+ available = forward ? next->leftR() - cur->rightR() - 1
+ : next->rightR() - cur->leftR() + 1;
+
+ if (!forward && distance < available
+ || forward && distance > available)
+ available += moveContainerPushRecursive(it, distance - available);
+ }
+ moved = forward ? kMin(distance, available)
+ : kMax(distance, available);
+
+ QRect geom = cur->geometryR();
+ geom.moveLeft(geom.left() + moved);
+ cur->setGeometryR(geom);
+
+ return moved;
+}
+
+QRect ContainerAreaLayout::transform(const QRect& r) const
+{
+ if (orientation() == Horizontal)
+ {
+ if (QApplication::reverseLayout())
+ {
+ QRect t = r;
+ t.moveLeft(geometry().right() - r.right());
+ return t;
+ }
+ else
+ {
+ return r;
+ }
+ }
+ else
+ {
+ return QRect(r.y(), r.x(), r.height(), r.width());
+ }
+}
+
+int ContainerAreaLayout::widthForHeightR(int h) const
+{
+ if (orientation() == Horizontal)
+ {
+ return widthForHeight(h);
+ }
+ else
+ {
+ return heightForWidth(h);
+ }
+}
+
+int ContainerAreaLayout::widthR() const
+{
+ if (orientation() == Horizontal)
+ {
+ return geometry().width();
+ }
+ else
+ {
+ return geometry().height();
+ }
+}
+
+int ContainerAreaLayout::heightR() const
+{
+ if (orientation() == Horizontal)
+ {
+ return geometry().height();
+ }
+ else
+ {
+ return geometry().width();
+ }
+}
+
+int ContainerAreaLayout::leftR() const
+{
+ if (orientation() == Horizontal)
+ return geometry().left();
+ else
+ return geometry().top();
+}
+
+int ContainerAreaLayout::rightR() const
+{
+ if (orientation() == Horizontal)
+ return geometry().right();
+ else
+ return geometry().bottom();
+}
+
diff --git a/kicker/kicker/core/containerarealayout.h b/kicker/kicker/core/containerarealayout.h
new file mode 100644
index 000000000..4d4e0561d
--- /dev/null
+++ b/kicker/kicker/core/containerarealayout.h
@@ -0,0 +1,120 @@
+/*****************************************************************
+
+Copyright (c) 1996-2004 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __containerarealayout_h__
+#define __containerarealayout_h__
+
+#include <qlayout.h>
+
+class ContainerAreaLayout;
+
+class ContainerAreaLayoutItem : public Qt
+{
+ public:
+ ContainerAreaLayoutItem(QLayoutItem* i, ContainerAreaLayout* layout)
+ : item(i),
+ m_freeSpaceRatio(0.0),
+ m_layout(layout)
+ {}
+
+ ~ContainerAreaLayoutItem()
+ { delete item; }
+
+ int heightForWidth(int w) const;
+ int widthForHeight(int h) const;
+
+ bool isStretch() const;
+
+ QRect geometry() const
+ { return item->geometry(); }
+ void setGeometry(const QRect& geometry)
+ { item->setGeometry(geometry); }
+
+ double freeSpaceRatio() const;
+ void setFreeSpaceRatio(double ratio);
+
+ Orientation orientation() const;
+
+ // Relative geometry
+ QRect geometryR() const;
+ void setGeometryR(const QRect&);
+ int widthForHeightR(int w) const;
+ int widthR() const;
+ int heightR() const;
+ int leftR() const;
+ int rightR() const;
+
+ QLayoutItem* item;
+
+ private:
+ double m_freeSpaceRatio;
+ ContainerAreaLayout* m_layout;
+};
+
+class ContainerAreaLayout : public QLayout
+{
+ public:
+ typedef ContainerAreaLayoutItem Item;
+ typedef QValueList<Item*> ItemList;
+
+ ContainerAreaLayout(QWidget* parent);
+
+ void addItem(QLayoutItem* item);
+ void insertIntoFreeSpace(QWidget* item, QPoint insertionPoint);
+ QStringList listItems() const;
+ QWidget* widgetAt(int index) const;
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QLayoutIterator iterator();
+ void setGeometry(const QRect& rect);
+
+ Orientation orientation() const { return m_orientation; }
+ void setOrientation(Orientation o) { m_orientation = o; }
+ int heightForWidth(int w) const;
+ int widthForHeight(int h) const;
+ void updateFreeSpaceValues();
+ void moveToFirstFreePosition(BaseContainer* a);
+
+ void setStretchEnabled(bool enable);
+
+ void moveContainerSwitch(QWidget* container, int distance);
+ int moveContainerPush(QWidget* container, int distance);
+
+ // Relative geometry
+ QRect transform(const QRect&) const;
+ int widthForHeightR(int w) const;
+ int widthR() const;
+ int heightR() const;
+ int leftR() const;
+ int rightR() const;
+
+ private:
+ int moveContainerPushRecursive(ItemList::const_iterator it, int distance);
+ int distanceToPreviousItem(ItemList::const_iterator it) const;
+
+ Orientation m_orientation;
+ bool m_stretchEnabled;
+ ItemList m_items;
+};
+
+#endif
diff --git a/kicker/kicker/core/default-apps b/kicker/kicker/core/default-apps
new file mode 100644
index 000000000..7505e5279
--- /dev/null
+++ b/kicker/kicker/core/default-apps
@@ -0,0 +1,2 @@
+Home.desktop
+Internet/konqbrowser.desktop
diff --git a/kicker/kicker/core/extensionSettings.kcfg b/kicker/kicker/core/extensionSettings.kcfg
new file mode 100644
index 000000000..dcf7edd23
--- /dev/null
+++ b/kicker/kicker/core/extensionSettings.kcfg
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+
+<include>kapplication.h</include>
+<include>kpanelextension.h</include>
+<include>unhidetrigger.h</include>
+<kcfgfile arg="true"/>
+<group name="General">
+
+<entry name="IExist" type="Bool">
+ <label>Whether this panel actually exists or not. Primarily to work around the fact that KConfigXT won't write a config file unless there is at least one non-default entry.</label>
+ <default>false</default>
+</entry>
+<entry name="Position" type="Int" >
+ <label>The position of the panel</label>
+ <default code="true">KPanelExtension::Bottom</default>
+ <min>0</min>
+ <max>3</max>
+ </entry>
+
+<entry name="Alignment" type="Int" >
+ <label>The alignment of the panel</label>
+ <default code="true">KPanelExtension::Left</default>
+ <min>0</min>
+ <max>2</max>
+ </entry>
+
+<entry name="XineramaScreen" type="Int">
+ <label>Primary xinerama screen</label>
+ <default code="true">QApplication::desktop()->primaryScreen()</default>
+ </entry>
+
+<entry name="HideButtonSize" type="Int" >
+ <label>Hide button size</label>
+ <default>14</default>
+ <min>3</min>
+ <max>48</max>
+ </entry>
+
+<entry name="ShowLeftHideButton" type="Bool" >
+ <label>Show left panel hide button</label>
+ <default>false</default>
+ </entry>
+
+<entry name="ShowRightHideButton" type="Bool" >
+ <label>Show right panel hide button</label>
+ <default>false</default>
+ </entry>
+
+<entry name="AutoHidePanel" type="Bool" >
+ <label>Auto hide panel</label>
+ <default>false</default>
+ </entry>
+
+<entry name="AutoHideSwitch" type="Bool" >
+ <label>Enable auto hide</label>
+ <default>false</default>
+ </entry>
+
+<entry name="AutoHideDelay" type="Int" >
+ <label>Delay before auto hide</label>
+ <default>3</default>
+ </entry>
+
+<entry name="UnhideLocation" type="Int" >
+ <label>The trigger location for unhides</label>
+ <default code="true">UnhideTrigger::None</default>
+ <min code="true">UnhideTrigger::None</min>
+ <max code="true">UnhideTrigger::TopLeft</max>
+ </entry>
+
+<entry name="BackgroundHide" type="Bool" >
+ <label>Enable background hiding</label>
+ <default>false</default>
+ </entry>
+
+<entry name="HideAnimation" type="Bool" >
+ <label>Animate panel hiding</label>
+ <default>true</default>
+ </entry>
+
+<entry name="HideAnimationSpeed" type="Int" >
+ <label>Panel hiding animation speed</label>
+ <default>40</default>
+ </entry>
+
+<entry name="SizePercentage" type="Int" >
+ <label>Length in percentage</label>
+ <default>100</default>
+ <min>1</min>
+ <max>100</max>
+ </entry>
+
+<entry name="ExpandSize" type="Bool" >
+ <label>Expand as required to fit contents</label>
+ <default>true</default>
+ </entry>
+
+<entry name="Size" type="Int">
+ <label>Size</label>
+ <default code="true">KPanelExtension::SizeNormal</default>
+ </entry>
+
+<entry name="CustomSize" type="Int" >
+ <label>Custom size</label>
+ <default>58</default>
+ <min>16</min>
+ </entry>
+
+</group>
+</kcfg>
diff --git a/kicker/kicker/core/extensionSettings.kcfgc b/kicker/kicker/core/extensionSettings.kcfgc
new file mode 100644
index 000000000..bee651f64
--- /dev/null
+++ b/kicker/kicker/core/extensionSettings.kcfgc
@@ -0,0 +1,5 @@
+File=extensionSettings.kcfg
+Singleton=false
+ClassName=ExtensionSettings
+Mutators=true
+IncludeFiles=kpanelextension.h
diff --git a/kicker/kicker/core/extensionmanager.cpp b/kicker/kicker/core/extensionmanager.cpp
new file mode 100644
index 000000000..d6342b8f9
--- /dev/null
+++ b/kicker/kicker/core/extensionmanager.cpp
@@ -0,0 +1,773 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <elter@kde.org>
+Copyright (c) 2004-2005 Aaron Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <kaboutdata.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmenubar.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kwinmodule.h>
+#include <dcopref.h>
+
+#include "container_extension.h"
+#include "global.h"
+#include "kicker.h"
+#include "panelextension.h"
+#include "pluginmanager.h"
+
+#include "extensionmanager.h"
+
+ExtensionManager* ExtensionManager::m_self = 0;
+
+ExtensionManager* ExtensionManager::the()
+{
+ if (!m_self)
+ {
+ m_self = new ExtensionManager;
+ }
+
+ return m_self;
+}
+
+ExtensionManager::ExtensionManager()
+ : QObject(0, "ExtensionManager"),
+ m_menubarPanel(0),
+ m_mainPanel(0),
+ m_panelCounter(-1)
+{
+}
+
+ExtensionManager::~ExtensionManager()
+{
+ if (this == m_self)
+ {
+ m_self = 0;
+ }
+
+ ExtensionList::iterator itEnd = _containers.end();
+ for (ExtensionList::iterator it = _containers.begin(); it != itEnd; ++it)
+ {
+ delete *it;
+ }
+ _containers.clear();
+
+ delete m_menubarPanel;
+ delete m_mainPanel;
+}
+
+void ExtensionManager::initialize()
+{
+// kdDebug(1210) << "ExtensionManager::loadContainerConfig()" << endl;
+ KConfig* config = KGlobal::config();
+ PluginManager* pm = PluginManager::the();
+
+ // set up the "main" panel
+ if (config->hasGroup("Main Panel"))
+ {
+ config->setGroup("Main Panel");
+ if (config->hasKey("DesktopFile"))
+ {
+ m_mainPanel = pm->createExtensionContainer(config->readPathEntry("DesktopFile"),
+ true, config->readPathEntry("ConfigFile"),
+ "Main Panel");
+ }
+ }
+
+ if (!m_mainPanel)
+ {
+ // fall back to a regular ol' PanelExtension
+ m_mainPanel = pm->createExtensionContainer(
+ "childpanelextension.desktop",
+ true,
+ QString(kapp->aboutData()->appName()) + "rc",
+ "Main Panel");
+ }
+
+ if (!m_mainPanel)
+ {
+ KMessageBox::error(0, i18n("The KDE panel (kicker) could not load the main panel "
+ "due to a problem with your installation. "),
+ i18n("Fatal Error!"));
+ exit(1);
+ }
+
+ configureMenubar(true);
+
+ Kicker::the()->setMainWidget(m_mainPanel);
+
+ m_mainPanel->readConfig();
+ m_mainPanel->show();
+ kapp->processEvents();
+
+ // read extension list
+ config->setGroup("General");
+ QStringList elist = config->readListEntry("Extensions2");
+
+ // now restore the extensions
+ QStringList::iterator itEnd = elist.end();
+ for (QStringList::iterator it = elist.begin(); it != elist.end(); ++it)
+ {
+ // extension id
+ QString extensionId(*it);
+
+ // create a matching applet container
+ if (extensionId.find("Extension") == -1)
+ {
+ continue;
+ }
+
+ // is there a config group for this extension?
+ if (!config->hasGroup(extensionId))
+ {
+ continue;
+ }
+
+ // set config group
+ config->setGroup(extensionId);
+
+ ExtensionContainer* e = pm->createExtensionContainer(config->readPathEntry("DesktopFile"),
+ true, // is startup
+ config->readPathEntry("ConfigFile"),
+ extensionId);
+ if (e)
+ {
+ addContainer(e);
+ e->readConfig();
+ e->show();
+ kapp->processEvents();
+ }
+ }
+
+ pm->clearUntrustedLists();
+ connect(Kicker::the(), SIGNAL(configurationChanged()), SLOT(configurationChanged()));
+ DCOPRef r( "ksmserver", "ksmserver" );
+ r.send( "resumeStartup", QCString( "kicker" ));
+}
+
+void ExtensionManager::configureMenubar(bool duringInit)
+{
+ KConfig menuConfig( "kdesktoprc", true );
+ if( KConfigGroup( &menuConfig, "KDE" ).readBoolEntry("macStyle", false)
+ || KConfigGroup( &menuConfig, "Menubar" ).readBoolEntry( "ShowMenubar", false ))
+ {
+ if (KGlobal::dirs()->findResource("applets", "menuapplet.desktop").isEmpty() ||
+ m_menubarPanel)
+ {
+ return;
+ }
+
+ if (duringInit)
+ {
+ AppletInfo menubarInfo("menuapplet.desktop", QString::null, AppletInfo::Applet);
+ if (PluginManager::the()->hasInstance(menubarInfo))
+ {
+ // it's already there, in the main panel!
+ return;
+ }
+ migrateMenubar();
+ }
+
+ AppletInfo info("childpanelextension.desktop",
+ "kicker_menubarpanelrc",
+ AppletInfo::Extension);
+ KPanelExtension* menubar = new MenubarExtension(info);
+ m_menubarPanel = new ExtensionContainer(menubar, info, "Menubar Panel");
+ m_menubarPanel->setPanelOrder(-1);
+ m_menubarPanel->readConfig();
+ m_menubarPanel->setPosition(KPanelExtension::Top);
+ m_menubarPanel->setXineramaScreen(XineramaAllScreens);
+ m_menubarPanel->setHideButtons(false, false);
+
+ // this takes care of resizing the panel so it shows with the right height
+ updateMenubar();
+
+ m_menubarPanel->show();
+ connect(kapp, SIGNAL(kdisplayFontChanged()), SLOT(updateMenubar()));
+ }
+ else if (m_menubarPanel)
+ {
+ int screen = m_menubarPanel->xineramaScreen();
+ delete m_menubarPanel;
+ m_menubarPanel = 0;
+
+ emit desktopIconsAreaChanged(desktopIconsArea(screen), screen);
+ }
+}
+
+void ExtensionManager::migrateMenubar()
+{
+ // lame, lame, lame.
+ // the menubar applet was just plunked into kicker and not much
+ // thought was put into how it should be used. great idea, but no
+ // integration. >:-(
+ // so now we have to check to see if we HAVE another extension that
+ // will have a menubar in it, and if so, abort creating one of our
+ // own.
+ //
+ // the reason i didn't do this as a kconfig_update script is that
+ // most people don't use this feature, so no reason to penalize
+ // everyone, and moreover the user may added this to their main
+ // panel, meaning kickerrc itself would have to be vastly modified
+ // with lots of complications. not work it IMHO.
+
+ KConfig* config = KGlobal::config();
+ config->setGroup("General");
+
+ if (config->readBoolEntry("CheckedForMenubar", false))
+ {
+ return;
+ }
+
+ if (!locate("config", "kicker_menubarpanelrc").isEmpty())
+ {
+ // don't overwrite/override something that's already there
+ return;
+ }
+
+ QStringList elist = config->readListEntry("Extensions2");
+ QStringList::iterator itEnd = elist.end();
+ for (QStringList::iterator it = elist.begin(); it != elist.end(); ++it)
+ {
+ QString extensionId(*it);
+
+ if (extensionId.find("Extension") == -1)
+ {
+ continue;
+ }
+
+ // is there a config group for this extension?
+ if (!config->hasGroup(extensionId))
+ {
+ continue;
+ }
+
+ config->setGroup(extensionId);
+ QString extension = config->readPathEntry("ConfigFile");
+ KConfig extensionConfig(locate("config", extension));
+ extensionConfig.setGroup("General");
+
+ if (extensionConfig.hasKey("Applets2"))
+ {
+ QStringList containers = extensionConfig.readListEntry("Applets2");
+ QStringList::iterator cit = containers.begin();
+ QStringList::iterator citEnd = containers.end();
+ for (; cit != citEnd; ++cit)
+ {
+ QString appletId(*cit);
+
+ // is there a config group for this applet?
+ if (!extensionConfig.hasGroup(appletId))
+ {
+ continue;
+ }
+
+ KConfigGroup group(&extensionConfig, appletId.latin1());
+ QString appletType = appletId.left(appletId.findRev('_'));
+
+ if (appletType == "Applet")
+ {
+ QString appletFile = group.readPathEntry("DesktopFile");
+ if (appletFile.find("menuapplet.desktop") != -1)
+ {
+ QString menubarConfig = locate("config", extension);
+ KIO::NetAccess::copy(menubarConfig,
+ locateLocal("config",
+ "kicker_menubarpanelrc"), 0);
+ elist.remove(it);
+ config->setGroup("General");
+ config->writeEntry("Extensions2", elist);
+ config->writeEntry("CheckedForMenubar", true);
+ config->sync();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ config->setGroup("General");
+ config->writeEntry("CheckedForMenubar", true);
+}
+
+void ExtensionManager::saveContainerConfig()
+{
+// kdDebug(1210) << "ExtensionManager::saveContainerConfig()" << endl;
+
+ KConfig *config = KGlobal::config();
+
+ // build the extension list
+ QStringList elist;
+ ExtensionList::iterator itEnd = _containers.end();
+ for (ExtensionList::iterator it = _containers.begin(); it != itEnd; ++it)
+ {
+ elist.append((*it)->extensionId());
+ }
+
+ // write extension list
+ config->setGroup("General");
+ config->writeEntry("Extensions2", elist);
+
+ config->sync();
+}
+
+void ExtensionManager::configurationChanged()
+{
+ if (m_mainPanel)
+ {
+ m_mainPanel->readConfig();
+ }
+
+ if (m_menubarPanel)
+ {
+ m_menubarPanel->readConfig();
+ }
+
+ ExtensionList::iterator itEnd = _containers.end();
+ for (ExtensionList::iterator it = _containers.begin(); it != itEnd; ++it)
+ {
+ (*it)->readConfig();
+ }
+}
+
+void ExtensionManager::updateMenubar()
+{
+ if (!m_menubarPanel)
+ {
+ return;
+ }
+
+ //kdDebug(0) << "ExtensionManager::updateMenubar()" << endl;
+ // we need to make sure the panel is tall enough to accomodate the
+ // menubar! an easy way to find out the height of a menu: make one ;)
+ KMenuBar tmpmenu;
+ tmpmenu.insertItem("KDE Rocks!");
+ m_menubarPanel->setSize(KPanelExtension::SizeCustom,
+ tmpmenu.sizeHint().height());
+ m_menubarPanel->writeConfig();
+
+ emit desktopIconsAreaChanged(desktopIconsArea(m_menubarPanel->xineramaScreen()),
+ m_menubarPanel->xineramaScreen());
+}
+
+bool ExtensionManager::isMainPanel(const QWidget* panel) const
+{
+ return m_mainPanel == panel;
+}
+
+bool ExtensionManager::isMenuBar(const QWidget* panel) const
+{
+ return m_menubarPanel == panel;
+}
+
+void ExtensionManager::addExtension( const QString& desktopFile )
+{
+ PluginManager* pm = PluginManager::the();
+ ExtensionContainer *e = pm->createExtensionContainer(desktopFile,
+ false, // is not startup
+ QString::null, // no config
+ uniqueId());
+
+
+ kdDebug(1210) << "ExtensionManager::addExtension" << endl;
+
+ if (e)
+ {
+ e->readConfig();
+ // as a new panel, the position will be set to the preferred position
+ // we just need to make sure this works with the rest of the panel layout
+ e->setPosition(initialPanelPosition(e->position()));
+ kdDebug(1210)<<"after e->readConfig(): pos="<<e->position()<<endl;
+ addContainer(e);
+ e->show();
+ e->writeConfig();
+ saveContainerConfig();
+ }
+}
+
+void ExtensionManager::addContainer(ExtensionContainer* e)
+{
+ if (!e)
+ {
+ return;
+ }
+
+ _containers.append(e);
+
+ connect(e, SIGNAL(removeme(ExtensionContainer*)),
+ this, SLOT(removeContainer(ExtensionContainer*)));
+
+ emit desktopIconsAreaChanged(desktopIconsArea(e->xineramaScreen()),
+ e->xineramaScreen());
+}
+
+void ExtensionManager::removeContainer(ExtensionContainer* e)
+{
+ if (!e)
+ {
+ return;
+ }
+
+ e->removeSessionConfigFile();
+ _containers.remove(e);
+ e->deleteLater(); // Wait till we return to the main event loop
+ saveContainerConfig();
+
+ emit desktopIconsAreaChanged(desktopIconsArea(e->xineramaScreen()),
+ e->xineramaScreen());
+}
+
+void ExtensionManager::removeAllContainers()
+{
+ while (!_containers.isEmpty())
+ {
+ ExtensionContainer* e = _containers.first();
+ _containers.remove(e);
+ e->deleteLater(); // Wait till we return to the main event loop
+ }
+
+ saveContainerConfig();
+}
+
+QString ExtensionManager::uniqueId()
+{
+ QString idBase = "Extension_%1";
+ QString newId;
+ int i = 0;
+ bool unique = false;
+
+ while (!unique)
+ {
+ i++;
+ newId = idBase.arg(i);
+
+ unique = true;
+ ExtensionList::iterator itEnd = _containers.end();
+ for (ExtensionList::iterator it = _containers.begin(); it != itEnd; ++it)
+ {
+ if ((*it)->extensionId() == newId)
+ {
+ unique = false;
+ break;
+ }
+ }
+ }
+
+ return newId;
+}
+
+KPanelExtension::Position ExtensionManager::initialPanelPosition(KPanelExtension::Position preferred)
+{
+ // Guess a good position
+ bool positions[KPanelExtension::Bottom+1];
+ for( int i = 0; i <= (int) KPanelExtension::Bottom; ++i )
+ {
+ positions[i] = true;
+ }
+
+ ExtensionList::iterator itEnd = _containers.end();
+ for (ExtensionList::iterator it = _containers.begin(); it != itEnd; ++it)
+ {
+ positions[(int) (*it)->position()] = false;
+ }
+
+ KPanelExtension::Position pos = preferred;
+ if (positions[(int)pos])
+ return pos;
+
+ pos = (KPanelExtension::Position) (pos ^ 1);
+ if (positions[(int)pos])
+ return pos;
+
+ pos = (KPanelExtension::Position) (pos ^ 3);
+ if (positions[(int)pos])
+ return pos;
+
+ pos = (KPanelExtension::Position) (pos ^ 1);
+ if (positions[(int)pos])
+ return pos;
+
+ return preferred;
+}
+
+bool ExtensionManager::shouldExclude(int XineramaScreen,
+ const ExtensionContainer* extension,
+ const ExtensionContainer* exclude) const
+{
+ // Rules of Exclusion:
+ // 0. Exclude ourselves
+ // 1. Exclude panels not on our Xinerama screen
+ // 2. Exclude panels on the same side of the screen as ourselves that are above us
+ // 3. Exclude panels on the opposite side of the screen. Breaks down if the user
+ // dabbles in insane layouts where a top/bottom or left/right pair overlap?
+ // 4. Exclude panels on adjacent sides of the screen that do not overlap with us
+
+ if (exclude->winId() == extension->winId())
+ {
+ // Rule 0 Exclusion
+ return true;
+ }
+
+ if (extension->xineramaScreen()!= XineramaAllScreens &&
+ exclude->xineramaScreen() != XineramaAllScreens &&
+ exclude->xineramaScreen() != XineramaScreen)
+ {
+ // Rule 1 exclusion
+ return true;
+ }
+
+ if (!exclude->reserveStrut())
+ {
+ return true;
+ }
+
+ bool lowerInStack = extension->panelOrder() < exclude->panelOrder();
+ if (exclude->position() == extension->position())
+ {
+ // Rule 2 Exclusion
+ if (extension->position() == KPanelExtension::Bottom &&
+ exclude->geometry().bottom() == extension->geometry().bottom() &&
+ !exclude->geometry().intersects(extension->geometry()))
+ {
+ return false;
+ }
+ else if (extension->position() == KPanelExtension::Top &&
+ exclude->geometry().top() == extension->geometry().top() &&
+ !exclude->geometry().intersects(extension->geometry()))
+ {
+ return false;
+ }
+ else if (extension->position() == KPanelExtension::Left &&
+ exclude->geometry().left() == extension->geometry().left() &&
+ !exclude->geometry().intersects(extension->geometry()))
+ {
+ return false;
+ }
+ else if (extension->position() == KPanelExtension::Right &&
+ exclude->geometry().right() == extension->geometry().right() &&
+ !exclude->geometry().intersects(extension->geometry()))
+ {
+ return false;
+ }
+
+ return lowerInStack;
+ }
+
+ // Rule 3 exclusion
+ if (exclude->orientation() == extension->orientation())
+ {
+ // on the opposite side of the screen from us.
+ return true;
+ }
+
+ // Rule 4 exclusion
+ if (extension->position() == KPanelExtension::Bottom)
+ {
+ if (exclude->geometry().bottom() > extension->geometry().top())
+ {
+ return lowerInStack;
+ }
+ }
+ else if (extension->position() == KPanelExtension::Top)
+ {
+ if (exclude->geometry().top() < extension->geometry().bottom())
+ {
+ return lowerInStack;
+ }
+ }
+ else if (extension->position() == KPanelExtension::Left)
+ {
+ if (exclude->geometry().left() < extension->geometry().right())
+ {
+ return lowerInStack;
+ }
+ }
+ else /* if (extension->position() == KPanelExtension::Right) */
+ {
+ if (exclude->geometry().right() > extension->geometry().left())
+ {
+ return lowerInStack;
+ }
+ }
+
+ return true;
+}
+
+QRect ExtensionManager::workArea(int XineramaScreen, const ExtensionContainer* extension)
+{
+ if (!extension)
+ {
+ return Kicker::the()->kwinModule()->workArea(XineramaScreen);
+ }
+
+ QValueList<WId> list;
+
+ ExtensionList::iterator itEnd = _containers.end();
+ ExtensionList::iterator it = _containers.begin();
+
+ // If the hide mode is Manual, exclude the struts of
+ // panels below this one in the list. Else exclude the
+ // struts of all panels.
+ if (extension->reserveStrut() &&
+ extension != m_menubarPanel &&
+ extension->hideMode() == ExtensionContainer::ManualHide)
+ {
+ if (m_mainPanel && shouldExclude(XineramaScreen, extension, m_mainPanel))
+ {
+ list.append(m_mainPanel->winId());
+ }
+
+ for (; it != itEnd; ++it)
+ {
+ if (shouldExclude(XineramaScreen, extension, *it))
+ {
+ list.append((*it)->winId());
+ }
+ }
+ }
+ else
+ {
+ // auto hide panel? just ignore everything else for now.
+ if (extension == m_menubarPanel)
+ {
+ list.append(m_menubarPanel->winId());
+ }
+
+ if (m_mainPanel)
+ {
+ list.append(m_mainPanel->winId());
+ }
+
+ for (; it != itEnd; ++it)
+ {
+ list.append((*it)->winId());
+ }
+ }
+
+ QRect workArea;
+ if (XineramaScreen == XineramaAllScreens)
+ {
+ /* special value for all screens */
+ workArea = Kicker::the()->kwinModule()->workArea(list);
+ }
+ else
+ {
+ workArea = Kicker::the()->kwinModule()->workArea(list, XineramaScreen)
+ .intersect(QApplication::desktop()->screenGeometry(XineramaScreen));
+ }
+
+ return workArea;
+}
+
+int ExtensionManager::nextPanelOrder()
+{
+ ++m_panelCounter;
+ return m_panelCounter;
+}
+
+void ExtensionManager::reduceArea(QRect &area, const ExtensionContainer *extension) const
+{
+ if (!extension ||
+ extension->hideMode() == ExtensionContainer::AutomaticHide ||
+ !extension->reserveStrut())
+ {
+ return;
+ }
+
+ QRect geom = extension->initialGeometry(extension->position(), extension->alignment(),
+ extension->xineramaScreen());
+
+ // reduce given area (QRect) to the space not covered by the given extension
+ // As simplification: the length of the extension is not taken into account
+ // which means that even a small extension e.g. on the left side of the desktop
+ // will remove the available area with its with
+
+ switch (extension->position())
+ {
+ case KPanelExtension::Left:
+ {
+ area.setLeft(QMAX(area.left(), geom.right()));
+ break;
+ }
+ case KPanelExtension::Right:
+ {
+ area.setRight(QMIN(area.right(), geom.left()));
+ break;
+ }
+ case KPanelExtension::Top:
+ {
+ area.setTop(QMAX(area.top(), geom.bottom()));
+ break;
+ }
+ case KPanelExtension::Bottom:
+ {
+ area.setBottom(QMIN(area.bottom(), geom.top()));
+ break;
+ }
+ default: ; // ignore KPanelExtension::Floating ... at least for now
+ }
+}
+
+QRect ExtensionManager::desktopIconsArea(int screen) const
+{
+ // This is pretty broken, mixes Xinerama and non-Xinerama multihead
+ // and generally doesn't seem to be required anyway => ignore screen.
+// QRect area = QApplication::desktop()->screenGeometry(screen);
+ QRect area = QApplication::desktop()->geometry();
+
+ reduceArea(area, m_mainPanel);
+ reduceArea(area, m_menubarPanel);
+
+ for (ExtensionList::const_iterator it = _containers.constBegin();
+ it != _containers.constEnd();
+ ++it)
+ {
+ reduceArea(area, (*it));
+ }
+
+ kdDebug(1210) << "ExtensionManager::desktopIconsArea() = " << area
+ << " screen = " << screen << endl;
+ return area;
+}
+
+void ExtensionManager::extensionSizeChanged(ExtensionContainer *extension)
+{
+ // we have to recalc the available space for desktop icons
+ if (!extension)
+ {
+ return;
+ }
+
+ emit desktopIconsAreaChanged(desktopIconsArea(extension->xineramaScreen()),
+ extension->xineramaScreen());
+}
+
+#include "extensionmanager.moc"
diff --git a/kicker/kicker/core/extensionmanager.h b/kicker/kicker/core/extensionmanager.h
new file mode 100644
index 000000000..2885df01f
--- /dev/null
+++ b/kicker/kicker/core/extensionmanager.h
@@ -0,0 +1,92 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __extensionmanager_h__
+#define __extensionmanager_h__
+
+#include <qvaluelist.h>
+#include <qobject.h>
+
+#include "container_extension.h"
+
+const int XineramaAllScreens = -2;
+
+class ExtensionManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ static ExtensionManager* the();
+
+ void configureMenubar(bool duringInit);
+ void addExtension( const QString &desktopFile );
+ bool isMainPanel(const QWidget* panel) const;
+ bool isMenuBar(const QWidget* panel) const;
+ void addContainer( ExtensionContainer* );
+ void removeAllContainers();
+ ExtensionList containers() const { return _containers; }
+
+ KPanelExtension::Position initialPanelPosition(KPanelExtension::Position preferred);
+ QRect workArea(int XineramaScreen, const ExtensionContainer* container);
+ int nextPanelOrder();
+
+ // return the space available for all icons on the desktop
+ // subtracts all panels from XineramaScreen's geometry
+ QRect desktopIconsArea(int xineramaScreen) const;
+
+public slots:
+ void removeContainer( ExtensionContainer* );
+ void initialize();
+ void extensionSizeChanged(ExtensionContainer *);
+
+signals:
+ void desktopIconsAreaChanged(const QRect &, int xineramaScreen);
+
+protected:
+ friend class Kicker;
+
+ ExtensionManager();
+ ~ExtensionManager();
+ QString uniqueId();
+ void saveContainerConfig();
+ bool shouldExclude(int XineramaScreen,
+ const ExtensionContainer* container,
+ const ExtensionContainer* exclude) const;
+
+protected slots:
+ void configurationChanged();
+ void updateMenubar();
+
+private:
+ void migrateMenubar();
+ void reduceArea(QRect &area, const ExtensionContainer *panel) const;
+
+ ExtensionList _containers;
+ ExtensionContainer* m_menubarPanel;
+ ExtensionContainer* m_mainPanel;
+ int m_panelCounter;
+ static ExtensionManager* m_self;
+};
+
+#endif
+
diff --git a/kicker/kicker/core/kicker.cpp b/kicker/kicker/core/kicker.cpp
new file mode 100644
index 000000000..65e059c5b
--- /dev/null
+++ b/kicker/kicker/core/kicker.cpp
@@ -0,0 +1,401 @@
+/*****************************************************************
+
+ Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ ******************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <qfile.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+
+#include <dcopclient.h>
+#include <kconfig.h>
+#include <kcmdlineargs.h>
+#include <kcmultidialog.h>
+#include <kcrash.h>
+#include <kdebug.h>
+#include <kdirwatch.h>
+#include <kglobal.h>
+#include <kglobalaccel.h>
+#include <kiconloader.h>
+#include <kimageio.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kwin.h>
+#include <kwinmodule.h>
+
+#include "extensionmanager.h"
+#include "pluginmanager.h"
+#include "menumanager.h"
+#include "k_mnu.h"
+#include "showdesktop.h"
+#include "panelbutton.h"
+
+#include "kicker.h"
+#include "kickerSettings.h"
+
+#include "kicker.moc"
+
+Kicker* Kicker::the() { return static_cast<Kicker*>(kapp); }
+
+Kicker::Kicker()
+ : KUniqueApplication(),
+ keys(0),
+ m_kwinModule(0),
+ m_configDialog(0),
+ m_canAddContainers(true)
+{
+ // initialize the configuration object
+ KickerSettings::instance(instanceName() + "rc");
+
+ if (KCrash::crashHandler() == 0 )
+ {
+ // this means we've most likely crashed once. so let's see if we
+ // stay up for more than 2 minutes time, and if so reset the
+ // crash handler since the crash isn't a frequent offender
+ QTimer::singleShot(120000, this, SLOT(setCrashHandler()));
+ }
+ else
+ {
+ // See if a crash handler was installed. It was if the -nocrashhandler
+ // argument was given, but the app eats the kde options so we can't
+ // check that directly. If it wasn't, don't install our handler either.
+ setCrashHandler();
+ }
+
+ // Make kicker immutable if configuration modules have been marked immutable
+ if (isKioskImmutable() && kapp->authorizeControlModules(Kicker::configModules(true)).isEmpty())
+ {
+ config()->setReadOnly(true);
+ config()->reparseConfiguration();
+ }
+
+ dcopClient()->setDefaultObject("Panel");
+ disableSessionManagement();
+ QString dataPathBase = KStandardDirs::kde_default("data").append("kicker/");
+ KGlobal::dirs()->addResourceType("mini", dataPathBase + "pics/mini");
+ KGlobal::dirs()->addResourceType("icon", dataPathBase + "pics");
+ KGlobal::dirs()->addResourceType("builtinbuttons", dataPathBase + "builtins");
+ KGlobal::dirs()->addResourceType("specialbuttons", dataPathBase + "menuext");
+ KGlobal::dirs()->addResourceType("applets", dataPathBase + "applets");
+ KGlobal::dirs()->addResourceType("tiles", dataPathBase + "tiles");
+ KGlobal::dirs()->addResourceType("extensions", dataPathBase + "extensions");
+
+ KImageIO::registerFormats();
+
+ KGlobal::iconLoader()->addExtraDesktopThemes();
+
+ KGlobal::locale()->insertCatalogue("libkonq");
+ KGlobal::locale()->insertCatalogue("libdmctl");
+ KGlobal::locale()->insertCatalogue("libtaskbar");
+
+ // initialize our keys
+ // note that this creates the KMenu by calling MenuManager::the()
+ keys = new KGlobalAccel( this );
+#define KICKER_ALL_BINDINGS
+#include "kickerbindings.cpp"
+ keys->readSettings();
+ keys->updateConnections();
+
+ // set up our global settings
+ configure();
+
+ connect(this, SIGNAL(settingsChanged(int)), SLOT(slotSettingsChanged(int)));
+ connect(this, SIGNAL(kdisplayPaletteChanged()), SLOT(paletteChanged()));
+ connect(this, SIGNAL(kdisplayStyleChanged()), SLOT(slotStyleChanged()));
+
+#if (QT_VERSION-0 >= 0x030200) // XRANDR support
+ connect(desktop(), SIGNAL(resized(int)), SLOT(slotDesktopResized()));
+#endif
+
+ // the panels, aka extensions
+ QTimer::singleShot(0, ExtensionManager::the(), SLOT(initialize()));
+
+ connect(ExtensionManager::the(), SIGNAL(desktopIconsAreaChanged(const QRect &, int)),
+ this, SLOT(slotDesktopIconsAreaChanged(const QRect &, int)));
+}
+
+Kicker::~Kicker()
+{
+ // order of deletion here is critical to avoid crashes
+ delete ExtensionManager::the();
+ delete MenuManager::the();
+}
+
+void Kicker::setCrashHandler()
+{
+ KCrash::setEmergencySaveFunction(Kicker::crashHandler);
+}
+
+void Kicker::crashHandler(int /* signal */)
+{
+ fprintf(stderr, "kicker: crashHandler called\n");
+
+ DCOPClient::emergencyClose();
+ sleep(1);
+ system("kicker --nocrashhandler &"); // try to restart
+}
+
+void Kicker::slotToggleShowDesktop()
+{
+ // don't connect directly to the ShowDesktop::toggle() slot
+ // so that the ShowDesktop object doesn't get created if
+ // this feature is never used, and isn't created until after
+ // startup even if it is
+ ShowDesktop::the()->toggle();
+}
+
+void Kicker::toggleLock()
+{
+ KickerSettings::self()->setLocked(!KickerSettings::locked());
+ KickerSettings::self()->writeConfig();
+ emit immutabilityChanged(isImmutable());
+}
+
+void Kicker::toggleShowDesktop()
+{
+ ShowDesktop::the()->toggle();
+}
+
+bool Kicker::desktopShowing()
+{
+ return ShowDesktop::the()->desktopShowing();
+}
+
+void Kicker::slotSettingsChanged(int category)
+{
+ if (category == (int)KApplication::SETTINGS_SHORTCUTS)
+ {
+ keys->readSettings();
+ keys->updateConnections();
+ }
+}
+
+void Kicker::paletteChanged()
+{
+ KConfigGroup c(KGlobal::config(), "General");
+ KickerSettings::setTintColor(c.readColorEntry("TintColor",
+ &palette().active().mid()));
+ KickerSettings::self()->writeConfig();
+}
+
+void Kicker::slotStyleChanged()
+{
+ restart();
+}
+
+bool Kicker::highlightMenuItem(const QString &menuId)
+{
+ return MenuManager::the()->kmenu()->highlightMenuItem( menuId );
+}
+
+void Kicker::showKMenu()
+{
+ MenuManager::the()->showKMenu();
+}
+
+void Kicker::popupKMenu(const QPoint &p)
+{
+ MenuManager::the()->popupKMenu(p);
+}
+
+void Kicker::configure()
+{
+ static bool notFirstConfig = false;
+
+ KConfig* c = KGlobal::config();
+ c->reparseConfiguration();
+ c->setGroup("General");
+ m_canAddContainers = !c->entryIsImmutable("Applets2");
+
+ KickerSettings::self()->readConfig();
+
+ QToolTip::setGloballyEnabled(KickerSettings::showToolTips());
+
+ if (notFirstConfig)
+ {
+ emit configurationChanged();
+ {
+ QByteArray data;
+ emitDCOPSignal("configurationChanged()", data);
+ }
+ }
+
+ notFirstConfig = true;
+// kdDebug(1210) << "tooltips " << ( _showToolTips ? "enabled" : "disabled" ) << endl;
+}
+
+void Kicker::quit()
+{
+ exit(1);
+}
+
+void Kicker::restart()
+{
+ // do this on a timer to give us time to return true
+ QTimer::singleShot(0, this, SLOT(slotRestart()));
+}
+
+void Kicker::slotRestart()
+{
+ // since the child will awaken before we do, we need to
+ // clear the untrusted list manually; can't rely on the
+ // dtor's to this for us.
+ PluginManager::the()->clearUntrustedLists();
+
+ char ** o_argv = new char*[2];
+ o_argv[0] = strdup("kicker");
+ o_argv[1] = 0L;
+ execv(QFile::encodeName(locate("exe", "kdeinit_wrapper")), o_argv);
+
+ exit(1);
+}
+
+bool Kicker::isImmutable() const
+{
+ return config()->isImmutable() || KickerSettings::locked();
+}
+
+bool Kicker::isKioskImmutable() const
+{
+ return config()->isImmutable();
+}
+
+void Kicker::addExtension( const QString &desktopFile )
+{
+ ExtensionManager::the()->addExtension( desktopFile );
+}
+
+QStringList Kicker::configModules(bool controlCenter)
+{
+ QStringList args;
+
+ if (controlCenter)
+ {
+ args << "kde-panel.desktop";
+ }
+ else
+ {
+ args << "kde-kicker_config_arrangement.desktop"
+ << "kde-kicker_config_hiding.desktop"
+ << "kde-kicker_config_menus.desktop"
+ << "kde-kicker_config_appearance.desktop";
+ }
+ args << "kde-kcmtaskbar.desktop";
+ return args;
+}
+
+QPoint Kicker::insertionPoint()
+{
+ return m_insertionPoint;
+}
+
+void Kicker::setInsertionPoint(const QPoint &p)
+{
+ m_insertionPoint = p;
+}
+
+
+void Kicker::showConfig(const QString& configPath, int page)
+{
+ if (!m_configDialog)
+ {
+ m_configDialog = new KCMultiDialog(0);
+
+ QStringList modules = configModules(false);
+ QStringList::ConstIterator end(modules.end());
+ for (QStringList::ConstIterator it = modules.begin(); it != end; ++it)
+ {
+ m_configDialog->addModule(*it);
+ }
+
+ connect(m_configDialog, SIGNAL(finished()), SLOT(configDialogFinished()));
+ }
+
+ if (!configPath.isEmpty())
+ {
+ QByteArray data;
+ QDataStream stream(data, IO_WriteOnly);
+ stream << configPath;
+ emitDCOPSignal("configSwitchToPanel(QString)", data);
+ }
+
+ KWin::setOnDesktop(m_configDialog->winId(), KWin::currentDesktop());
+ m_configDialog->show();
+ m_configDialog->raise();
+ if (page > -1)
+ {
+ m_configDialog->showPage(page);
+ }
+}
+
+void Kicker::showTaskBarConfig()
+{
+ showConfig(QString(), 4);
+}
+
+void Kicker::configureMenubar()
+{
+ ExtensionManager::the()->configureMenubar(false);
+}
+
+void Kicker::configDialogFinished()
+{
+ m_configDialog->delayedDestruct();
+ m_configDialog = 0;
+}
+
+void Kicker::slotDesktopResized()
+{
+ configure(); // reposition on the desktop
+}
+
+void Kicker::clearQuickStartMenu()
+{
+ MenuManager::the()->kmenu()->clearRecentMenuItems();
+}
+
+KWinModule* Kicker::kwinModule()
+{
+ if (!m_kwinModule)
+ {
+ m_kwinModule = new KWinModule();
+ }
+
+ return m_kwinModule;
+}
+
+QRect Kicker::desktopIconsArea(int screen) const
+{
+ return ExtensionManager::the()->desktopIconsArea(screen);
+}
+
+void Kicker::slotDesktopIconsAreaChanged(const QRect &area, int screen)
+{
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << area;
+ stream << screen;
+ emitDCOPSignal("desktopIconsAreaChanged(QRect, int)", params);
+}
diff --git a/kicker/kicker/core/kicker.h b/kicker/kicker/core/kicker.h
new file mode 100644
index 000000000..9ac1d3eac
--- /dev/null
+++ b/kicker/kicker/core/kicker.h
@@ -0,0 +1,131 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __kicker_h__
+#define __kicker_h__
+
+#include <qcolor.h>
+
+#include <kuniqueapplication.h>
+#include <kicontheme.h>
+
+class KCMultiDialog;
+class KDirWatch;
+class KGlobalAccel;
+class KWinModule;
+class PanelKMenu;
+class PanelPopupButton;
+
+class Kicker : public KUniqueApplication
+{
+ Q_OBJECT
+ K_DCOP
+
+public:
+ Kicker();
+ ~Kicker();
+
+k_dcop:
+ void configure();
+ void quit();
+ void restart();
+ void addExtension( const QString &desktopFile );
+ void popupKMenu( const QPoint &globalPos );
+ void clearQuickStartMenu();
+ bool highlightMenuItem( const QString &menuId );
+ void showKMenu();
+ void toggleShowDesktop();
+ bool desktopShowing();
+ void showConfig(const QString& config, int page = -1);
+ void showTaskBarConfig();
+ void configureMenubar();
+ // return the region on the desktop, which is not covered by panels
+ // and therefore allowed to be used by icons placed on the desktop
+ QRect desktopIconsArea(int screen) const;
+
+k_dcop_signals:
+ void desktopIconsAreaChanged(QRect area, int screen);
+
+public:
+ static Kicker* the();
+ KDirWatch* fileWatcher();
+ KWinModule* kwinModule();
+
+ bool isImmutable() const;
+ bool isKioskImmutable() const;
+ bool canAddContainers() const { return m_canAddContainers && !isImmutable(); }
+
+ static QStringList configModules(bool controlCenter);
+
+ /**
+ * Global position where to insert a new item
+ */
+ QPoint insertionPoint();
+
+ /**
+ * Set the global position where to insert a new item
+ * This is not meant to be used by more than one code path
+ * at a time! A point is set, then later accessed, then cleared
+ * as an atomic action:
+ *
+ * Kicker::the()->setInsertionPoint(p);
+ * ...
+ * QPoint where = Kicker::the()->insertionPoint();
+ * ...
+ * Kicker::the()->setInsertionPoint(QPoint());
+ *
+ * this is not pretty, but it's pragmatic and does everything
+ * that is needed
+ */
+ void setInsertionPoint(const QPoint &p);
+
+
+public slots:
+ void slotToggleShowDesktop();
+ void toggleLock();
+
+signals:
+ void configurationChanged();
+ void immutabilityChanged(bool immutable);
+
+private slots:
+ void configDialogFinished();
+ void slotSettingsChanged( int );
+ void slotRestart();
+ void slotDesktopResized();
+ void slotStyleChanged();
+ void paletteChanged();
+ void setCrashHandler();
+ void slotDesktopIconsAreaChanged(const QRect &area, int screen);
+
+private:
+ static void crashHandler(int signal);
+
+ KGlobalAccel* keys;
+ KWinModule* m_kwinModule;
+ KCMultiDialog* m_configDialog;
+ bool m_canAddContainers;
+ QPoint m_insertionPoint;
+};
+
+#endif
diff --git a/kicker/kicker/core/kickerbindings.cpp b/kicker/kicker/core/kickerbindings.cpp
new file mode 100644
index 000000000..2134fb975
--- /dev/null
+++ b/kicker/kicker/core/kickerbindings.cpp
@@ -0,0 +1,50 @@
+/*****************************************************************
+
+Copyright (c) 2001-2004 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef NOSLOTS
+# define DEF( name, key3, key4, target, fnSlot ) \
+ keys->insert( name, i18n(name), QString::null, key3, key4, target, SLOT(fnSlot) )
+#else
+# define DEF( name, key3, key4, target, fnSlot ) \
+ keys->insert( name, i18n(name), QString::null, key3, key4 )
+#endif
+#define WIN KKey::QtWIN
+
+#ifdef KICKER_ALL_BINDINGS
+#define LAUNCH_MENU
+#define SHOW_DESKTOP
+#endif
+
+#ifdef LAUNCH_MENU
+ keys->insert("Program:kicker", i18n("Panel"));
+ DEF(I18N_NOOP("Popup Launch Menu" ), ALT+Qt::Key_F1, WIN+Qt::Key_Menu,
+ MenuManager::the(), kmenuAccelActivated());
+#endif
+
+#ifdef SHOW_DESKTOP
+ DEF(I18N_NOOP( "Toggle Showing Desktop" ), ALT+CTRL+Qt::Key_D, WIN+CTRL+Qt::Key_D,
+ this, slotToggleShowDesktop());
+#endif
+
+#undef DEF
+#undef WIN
diff --git a/kicker/kicker/core/main.cpp b/kicker/kicker/core/main.cpp
new file mode 100644
index 000000000..8eb033e29
--- /dev/null
+++ b/kicker/kicker/core/main.cpp
@@ -0,0 +1,154 @@
+/*****************************************************************
+
+Copyright (c) 1996-2002 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <config.h>
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kaboutdata.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "kicker.h"
+
+int kicker_screen_number = 0;
+
+static const char description[] =
+ I18N_NOOP("The KDE panel");
+
+static const char version[] = VERSION;
+
+static void sighandler(int)
+{
+ fprintf(stderr, "kicker: sighandler called\n");
+ QApplication::exit();
+}
+
+extern "C" KDE_EXPORT int kdemain( int argc, char ** argv )
+{
+ {
+ QCString multiHead = getenv("KDE_MULTIHEAD");
+ if (multiHead.lower() == "true") {
+ Display *dpy = XOpenDisplay(NULL);
+ if (! dpy) {
+ fprintf(stderr, "%s: FATAL ERROR: couldn't open display %s\n",
+ argv[0], XDisplayName(NULL));
+ exit(1);
+ }
+
+ int number_of_screens = ScreenCount(dpy);
+ kicker_screen_number = DefaultScreen(dpy);
+ int pos;
+ QCString display_name = XDisplayString(dpy);
+ XCloseDisplay(dpy);
+ dpy = 0;
+
+ if ((pos = display_name.findRev('.')) != -1)
+ display_name.remove(pos, 10);
+
+ QCString env;
+ if (number_of_screens != 1) {
+ for (int i = 0; i < number_of_screens; i++) {
+ if (i != kicker_screen_number && fork() == 0) {
+ kicker_screen_number = i;
+ // break here because we are the child process, we don't
+ // want to fork() anymore
+ break;
+ }
+ }
+
+ env.sprintf("DISPLAY=%s.%d", display_name.data(), kicker_screen_number);
+
+ if (putenv(strdup(env.data()))) {
+ fprintf(stderr,
+ "%s: WARNING: unable to set DISPLAY environment variable\n",
+ argv[0]);
+ perror("putenv()");
+ }
+ }
+ }
+ }
+
+ KGlobal::locale()->setMainCatalogue("kicker");
+
+ QCString appname;
+ if (kicker_screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", kicker_screen_number);
+
+ KAboutData aboutData( appname.data(), I18N_NOOP("KDE Panel"),
+ version, description, KAboutData::License_BSD,
+ I18N_NOOP("(c) 1999-2004, The KDE Team") );
+
+ aboutData.addAuthor("Aaron J. Seigo", I18N_NOOP("Current maintainer"), "aseigo@kde.org");
+ aboutData.addAuthor("Matthias Elter",0, "elter@kde.org");
+ aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org");
+ aboutData.addAuthor("Wilco Greven",0, "greven@kde.org");
+ aboutData.addAuthor("Rik Hemsley",0, "rik@kde.org");
+ aboutData.addAuthor("Daniel M. Duley",0, "mosfet@kde.org");
+ aboutData.addAuthor("Preston Brown",0, "pbrown@kde.org");
+ aboutData.addAuthor("John Firebaugh",0, "jfirebaugh@kde.org");
+ aboutData.addAuthor("Waldo Bastian", I18N_NOOP("Kiosk mode"), "bastian@kde.org");
+
+ aboutData.addCredit("Jessica Hall", /* I18N_NOOP("KConfigXT") */ 0, "jes.hall@kdemail.net");
+ aboutData.addCredit("Stefan Nikolaus", /* I18N_NOOP("Bug fixes") */ 0, "stefan.nikolaus@kdemail.net");
+ aboutData.addCredit("Benoît Minisini", /* I18N_NOOP("Bug fixes") */ 0, "gambas@users.sourceforge.net");
+ KCmdLineArgs::init( argc, argv, &aboutData );
+
+ if (!Kicker::start()) {
+ kdError() << "kicker is already running!" << endl;
+ return 0;
+ }
+
+ if (signal(SIGTERM, sighandler) == SIG_IGN)
+ signal(SIGTERM, SIG_IGN);
+ if (signal(SIGINT, sighandler) == SIG_IGN)
+ signal(SIGINT, SIG_IGN);
+ if (signal(SIGHUP, sighandler) == SIG_IGN)
+ signal(SIGHUP, SIG_IGN);
+
+ // send it even before KApplication ctor, because ksmserver will launch another app as soon
+ // as QApplication registers with it
+ DCOPClient* cl = new DCOPClient;
+ cl->attach();
+ DCOPRef r( "ksmserver", "ksmserver" );
+ r.setDCOPClient( cl );
+ r.send( "suspendStartup", QCString( "kicker" ));
+ delete cl;
+ Kicker* kicker = new Kicker;
+ int rv = kicker->exec();
+ delete kicker;
+ return rv;
+}
+
diff --git a/kicker/kicker/core/menumanager.cpp b/kicker/kicker/core/menumanager.cpp
new file mode 100644
index 000000000..ba07b39c7
--- /dev/null
+++ b/kicker/kicker/core/menumanager.cpp
@@ -0,0 +1,272 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qcursor.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <dcopclient.h>
+
+#include "client_mnu.h"
+#include "container_extension.h"
+#include "global.h"
+#include "k_mnu.h"
+#include "kicker.h"
+#include "panelbutton.h"
+
+#include "menumanager.h"
+#include "menumanager.moc"
+
+// Why MenuManager doesn't use KStaticDeleter
+// MenuManager gets created before the ExtensionManager
+// So using KStaticDeleter results in MenuManager getting
+// deleted before ExtensionManager, which means also the panels
+// which means also the K Menu buttons. K Menu buttons call
+// MenuManager in their dtor, so if MenuManager is already gone
+// then every KButton will cause it to be reconstructed.
+// So we rely on Kicker to delete MenuManager on the way out
+// ensuring it's the last thing to go.
+MenuManager* MenuManager::m_self = 0;
+
+MenuManager* MenuManager::the()
+{
+ if (!m_self)
+ {
+ m_self = new MenuManager();
+ }
+
+ return m_self;
+}
+
+MenuManager::MenuManager(QObject *parent)
+ : QObject(parent, "MenuManager"), DCOPObject("MenuManager")
+{
+ m_kmenu = new PanelKMenu;
+ kapp->dcopClient()->setNotifications(true);
+ connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)),
+ this, SLOT(applicationRemoved(const QCString&)));
+}
+
+MenuManager::~MenuManager()
+{
+ if (this == m_self)
+ {
+ m_self = 0;
+ }
+
+ delete m_kmenu;
+}
+
+void MenuManager::slotSetKMenuItemActive()
+{
+ m_kmenu->selectFirstItem();
+}
+
+void MenuManager::showKMenu()
+{
+ m_kmenu->showMenu();
+}
+
+void MenuManager::popupKMenu(const QPoint &p)
+{
+// kdDebug(1210) << "popupKMenu()" << endl;
+ if (m_kmenu->isVisible())
+ {
+ m_kmenu->hide();
+ }
+ else if (p.isNull())
+ {
+ m_kmenu->popup(QCursor::pos());
+ }
+ else
+ {
+ m_kmenu->popup( p );
+ }
+}
+
+void MenuManager::registerKButton(PanelPopupButton *button)
+{
+ if (!button)
+ {
+ return;
+ }
+
+ m_kbuttons.append(button);
+}
+
+void MenuManager::unregisterKButton(PanelPopupButton *button)
+{
+ m_kbuttons.remove(button);
+}
+
+PanelPopupButton* MenuManager::findKButtonFor(QPopupMenu* menu)
+{
+ KButtonList::const_iterator itEnd = m_kbuttons.constEnd();
+ for (KButtonList::const_iterator it = m_kbuttons.constBegin(); it != itEnd; ++it)
+ {
+ if ((*it)->popup() == menu)
+ {
+ return *it;
+ }
+ }
+
+ return 0;
+}
+
+void MenuManager::kmenuAccelActivated()
+{
+ if (m_kmenu->isVisible())
+ {
+ m_kmenu->hide();
+ return;
+ }
+
+ m_kmenu->initialize();
+
+ if (m_kbuttons.isEmpty())
+ {
+ // no button to use, make it behave like a desktop menu
+ QPoint p;
+ // Popup the K-menu at the center of the screen.
+ QDesktopWidget* desktop = KApplication::desktop();
+ QRect r = desktop->screenGeometry(desktop->screenNumber(QCursor::pos()));
+ // kMenu->rect() is not valid before showing, use sizeHint()
+ p = r.center() - QRect( QPoint( 0, 0 ), m_kmenu->sizeHint()).center();
+ m_kmenu->popup(p);
+
+ // when the cursor is in the area where the menu pops up,
+ // the item under the cursor gets selected. The single shot
+ // avoids this from happening by allowing the item to be selected
+ // when the event loop is enterred, and then resetting it.
+ QTimer::singleShot(0, this, SLOT(slotSetKMenuItemActive()));
+ }
+ else
+ {
+ // We need the kmenu's size to place it at the right position.
+ // We cannot rely on the popup menu's current size(), if it wasn't
+ // shown before, so we resize it here according to its sizeHint().
+ const QSize size = m_kmenu->sizeHint();
+ m_kmenu->resize(size.width(),size.height());
+
+ PanelPopupButton* button = findKButtonFor(m_kmenu);
+
+ // let's unhide the panel while we're at it. traverse the widget
+ // hierarchy until we find the panel, if any
+ QObject* menuParent = button->parent();
+ while (menuParent)
+ {
+ ExtensionContainer* ext = dynamic_cast<ExtensionContainer*>(menuParent);
+
+ if (ext)
+ {
+ ext->unhideIfHidden();
+ // make sure it's unhidden before we use it to figure out
+ // where to popup
+ qApp->processEvents();
+ break;
+ }
+
+ menuParent = menuParent->parent();
+ }
+
+ button->showMenu();
+ }
+}
+
+QCString MenuManager::createMenu(QPixmap icon, QString text)
+{
+ static int menucount = 0;
+ menucount++;
+ QCString name;
+ name.sprintf("kickerclientmenu-%d", menucount );
+ KickerClientMenu* p = new KickerClientMenu( 0, name );
+ clientmenus.append(p);
+ m_kmenu->initialize();
+ p->text = text;
+ p->icon = icon;
+ p->idInParentMenu = m_kmenu->insertClientMenu( p );
+ p->createdBy = kapp->dcopClient()->senderId();
+ m_kmenu->adjustSize();
+ return name;
+}
+
+void MenuManager::removeMenu(QCString menu)
+{
+ bool iterate = true;
+ ClientMenuList::iterator it = clientmenus.begin();
+ for (; it != clientmenus.end(); iterate ? ++it : it)
+ {
+ iterate = true;
+ KickerClientMenu* m = *it;
+ if (m->objId() == menu)
+ {
+ m_kmenu->removeClientMenu(m->idInParentMenu);
+ it = clientmenus.erase(it);
+ iterate = false;
+ }
+ }
+ m_kmenu->adjustSize();
+}
+
+
+void MenuManager::applicationRemoved(const QCString& appRemoved)
+{
+ bool iterate = true;
+ ClientMenuList::iterator it = clientmenus.begin();
+ for (; it != clientmenus.end(); iterate ? ++it : it)
+ {
+ iterate = true;
+ KickerClientMenu* m = *it;
+ if (m->createdBy == appRemoved)
+ {
+ m_kmenu->removeClientMenu(m->idInParentMenu);
+ it = clientmenus.erase(it);
+ iterate = false;
+ }
+ }
+ m_kmenu->adjustSize();
+}
+
+bool MenuManager::process(const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData)
+{
+ if ( fun == "createMenu(QPixmap,QString)" ) {
+ QDataStream dataStream( data, IO_ReadOnly );
+ QPixmap icon;
+ QString text;
+ dataStream >> icon >> text;
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << createMenu( icon, text );
+ replyType = "QCString";
+ return true;
+ } else if ( fun == "removeMenu(QCString)" ) {
+ QDataStream dataStream( data, IO_ReadOnly );
+ QCString menu;
+ dataStream >> menu;
+ removeMenu( menu );
+ replyType = "void";
+ return true;
+ }
+ return false;
+}
diff --git a/kicker/kicker/core/menumanager.h b/kicker/kicker/core/menumanager.h
new file mode 100644
index 000000000..ed0e5d225
--- /dev/null
+++ b/kicker/kicker/core/menumanager.h
@@ -0,0 +1,81 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef KICKER_MENU_MANAGER_H
+#define KICKER_MENU_MANAGER_H
+
+#include <dcopobject.h>
+#include <qvaluelist.h>
+
+class PanelKMenu;
+class KickerClientMenu;
+class PanelPopupButton;
+
+typedef QValueList<PanelPopupButton*> KButtonList;
+
+/**
+ * The factory for menus created by other applications. Also the owner of these menus.
+ */
+class MenuManager : public QObject, DCOPObject
+{
+ Q_OBJECT
+public:
+ static MenuManager* the();
+
+ // dcop exported
+ QCString createMenu(QPixmap icon, QString text);
+ void removeMenu(QCString menu);
+
+ // dcop internal
+ bool process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &reply);
+
+ // KMenu controls
+ PanelKMenu* kmenu() { return m_kmenu; }
+ void showKMenu();
+ void popupKMenu(const QPoint &p);
+
+ void registerKButton(PanelPopupButton *button);
+ void unregisterKButton(PanelPopupButton *button);
+ PanelPopupButton* findKButtonFor(QPopupMenu* menu);
+ ~MenuManager();
+
+public slots:
+ void slotSetKMenuItemActive();
+ void kmenuAccelActivated();
+
+protected slots:
+ void applicationRemoved(const QCString&);
+
+protected:
+ PanelKMenu* m_kmenu;
+ typedef QValueList<KickerClientMenu*> ClientMenuList;
+ ClientMenuList clientmenus;
+
+private:
+ MenuManager(QObject *parent = 0);
+
+ static MenuManager* m_self;
+ KButtonList m_kbuttons;
+};
+
+#endif
diff --git a/kicker/kicker/core/panelextension.cpp b/kicker/kicker/core/panelextension.cpp
new file mode 100644
index 000000000..cf5067c17
--- /dev/null
+++ b/kicker/kicker/core/panelextension.cpp
@@ -0,0 +1,445 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter
+ 2004 Aaron J. Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qframe.h>
+#include <qvalidator.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qstyle.h>
+
+#include <kdebug.h>
+#include <khelpmenu.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <kconfig.h>
+#include <kstdguiitem.h>
+
+#include "container_applet.h"
+#include "container_extension.h"
+#include "containerarea.h"
+#include "extensionmanager.h"
+#include "kicker.h"
+#include "removecontainer_mnu.h"
+#include "removeextension_mnu.h"
+
+#include "addapplet_mnu.h"
+#include "addbutton_mnu.h"
+#include "addextension_mnu.h"
+
+#include "panelextension.h"
+#include "panelextension.moc"
+
+// KDE4: make these say Panel_(somenumber)
+PanelExtension::PanelExtension(const QString& configFile, QWidget *parent, const char *name)
+ : DCOPObject(QCString("ChildPanel_") + QString::number((ulong)this).latin1()),
+ KPanelExtension(configFile, KPanelExtension::Stretch, 0, parent, name),
+ _opMnu(0),
+ m_panelAddMenu(0),
+ m_removeMnu(0),
+ m_addExtensionMenu(0),
+ m_removeExtensionMenu(0),
+ _configFile(configFile),
+ m_opMenuBuilt( false )
+{
+ setAcceptDrops(!Kicker::the()->isImmutable());
+ setCustomMenu(opMenu());
+
+ QVBoxLayout* _layout = new QVBoxLayout(this);
+
+ // container area
+ _containerArea = new ContainerArea( config(), this, opMenu() );
+ connect(_containerArea, SIGNAL(maintainFocus(bool)), this, SIGNAL(maintainFocus(bool)));
+ _layout->addWidget(_containerArea);
+
+ _containerArea->viewport()->installEventFilter(this);
+ _containerArea->configure();
+
+ // Make sure the containerarea has the right orientation from the
+ // beginning.
+ positionChange(position());
+
+ connect(Kicker::the(), SIGNAL(configurationChanged()),
+ SLOT(configurationChanged()));
+ connect(Kicker::the(), SIGNAL(immutabilityChanged(bool)),
+ SLOT(immutabilityChanged(bool)));
+
+ // we wait to get back to the event loop to start up the container area so that
+ // the main panel in ExtensionManager will be assigned and we can tell in a
+ // relatively non-hackish way that we are (or aren't) the "main panel"
+ QTimer::singleShot(0, this, SLOT(populateContainerArea()));
+}
+
+PanelExtension::~PanelExtension()
+{
+}
+
+void PanelExtension::populateContainerArea()
+{
+ _containerArea->show();
+
+ if (ExtensionManager::the()->isMainPanel(topLevelWidget()))
+ {
+ setObjId("Panel");
+ _containerArea->initialize(true);
+ }
+ else
+ {
+ _containerArea->initialize(false);
+ }
+}
+
+void PanelExtension::configurationChanged()
+{
+ _containerArea->configure();
+}
+
+void PanelExtension::immutabilityChanged(bool)
+{
+ m_opMenuBuilt = false;
+}
+
+QPopupMenu* PanelExtension::opMenu()
+{
+ if (_opMnu)
+ {
+ return _opMnu;
+ }
+
+ _opMnu = new QPopupMenu(this);
+ connect(_opMnu, SIGNAL(aboutToShow()), this, SLOT(slotBuildOpMenu()));
+
+ return _opMnu;
+}
+
+void PanelExtension::positionChange(Position p)
+{
+ _containerArea->setPosition(p);
+}
+
+QSize PanelExtension::sizeHint(Position p, QSize maxSize) const
+{
+ QSize size;
+
+ if (p == Left || p == Right)
+ {
+ size = QSize(sizeInPixels(),
+ _containerArea->heightForWidth(sizeInPixels()));
+ }
+ else
+ {
+ size = QSize(_containerArea->widthForHeight(sizeInPixels()),
+ sizeInPixels());
+ }
+
+ return size.boundedTo( maxSize );
+}
+
+bool PanelExtension::eventFilter(QObject*, QEvent * e)
+{
+ if ( e->type() == QEvent::MouseButtonPress )
+ {
+ QMouseEvent* me = (QMouseEvent*) e;
+ if ( me->button() == RightButton && kapp->authorize("action/kicker_rmb"))
+ {
+ Kicker::the()->setInsertionPoint(me->globalPos());
+ opMenu()->exec(me->globalPos());
+ Kicker::the()->setInsertionPoint(QPoint());
+ return true;
+ }
+ }
+ else
+ if ( e->type() == QEvent::Resize )
+ {
+ emit updateLayout();
+ }
+
+ return false;
+}
+
+void PanelExtension::setPanelSize(int size)
+{
+ int custom = customSize();
+ if (size > KPanelExtension::SizeCustom)
+ {
+ custom = size;
+ size = KPanelExtension::SizeCustom;
+ }
+
+ setSize(static_cast<Size>(size), custom);
+
+ // save the size setting here if it isn't a custom setting
+ config()->setGroup("General");
+ config()->writeEntry("Size", size);
+ config()->sync();
+}
+
+void PanelExtension::addKMenuButton()
+{
+ _containerArea->addKMenuButton();
+}
+
+void PanelExtension::addDesktopButton()
+{
+ _containerArea->addDesktopButton();
+}
+
+void PanelExtension::addWindowListButton()
+{
+ _containerArea->addWindowListButton();
+}
+
+void PanelExtension::addURLButton(const QString &url)
+{
+ _containerArea->addURLButton(url);
+}
+
+void PanelExtension::addBrowserButton(const QString &startDir)
+{
+ _containerArea->addBrowserButton(startDir);
+}
+
+void PanelExtension::addServiceButton(const QString& desktopEntry)
+{
+ _containerArea->addServiceButton(desktopEntry);
+}
+
+void PanelExtension::addServiceMenuButton(const QString &,
+ const QString& relPath)
+{
+ _containerArea->addServiceMenuButton(relPath);
+}
+
+void PanelExtension::addNonKDEAppButton(const QString &filePath,
+ const QString &icon,
+ const QString &cmdLine, bool inTerm)
+{
+ _containerArea->addNonKDEAppButton(filePath, QString::null, filePath, icon,
+ cmdLine, inTerm);
+}
+
+void PanelExtension::addNonKDEAppButton(const QString &title,
+ const QString &description,
+ const QString &filePath,
+ const QString &icon,
+ const QString &cmdLine, bool inTerm)
+{
+ _containerArea->addNonKDEAppButton(title, description, filePath, icon,
+ cmdLine, inTerm);
+}
+
+void PanelExtension::addApplet(const QString &desktopFile)
+{
+ _containerArea->addApplet(AppletInfo(desktopFile, QString::null, AppletInfo::Applet));
+}
+
+void PanelExtension::addAppletContainer(const QString &desktopFile)
+{
+ // KDE4: this appears in the DCOP interface.
+ // but it's such a bad name, can this go away?
+ addApplet(desktopFile);
+}
+
+bool PanelExtension::insertApplet(const QString& desktopFile, int index)
+{
+ return _containerArea->addApplet(desktopFile, false, index) != 0;
+}
+
+bool PanelExtension::insertImmutableApplet(const QString& desktopFile, int index)
+{
+ return _containerArea->addApplet(desktopFile, true, index) != 0;
+}
+
+QStringList PanelExtension::listApplets()
+{
+ return _containerArea->listContainers();
+ BaseContainer::List containers = _containerArea->containers("All");
+ QStringList names;
+
+ for (BaseContainer::List::const_iterator it = containers.constBegin();
+ it != containers.constEnd();
+ ++it)
+ {
+ names.append((*it)->visibleName());
+ }
+
+ return names;
+}
+
+bool PanelExtension::removeApplet(int index)
+{
+ return _containerArea->removeContainer(index);
+}
+
+void PanelExtension::restart()
+{
+ Kicker::the()->restart();
+}
+
+void PanelExtension::configure()
+{
+ Kicker::the()->configure();
+}
+
+void PanelExtension::slotBuildOpMenu()
+{
+ const int REMOVE_EXTENSION_ID = 1000;
+ if (m_opMenuBuilt || !_opMnu)
+ {
+ if (_opMnu)
+ {
+ bool haveExtensions = ExtensionManager::the()->containers().count() > 0;
+ _opMnu->setItemEnabled(REMOVE_EXTENSION_ID, haveExtensions);
+ }
+
+ return;
+ }
+
+ _opMnu->clear();
+
+ delete m_panelAddMenu;
+ m_panelAddMenu = 0;
+ delete m_removeMnu;
+ m_removeMnu = 0;
+ delete m_addExtensionMenu;
+ m_addExtensionMenu = 0;
+ delete m_removeExtensionMenu;
+ m_removeExtensionMenu = 0;
+
+ m_opMenuBuilt = true;
+ bool kickerImmutable = Kicker::the()->isImmutable();
+ bool isMenuBar = ExtensionManager::the()->isMenuBar(dynamic_cast<QWidget*>(parent()));
+
+ if (!kickerImmutable)
+ {
+ // setup addmenu and removemenu
+ if (_containerArea->canAddContainers())
+ {
+ _opMnu->insertItem(isMenuBar ? i18n("Add &Applet to Menubar...")
+ : i18n("Add &Applet to Panel..."),
+ _containerArea, SLOT(showAddAppletDialog()));
+ m_panelAddMenu = new PanelAddButtonMenu(_containerArea, this);
+ _opMnu->insertItem(isMenuBar ? i18n("Add Appli&cation to Menubar")
+ : i18n("Add Appli&cation to Panel"),
+ m_panelAddMenu);
+
+ m_removeMnu = new RemoveContainerMenu(_containerArea, this);
+ _opMnu->insertItem(isMenuBar ? i18n("&Remove From Menubar")
+ : i18n("&Remove From Panel"),
+ m_removeMnu);
+ _opMnu->insertSeparator();
+
+ m_addExtensionMenu = new PanelAddExtensionMenu(this);
+ _opMnu->insertItem(i18n("Add New &Panel"), m_addExtensionMenu);
+ m_removeExtensionMenu = new PanelRemoveExtensionMenu(this);
+ _opMnu->insertItem(i18n("Remove Pa&nel"), m_removeExtensionMenu,
+ REMOVE_EXTENSION_ID);
+ _opMnu->setItemEnabled(REMOVE_EXTENSION_ID,
+ ExtensionManager::the()->containers().count() > 0);
+ _opMnu->insertSeparator();
+ }
+
+ _opMnu->insertItem(SmallIconSet("lock"), i18n("&Lock Panels"),
+ Kicker::the(), SLOT(toggleLock()));
+ }
+ else if (!Kicker::the()->isKioskImmutable())
+ {
+ _opMnu->insertItem(kickerImmutable? SmallIconSet("unlock") :
+ SmallIconSet("lock"),
+ kickerImmutable ? i18n("Un&lock Panels") :
+ i18n("&Lock Panels"),
+ Kicker::the(), SLOT(toggleLock()));
+ }
+
+ if (!isMenuBar && !Kicker::the()->isKioskImmutable())
+ {
+ _opMnu->insertItem(SmallIconSet("configure"),
+ i18n("&Configure Panel..."),
+ this, SLOT(showConfig()));
+ _opMnu->insertSeparator();
+ }
+
+ if (kapp->authorize("action/help"))
+ {
+ KHelpMenu* help = new KHelpMenu( this, KGlobal::instance()->aboutData(), false);
+ _opMnu->insertItem(SmallIconSet("help"), KStdGuiItem::help().text(), help->menu());
+ }
+ _opMnu->adjustSize();
+}
+
+void PanelExtension::showConfig()
+{
+ Kicker::the()->showConfig(_configFile);
+}
+
+MenubarExtension::MenubarExtension(const AppletInfo& info)
+ : PanelExtension(info.configFile()),
+ m_menubar(0)
+{
+}
+
+MenubarExtension::~MenubarExtension()
+{
+ if (m_menubar)
+ {
+ m_menubar->setImmutable(false);
+ _containerArea->slotSaveContainerConfig();
+ }
+}
+
+void MenubarExtension::populateContainerArea()
+{
+ PanelExtension::populateContainerArea();
+ BaseContainer::List containers = _containerArea->containers("All");
+ for (BaseContainer::Iterator it = containers.begin();
+ it != containers.end();
+ ++it)
+ {
+ if ((*it)->appletType() == "Applet")
+ {
+ AppletContainer* applet = dynamic_cast<AppletContainer*>(*it);
+ if (applet && applet->info().desktopFile() == "menuapplet.desktop")
+ {
+ m_menubar = applet;
+ break;
+ }
+ }
+ }
+
+ if (!m_menubar)
+ {
+ m_menubar = _containerArea->addApplet(AppletInfo("menuapplet.desktop",
+ QString::null,
+ AppletInfo::Applet));
+ }
+
+ // in the pathological case we may not have a menuapplet at all,
+ // so check for it =/
+ if (m_menubar)
+ {
+ m_menubar->setImmutable(true);
+ }
+}
+
diff --git a/kicker/kicker/core/panelextension.h b/kicker/kicker/core/panelextension.h
new file mode 100644
index 000000000..d1d7deb28
--- /dev/null
+++ b/kicker/kicker/core/panelextension.h
@@ -0,0 +1,126 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter
+ 2004 Aaron J. Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef _panelextension_h_
+#define _panelextension_h_
+
+#include <kpanelextension.h>
+#include <dcopobject.h>
+
+#include "appletinfo.h"
+
+class AppletContainer;
+class ContainerArea;
+class QPopupMenu;
+class QGridLayout;
+
+// This is the KPanelExtension responsible for the main kicker panel
+// Prior to KDE 3.4 it was the ChildPanelExtension
+
+class PanelExtension : public KPanelExtension, virtual public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+public:
+ PanelExtension(const QString& configFile, QWidget *parent = 0, const char *name = 0);
+ virtual ~PanelExtension();
+
+ QPopupMenu* opMenu();
+
+k_dcop:
+ int panelSize() { return sizeInPixels(); }
+ int panelOrientation() { return static_cast<int>(orientation()); }
+ int panelPosition() { return static_cast<int>(position()); }
+
+ void setPanelSize(int size);
+ void addKMenuButton();
+ void addDesktopButton();
+ void addWindowListButton();
+ void addURLButton(const QString &url);
+ void addBrowserButton(const QString &startDir);
+ void addServiceButton(const QString &desktopEntry);
+ void addServiceMenuButton(const QString &name, const QString& relPath);
+ void addNonKDEAppButton(const QString &filePath, const QString &icon,
+ const QString &cmdLine, bool inTerm);
+ void addNonKDEAppButton(const QString &title, const QString &description,
+ const QString &filePath, const QString &icon,
+ const QString &cmdLine, bool inTerm);
+
+ void addApplet(const QString &desktopFile);
+ void addAppletContainer(const QString &desktopFile); // KDE4: remove, useless
+
+ bool insertApplet(const QString& desktopFile, int index);
+ bool insertImmutableApplet(const QString& desktopFile, int index);
+ QStringList listApplets();
+ bool removeApplet(int index);
+
+ void restart(); // KDE4: remove, moved to Kicker
+ void configure(); // KDE4: remove, moved to Kikcker
+
+public:
+ QSize sizeHint(Position, QSize maxSize) const;
+ Position preferedPosition() const { return Bottom; }
+ bool eventFilter( QObject *, QEvent * );
+
+protected:
+ void positionChange(Position);
+
+ ContainerArea *_containerArea;
+
+protected slots:
+ void configurationChanged();
+ void immutabilityChanged(bool);
+ void slotBuildOpMenu();
+ void showConfig();
+ virtual void populateContainerArea();
+
+private:
+ QPopupMenu* _opMnu;
+ QPopupMenu* m_panelAddMenu;
+ QPopupMenu* m_removeMnu;
+ QPopupMenu* m_addExtensionMenu;
+ QPopupMenu* m_removeExtensionMenu;
+ QString _configFile;
+ bool m_opMenuBuilt;
+};
+
+class MenubarExtension : public PanelExtension
+{
+ Q_OBJECT
+
+ public:
+ MenubarExtension(const AppletInfo& info);
+ virtual ~MenubarExtension();
+
+ protected slots:
+ virtual void populateContainerArea();
+
+ private:
+ MenubarExtension();
+
+ AppletContainer* m_menubar;
+};
+
+#endif
diff --git a/kicker/kicker/core/pluginmanager.cpp b/kicker/kicker/core/pluginmanager.cpp
new file mode 100644
index 000000000..e392959ad
--- /dev/null
+++ b/kicker/kicker/core/pluginmanager.cpp
@@ -0,0 +1,378 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qfile.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klibloader.h>
+#include <kpanelapplet.h>
+#include <kpanelextension.h>
+#include <kstandarddirs.h>
+#include <kstaticdeleter.h>
+
+#include "appletinfo.h"
+#include "container_applet.h"
+#include "container_extension.h"
+#include "panelextension.h"
+#include "pluginmanager.h"
+
+static KStaticDeleter<PluginManager> pluginManagerDeleter;
+PluginManager* PluginManager::m_self = 0;
+
+PluginManager* PluginManager::the()
+{
+ if (!m_self)
+ {
+ pluginManagerDeleter.setObject(m_self, new PluginManager());
+ }
+
+ return m_self;
+}
+
+AppletInfo::List PluginManager::applets(bool sort, AppletInfo::List* list)
+{
+ QStringList rel;
+ KGlobal::dirs()->findAllResources("applets", "*.desktop", false, true, rel);
+ return plugins(rel, AppletInfo::Applet, sort, list);
+}
+
+AppletInfo::List PluginManager::extensions(bool sort, AppletInfo::List* list)
+{
+ QStringList rel;
+ KGlobal::dirs()->findAllResources("extensions", "*.desktop", false, true, rel);
+ return plugins(rel, AppletInfo::Extension, sort, list);
+}
+
+AppletInfo::List PluginManager::builtinButtons(bool sort, AppletInfo::List* list)
+{
+ QStringList rel;
+ KGlobal::dirs()->findAllResources("builtinbuttons", "*.desktop", false, true, rel);
+ return plugins(rel, AppletInfo::BuiltinButton, sort, list);
+}
+
+AppletInfo::List PluginManager::specialButtons(bool sort, AppletInfo::List* list)
+{
+ QStringList rel;
+ KGlobal::dirs()->findAllResources("specialbuttons", "*.desktop", false, true, rel);
+ return plugins(rel, AppletInfo::SpecialButton, sort, list);
+}
+
+AppletInfo::List PluginManager::plugins(const QStringList& desktopFiles,
+ AppletInfo::AppletType type,
+ bool sort,
+ AppletInfo::List* list)
+{
+ AppletInfo::List plugins;
+
+ if (list)
+ {
+ plugins = *list;
+ }
+
+ for (QStringList::ConstIterator it = desktopFiles.constBegin();
+ it != desktopFiles.constEnd(); ++it)
+ {
+ AppletInfo info(*it, QString::null, type);
+
+ if (!info.isHidden())
+ {
+ plugins.append(info);
+ }
+ }
+
+ if (sort)
+ {
+ qHeapSort(plugins.begin(), plugins.end());
+ }
+
+ return plugins;
+}
+
+PluginManager::PluginManager()
+{
+ KConfigGroup generalGroup(KGlobal::config(), "General");
+ m_untrustedApplets = generalGroup.readListEntry("UntrustedApplets");
+ m_untrustedExtensions = generalGroup.readListEntry("UntrustedExtensions");
+}
+
+PluginManager::~PluginManager()
+{
+ AppletInfo::Dict::const_iterator it = _dict.constBegin();
+ for (; it != _dict.constEnd(); ++it)
+ {
+ disconnect(it.key(), SIGNAL(destroyed( QObject*)),
+ this, SLOT(slotPluginDestroyed(QObject*)));
+ delete it.data();
+ }
+
+ // clear the untrusted lists
+ clearUntrustedLists();
+}
+
+KPanelApplet* PluginManager::loadApplet(const AppletInfo& info,
+ QWidget* parent )
+{
+ KLibLoader* loader = KLibLoader::self();
+ KLibrary* lib = loader->library( QFile::encodeName(info.library()) );
+
+ if (!lib)
+ {
+ kdWarning() << "cannot open applet: " << info.library()
+ << " because of " << loader->lastErrorMessage() << endl;
+ return 0;
+ }
+
+ KPanelApplet* (*init_ptr)(QWidget *, const QString&);
+ init_ptr = (KPanelApplet* (*)(QWidget *, const QString&))lib->symbol( "init" );
+
+ if (!init_ptr)
+ {
+ kdWarning() << info.library() << " is not a kicker extension!" << endl;
+ loader->unloadLibrary( QFile::encodeName(info.library()) );
+ return 0;
+ }
+
+ KPanelApplet* applet = init_ptr( parent, info.configFile() );
+
+ if (applet)
+ {
+ _dict.insert( applet, new AppletInfo( info ) );
+ connect( applet, SIGNAL( destroyed( QObject* ) ),
+ SLOT( slotPluginDestroyed( QObject* ) ) );
+ }
+
+ return applet;
+}
+
+KPanelExtension* PluginManager::loadExtension(
+ const AppletInfo& info, QWidget* parent )
+{
+ if (info.library() == "childpanel_panelextension"
+ /* KDE4? || info.library() == "panel" */)
+ {
+ return new PanelExtension(info.configFile(), parent, "panelextension");
+ }
+
+ KLibLoader* loader = KLibLoader::self();
+ KLibrary* lib = loader->library( QFile::encodeName(info.library()) );
+
+ if( !lib ) {
+ kdWarning() << "cannot open extension: " << info.library()
+ << " because of " << loader->lastErrorMessage() << endl;
+ return 0;
+ }
+
+ KPanelExtension* (*init_ptr)(QWidget *, const QString&);
+ init_ptr = (KPanelExtension* (*)(QWidget *, const QString&))lib->symbol( "init" );
+
+ if(!init_ptr){
+ kdWarning() << info.library() << " is not a kicker extension!" << endl;
+ loader->unloadLibrary( QFile::encodeName(info.library()) );
+ return 0;
+ }
+
+ KPanelExtension* extension = init_ptr( parent, info.configFile() );
+
+ if( extension ) {
+ _dict.insert( extension, new AppletInfo( info ) );
+ connect( extension, SIGNAL( destroyed( QObject* ) ),
+ SLOT( slotPluginDestroyed( QObject* ) ) );
+ }
+
+ return extension;
+}
+
+bool PluginManager::hasInstance( const AppletInfo& info ) const
+{
+ AppletInfo::Dict::const_iterator it = _dict.constBegin();
+ for (; it != _dict.constEnd(); ++it)
+ {
+ if (it.data()->library() == info.library())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void PluginManager::slotPluginDestroyed(QObject* object)
+{
+ AppletInfo* info = 0;
+ AppletInfo::Dict::iterator it = _dict.begin();
+ for (; it != _dict.end(); ++it)
+ {
+ if (it.key() == object)
+ {
+ info = dynamic_cast<AppletInfo*>(it.data());
+ _dict.erase(it);
+ break;
+ }
+ }
+
+ if (!info)
+ {
+ return;
+ }
+
+ LibUnloader::unload(info->library());
+ delete info;
+}
+
+AppletContainer* PluginManager::createAppletContainer(
+ const QString& desktopFile,
+ bool isStartup,
+ const QString& configFile,
+ QPopupMenu* opMenu,
+ QWidget* parent,
+ bool isImmutable)
+{
+ QString desktopPath = KGlobal::dirs()->findResource( "applets", desktopFile );
+
+ // KDE4: remove
+ // support the old (KDE 2.2) nameing scheme
+ if (desktopPath.isEmpty())
+ {
+ desktopPath = KGlobal::dirs()->findResource( "applets",
+ desktopFile.right(
+ desktopFile.length() - 1 ) );
+ }
+
+ if (desktopPath.isEmpty())
+ return 0;
+
+ AppletInfo info( desktopPath, configFile, AppletInfo::Applet );
+
+ bool instanceFound = hasInstance(info);
+ if (info.isUniqueApplet() && instanceFound)
+ {
+ return 0;
+ }
+
+ bool untrusted = m_untrustedApplets.find(desktopFile) != m_untrustedApplets.end();
+ if (isStartup && untrusted)
+ {
+ // don't load extensions that bombed on us previously!
+ return 0;
+ }
+ else if (!isStartup && !instanceFound && !untrusted)
+ {
+ // we haven't loaded this puppy before and we're not in the untrusted list
+ m_untrustedApplets.append(desktopFile);
+ KConfigGroup generalGroup(KGlobal::config(), "General");
+ generalGroup.writeEntry("UntrustedApplets", m_untrustedApplets);
+ generalGroup.sync();
+ }
+
+ AppletContainer* container = new AppletContainer(info, opMenu, isImmutable, parent);
+
+ if (!container->isValid())
+ {
+ delete container;
+ return 0;
+ }
+
+ return container;
+}
+
+ExtensionContainer* PluginManager::createExtensionContainer(const QString& desktopFile,
+ bool isStartup,
+ const QString& configFile,
+ const QString& extensionId)
+{
+ if (desktopFile.isEmpty())
+ {
+ return 0;
+ }
+
+ QString desktopPath = KGlobal::dirs()->findResource("extensions", desktopFile);
+ if (desktopPath.isEmpty())
+ {
+ return 0;
+ }
+
+ AppletInfo info( desktopPath, configFile, AppletInfo::Extension );
+
+ bool internal = (info.library() == "childpanel_panelextension");
+ bool instance = !internal && hasInstance(info);
+ if (instance && info.isUniqueApplet())
+ {
+ return 0;
+ }
+
+ if (!internal)
+ {
+ bool untrusted = m_untrustedExtensions.find(desktopFile) != m_untrustedExtensions.end();
+ if (isStartup && untrusted)
+ {
+ // don't load extensions that bombed on us previously!
+ return 0;
+ }
+ else if (!isStartup && !instance && !untrusted)
+ {
+ // we don't have an instance around and we're not in the untrusted list!
+ m_untrustedExtensions.append(desktopFile);
+ KConfigGroup generalGroup(KGlobal::config(), "General");
+ generalGroup.writeEntry("UntrustedExtensions", m_untrustedExtensions);
+ generalGroup.sync();
+ }
+ }
+
+ return new ExtensionContainer(info, extensionId);
+}
+
+void PluginManager::clearUntrustedLists()
+{
+ m_untrustedExtensions.clear();
+ m_untrustedApplets.clear();
+
+ KConfigGroup generalGroup(KGlobal::config(), "General");
+ generalGroup.writeEntry("UntrustedApplets", m_untrustedApplets);
+ generalGroup.writeEntry("UntrustedExtensions", m_untrustedExtensions);
+ generalGroup.sync();
+}
+
+LibUnloader::LibUnloader( const QString &libName, QObject *parent )
+ : QObject( parent ), _libName( libName )
+{
+ // NOTE: this doesn't work on kicker shutdown because the timer never gets
+ // fired.
+ QTimer::singleShot( 0, this, SLOT( unload() ) );
+}
+
+void LibUnloader::unload( const QString &libName )
+{
+ (void)new LibUnloader( libName, kapp );
+}
+
+void LibUnloader::unload()
+{
+ KLibLoader::self()->unloadLibrary( QFile::encodeName( _libName ) );
+ deleteLater();
+}
+
+#include "pluginmanager.moc"
+
diff --git a/kicker/kicker/core/pluginmanager.h b/kicker/kicker/core/pluginmanager.h
new file mode 100644
index 000000000..bbea87b30
--- /dev/null
+++ b/kicker/kicker/core/pluginmanager.h
@@ -0,0 +1,106 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __PLUGIN_MANAGER_H__
+#define __PLUGIN_MANAGER_H__
+
+#include <qmap.h>
+#include <qobject.h>
+#include <qstringlist.h>
+#include <kdemacros.h>
+#include <kstaticdeleter.h>
+
+#include "appletinfo.h"
+
+class AppletContainer;
+class ExtensionContainer;
+class KPanelApplet;
+class KPanelExtension;
+class QPopupMenu;
+
+class KDE_EXPORT PluginManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ static PluginManager* the();
+ static AppletInfo::List applets(bool sort = true, AppletInfo::List* list = 0);
+ static AppletInfo::List extensions(bool sort = true, AppletInfo::List* list = 0);
+ static AppletInfo::List builtinButtons(bool sort = true, AppletInfo::List* list = 0);
+ static AppletInfo::List specialButtons(bool sort = true, AppletInfo::List* list = 0);
+
+ AppletContainer* createAppletContainer(const QString& desktopFile,
+ bool isStartup,
+ const QString& configFile,
+ QPopupMenu* opMenu,
+ QWidget* parent,
+ bool isImmutable = false);
+ ExtensionContainer* createExtensionContainer(const QString& desktopFile,
+ bool isStartup,
+ const QString& configFile,
+ const QString& extensionId);
+
+ KPanelApplet* loadApplet(const AppletInfo& info, QWidget* parent);
+ KPanelExtension* loadExtension(const AppletInfo& info, QWidget* parent);
+
+ bool hasInstance(const AppletInfo&) const;
+
+public slots:
+ void clearUntrustedLists();
+
+protected:
+ static AppletInfo::List plugins(const QStringList& desktopFiles,
+ AppletInfo::AppletType,
+ bool sort,
+ AppletInfo::List* list);
+
+private slots:
+ void slotPluginDestroyed(QObject* plugin);
+
+private:
+ friend class KStaticDeleter<PluginManager>;
+ PluginManager();
+ virtual ~PluginManager();
+
+ AppletInfo::Dict _dict;
+ static PluginManager* m_self;
+ QStringList m_untrustedApplets;
+ QStringList m_untrustedExtensions;
+};
+
+class LibUnloader : public QObject
+{
+ Q_OBJECT
+public:
+ static void unload( const QString &libName );
+
+private slots:
+ void unload();
+
+private:
+ LibUnloader( const QString &libName, QObject *parent );
+
+ QString _libName;
+};
+
+#endif
diff --git a/kicker/kicker/core/showdesktop.cpp b/kicker/kicker/core/showdesktop.cpp
new file mode 100644
index 000000000..5575b3b28
--- /dev/null
+++ b/kicker/kicker/core/showdesktop.cpp
@@ -0,0 +1,198 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001,2002 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+// kicker.h needs to be up here due to compilation errors that result
+// it's placed further on. >=(
+#include "kicker.h"
+#include "kickerSettings.h"
+
+#include <kwin.h>
+#include <kwinmodule.h>
+#include <netwm.h>
+
+#include "showdesktop.h"
+#include "showdesktop.moc"
+
+ShowDesktop* ShowDesktop::the()
+{
+ static ShowDesktop showDesktop;
+ return &showDesktop;
+}
+
+ShowDesktop::ShowDesktop()
+ : QObject(),
+ m_showingDesktop(false)
+{
+ // This feature is implemented in KWin. Keep old code in Kicker for the case
+ // KDE is running with another WM without the feature.
+ NETRootInfo i( qt_xdisplay(), NET::Supported );
+ m_wmSupport = i.isSupported( NET::WM2ShowingDesktop );
+ if( m_wmSupport )
+ {
+ connect( Kicker::the()->kwinModule(), SIGNAL( showingDesktopChanged( bool )),
+ SLOT( showingDesktopChanged( bool )));
+ showingDesktopChanged( m_showingDesktop = Kicker::the()->kwinModule()->showingDesktop());
+ }
+}
+
+void ShowDesktop::slotCurrentDesktopChanged(int)
+{
+ showDesktop( false );
+}
+
+void ShowDesktop::slotWindowAdded(WId w)
+{
+ if (!m_showingDesktop)
+ {
+ return;
+ }
+
+ NETWinInfo inf(qt_xdisplay(), w, qt_xrootwin(),
+ NET::XAWMState | NET::WMWindowType);
+ NET::WindowType windowType = inf.windowType(NET::AllTypesMask);
+
+ if ((windowType == NET::Normal || windowType == NET::Unknown) &&
+ inf.mappingState() == NET::Visible)
+ {
+ KConfig kwincfg( "kwinrc", true ); // see in kwin
+ kwincfg.setGroup( "Windows" );
+ if( kwincfg.readBoolEntry( "ShowDesktopIsMinimizeAll", false ))
+ {
+ m_iconifiedList.clear();
+ m_showingDesktop = false;
+ emit desktopShown(false);
+ }
+ else
+ {
+ m_activeWindow = w;
+ showDesktop(false);
+ }
+ }
+}
+
+void ShowDesktop::slotWindowChanged(WId w, unsigned int dirty)
+{
+ if (!m_showingDesktop)
+ {
+ return;
+ }
+
+ if (dirty & NET::XAWMState)
+ {
+ NETWinInfo inf(qt_xdisplay(), w, qt_xrootwin(),
+ NET::XAWMState | NET::WMWindowType);
+ NET::WindowType windowType = inf.windowType(NET::AllTypesMask);
+
+ if ((windowType == NET::Normal || windowType == NET::Unknown) &&
+ inf.mappingState() == NET::Visible)
+ {
+ // a window was deiconified, abort the show desktop mode.
+ m_iconifiedList.clear();
+ m_showingDesktop = false;
+ emit desktopShown(false);
+ }
+ }
+}
+
+void ShowDesktop::showDesktop( bool b )
+{
+ if (b == m_showingDesktop)
+ {
+ return;
+ }
+
+ if( m_wmSupport )
+ {
+ NETRootInfo i( qt_xdisplay(), 0 );
+ i.setShowingDesktop( b );
+ return;
+ }
+
+ if (b)
+ {
+ m_activeWindow = Kicker::the()->kwinModule()->activeWindow();
+ m_iconifiedList.clear();
+
+ const QValueList<WId> windows = Kicker::the()->kwinModule()->windows();
+ for (QValueList<WId>::ConstIterator it = windows.begin();
+ it != windows.end();
+ ++it)
+ {
+ WId w = *it;
+
+ NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(),
+ NET::XAWMState | NET::WMDesktop );
+
+ if (info.mappingState() == NET::Visible &&
+ (info.desktop() == NETWinInfo::OnAllDesktops ||
+ info.desktop() == (int)Kicker::the()->kwinModule()->currentDesktop()))
+ {
+ m_iconifiedList.append( w );
+ }
+ }
+
+ // find first, hide later, otherwise transients may get minimized
+ // with the window they're transient for
+ for (QValueVector<WId>::Iterator it = m_iconifiedList.begin();
+ it != m_iconifiedList.end();
+ ++it)
+ {
+ KWin::iconifyWindow( *it, false );
+ }
+
+ // on desktop changes or when a window is deiconified, we abort the show desktop mode
+ connect(Kicker::the()->kwinModule(), SIGNAL(currentDesktopChanged(int)),
+ SLOT(slotCurrentDesktopChanged(int)));
+ connect(Kicker::the()->kwinModule(), SIGNAL(windowChanged(WId,unsigned int)),
+ SLOT(slotWindowChanged(WId,unsigned int)));
+ connect(Kicker::the()->kwinModule(), SIGNAL(windowAdded(WId)),
+ SLOT(slotWindowAdded(WId)));
+ }
+ else
+ {
+ disconnect(Kicker::the()->kwinModule(), SIGNAL(currentDesktopChanged(int)),
+ this, SLOT(slotCurrentDesktopChanged(int)));
+ disconnect(Kicker::the()->kwinModule(), SIGNAL(windowChanged(WId,unsigned int)),
+ this, SLOT(slotWindowChanged(WId,unsigned int)));
+ disconnect(Kicker::the()->kwinModule(), SIGNAL(windowAdded(WId)),
+ this, SLOT(slotWindowAdded(WId)));
+
+ for (QValueVector<WId>::ConstIterator it = m_iconifiedList.begin();
+ it != m_iconifiedList.end();
+ ++it)
+ {
+ KWin::deIconifyWindow(*it, false);
+ }
+
+ KWin::forceActiveWindow(m_activeWindow);
+ }
+
+ m_showingDesktop = b;
+ emit desktopShown(m_showingDesktop);
+}
+
+void ShowDesktop::showingDesktopChanged( bool showing )
+{
+ m_showingDesktop = showing;
+ emit desktopShown(m_showingDesktop);
+}
diff --git a/kicker/kicker/core/showdesktop.h b/kicker/kicker/core/showdesktop.h
new file mode 100644
index 000000000..bebf62007
--- /dev/null
+++ b/kicker/kicker/core/showdesktop.h
@@ -0,0 +1,64 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000,2002 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __showdesktop_h__
+#define __showdesktop_h__
+
+class KWinModule;
+
+#include <qvaluevector.h>
+
+/**
+ * Singleton class that handles desktop access (minimizing all windows)
+ */
+class ShowDesktop : public QObject
+{
+ Q_OBJECT
+
+public:
+ static ShowDesktop* the();
+ bool desktopShowing() { return m_showingDesktop; }
+
+public slots:
+ void showDesktop(bool show);
+ void toggle() { showDesktop( !desktopShowing() ); }
+
+signals:
+ void desktopShown(bool shown);
+
+private slots:
+ void slotCurrentDesktopChanged(int);
+ void slotWindowAdded(WId w);
+ void slotWindowChanged(WId w, unsigned int dirty);
+ void showingDesktopChanged( bool );
+
+private:
+ ShowDesktop();
+
+ bool m_showingDesktop;
+ QValueVector<WId> m_iconifiedList;
+ WId m_activeWindow;
+ bool m_wmSupport;
+};
+
+#endif
diff --git a/kicker/kicker/core/unhidetrigger.cpp b/kicker/kicker/core/unhidetrigger.cpp
new file mode 100644
index 000000000..bd0e0a0f8
--- /dev/null
+++ b/kicker/kicker/core/unhidetrigger.cpp
@@ -0,0 +1,137 @@
+/*****************************************************************
+
+Copyright (c) 2002 John Firebaugh <jfirebaugh@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qtimer.h>
+#include <qcursor.h>
+#include <kdebug.h>
+
+#include "unhidetrigger.h"
+#include "unhidetrigger.moc"
+
+UnhideTrigger* UnhideTrigger::the()
+{
+ static UnhideTrigger UnhideTrigger;
+ return &UnhideTrigger;
+}
+
+UnhideTrigger::UnhideTrigger()
+ : _lastTrigger( None )
+ , _lastXineramaScreen( -1 )
+ , enabledCount( 0 )
+{
+ _timer = new QTimer( this );
+ connect( _timer, SIGNAL(timeout()), SLOT(pollMouse()) );
+}
+
+void UnhideTrigger::setEnabled( bool enable )
+{
+ if( enable ) {
+ enabledCount++;
+ } else {
+ enabledCount--;
+ }
+
+ if ( enabledCount > 0 && !_timer->isActive() ) {
+ _timer->start( 100 );
+ } else if( enabledCount <= 0 ) {
+ _timer->stop();
+ }
+}
+
+bool UnhideTrigger::isEnabled() const
+{
+ return _timer->isActive();
+}
+
+void UnhideTrigger::pollMouse()
+{
+ QPoint pos = QCursor::pos();
+ for(int s = 0; s < QApplication::desktop()->numScreens(); s++)
+ {
+ QRect r = QApplication::desktop()->screenGeometry(s);
+ if (pos.x() == r.left())
+ {
+ if (pos.y() == r.top())
+ {
+ emitTrigger(TopLeft, s);
+ }
+ else if (pos.y() == r.bottom())
+ {
+ emitTrigger(BottomLeft, s);
+ }
+ else
+ {
+ emitTrigger(Left, s);
+ }
+ }
+ else if (pos.x() == r.right())
+ {
+ if (pos.y() == r.top())
+ {
+ emitTrigger(TopRight, s);
+ }
+ else if (pos.y() == r.bottom())
+ {
+ emitTrigger(BottomRight, s);
+ }
+ else
+ {
+ emitTrigger(Right, s);
+ }
+ }
+ else if (pos.y() == r.top())
+ {
+ emitTrigger(Top, s);
+ }
+ else if (pos.y() == r.bottom())
+ {
+ emitTrigger(Bottom, s);
+ }
+ else if (_lastTrigger != None)
+ {
+ emitTrigger(None, -1);
+ }
+ }
+}
+
+void UnhideTrigger::resetTriggerThrottle()
+{
+ _lastTrigger = None;
+ _lastXineramaScreen = -1;
+}
+
+void UnhideTrigger::emitTrigger( Trigger t, int XineramaScreen )
+{
+ if( _lastTrigger == t && _lastXineramaScreen == XineramaScreen)
+ return;
+
+ resetTriggerThrottle();
+ emit triggerUnhide( t, XineramaScreen );
+}
+
+void UnhideTrigger::triggerAccepted( Trigger t, int XineramaScreen )
+{
+ _lastTrigger = t;
+ _lastXineramaScreen = XineramaScreen;
+}
+
diff --git a/kicker/kicker/core/unhidetrigger.h b/kicker/kicker/core/unhidetrigger.h
new file mode 100644
index 000000000..7e13a0e1d
--- /dev/null
+++ b/kicker/kicker/core/unhidetrigger.h
@@ -0,0 +1,62 @@
+/*****************************************************************
+
+Copyright (c) 2002 John Firebaugh <jfirebaugh@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __UnhideTrigger_h__
+#define __UnhideTrigger_h__
+
+// Fix compilation with --enable-final
+#ifdef None
+#undef None
+#endif
+
+
+#include <qobject.h>
+
+class UnhideTrigger : public QObject
+{
+ Q_OBJECT
+public:
+ enum Trigger { None = 0, Top, TopRight, Right, BottomRight, Bottom, BottomLeft, Left, TopLeft };
+ static UnhideTrigger* the();
+
+ void setEnabled( bool enable );
+ bool isEnabled() const;
+
+ // this is called whenever an item accepts a trigger, thereby preventing further calling of it again
+ void triggerAccepted( UnhideTrigger::Trigger t, int XineramaScreen );
+ void resetTriggerThrottle();
+
+signals:
+ void triggerUnhide( UnhideTrigger::Trigger t, int XineramaScreen );
+private slots:
+ void pollMouse();
+private:
+ UnhideTrigger();
+ void emitTrigger( Trigger t , int XineramaScreen );
+ Trigger _lastTrigger;
+ int _lastXineramaScreen;
+ QTimer *_timer;
+ int enabledCount;
+};
+
+#endif
diff --git a/kicker/kicker/core/userrectsel.cpp b/kicker/kicker/core/userrectsel.cpp
new file mode 100644
index 000000000..5654b1eb3
--- /dev/null
+++ b/kicker/kicker/core/userrectsel.cpp
@@ -0,0 +1,147 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qapplication.h>
+#include <qpainter.h>
+
+#include "userrectsel.h"
+#include "userrectsel.moc"
+
+UserRectSel::UserRectSel(const RectList& rects, const QPoint& _offset, const QColor& color)
+ : QWidget(0, 0, WStyle_Customize | WX11BypassWM),
+ rectangles(rects),
+ offset(_offset)
+{
+ setGeometry(-10, -10, 2, 2);
+ _color = color;
+ for (int i = 0; i < 8; i++)
+ _frame[i] = 0;
+}
+
+UserRectSel::~UserRectSel()
+{
+ for (int i = 0; i < 8; i++)
+ delete _frame[i];
+}
+
+void UserRectSel::mouseReleaseEvent(QMouseEvent * e)
+{
+ if (e->button() == LeftButton)
+ {
+ qApp->exit_loop();
+ }
+}
+
+void UserRectSel::mouseMoveEvent(QMouseEvent * e)
+{
+ PanelStrut nearest = current;
+ int diff = -1;
+ QPoint p = e->globalPos(); // + offset;
+ for (RectList::const_iterator it = rectangles.constBegin();
+ it != rectangles.constEnd();
+ ++it)
+ {
+ PanelStrut r = *it;
+ int ndiff = (r.m_rect.center() - p).manhattanLength();
+
+ if (diff < 0 || ndiff < diff)
+ {
+ diff = ndiff;
+ nearest = r;
+ }
+ }
+
+ if (nearest != current)
+ {
+ paintCurrent();
+ current = nearest;
+ paintCurrent();
+ }
+}
+
+void UserRectSel::paintCurrent()
+{
+ int i;
+ int x, y, w, h;
+
+ if (!_frame[0])
+ {
+ for (i = 0; i < 4; i++)
+ {
+ _frame[i] = new QWidget(0, 0, Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WX11BypassWM);
+ _frame[i]->setPaletteBackgroundColor(Qt::black);
+ }
+ for (i = 4; i < 8; i++)
+ {
+ _frame[i] = new QWidget(0, 0, Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WX11BypassWM);
+ _frame[i]->setPaletteBackgroundColor(_color);
+ }
+ }
+
+ x = current.m_rect.x();
+ y = current.m_rect.y();
+ w = current.m_rect.width();
+ h = current.m_rect.height();
+
+ if (w > 0 && h > 0)
+ {
+ _frame[0]->setGeometry(x, y, w, 4);
+ _frame[1]->setGeometry(x, y, 4, h);
+ _frame[2]->setGeometry(x + w - 4, y, 4, h);
+ _frame[3]->setGeometry(x, y + h - 4, w, 4);
+
+ for (i = 0; i < 4; i++)
+ _frame[i]->show();
+ }
+
+ x += 1;
+ y += 1;
+ w -= 2;
+ h -= 2;
+
+ if (w > 0 && h > 0)
+ {
+ _frame[4]->setGeometry(x, y, w, 2);
+ _frame[5]->setGeometry(x, y, 2, h);
+ _frame[6]->setGeometry(x + w - 2, y, 2, h);
+ _frame[7]->setGeometry(x, y + h - 2, w, 2);
+
+ for (i = 4; i < 8; i++)
+ _frame[i]->show();
+ }
+
+}
+
+UserRectSel::PanelStrut UserRectSel::select(const RectList& rects, const QPoint& offset, const QColor& color)
+{
+ UserRectSel sel(rects, offset, color);
+ sel.show();
+ sel.grabMouse();
+ sel.paintCurrent();
+ qApp->enter_loop();
+ sel.paintCurrent();
+ sel.releaseMouse();
+ qApp->syncX();
+ return sel.current;
+}
+
diff --git a/kicker/kicker/core/userrectsel.h b/kicker/kicker/core/userrectsel.h
new file mode 100644
index 000000000..724f39818
--- /dev/null
+++ b/kicker/kicker/core/userrectsel.h
@@ -0,0 +1,99 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __userrectsel_h__
+#define __userrectsel_h__
+
+#include <qwidget.h>
+#include <qvaluevector.h>
+#include <qcolor.h>
+
+#include <kpanelextension.h>
+
+class ShutUpCompiler;
+
+class UserRectSel : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ class PanelStrut
+ {
+ public:
+ PanelStrut()
+ : m_screen(-1),
+ m_pos(KPanelExtension::Bottom),
+ m_alignment(KPanelExtension::LeftTop)
+ {
+ }
+
+ PanelStrut(const QRect& rect, int XineramaScreen,
+ KPanelExtension::Position pos,
+ KPanelExtension::Alignment alignment)
+ : m_rect(rect),
+ m_screen(XineramaScreen),
+ m_pos(pos),
+ m_alignment(alignment)
+ {
+ }
+
+ bool operator==(const PanelStrut& rhs)
+ {
+ return m_screen == rhs.m_screen &&
+ m_pos == rhs.m_pos &&
+ m_alignment == rhs.m_alignment;
+ }
+
+ bool operator!=(const PanelStrut& rhs)
+ {
+ return !(*this == rhs);
+ }
+
+ QRect m_rect;
+ int m_screen;
+ KPanelExtension::Position m_pos;
+ KPanelExtension::Alignment m_alignment;
+ };
+
+ typedef QValueVector<PanelStrut> RectList;
+ static PanelStrut select(const RectList& rects, const QPoint& _offset, const QColor& color);
+
+ protected:
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+
+ private:
+ UserRectSel(const RectList& rects, const QPoint& _offset, const QColor& color);
+ ~UserRectSel();
+ void paintCurrent();
+
+ const RectList rectangles;
+ PanelStrut current;
+ QPoint offset;
+ QWidget *_frame[8];
+ QColor _color;
+
+ friend class ShutUpCompiler;
+};
+
+#endif
diff --git a/kicker/kicker/kcmkicker.desktop b/kicker/kicker/kcmkicker.desktop
new file mode 100644
index 000000000..d2a575979
--- /dev/null
+++ b/kicker/kicker/kcmkicker.desktop
@@ -0,0 +1,80 @@
+[Desktop Entry]
+Icon=kcmkicker
+Type=Application
+Exec=kcmshell %i kicker_config kcmtaskbar
+Name=Configure the Panel
+Name[af]=Stel die paneel op
+Name[ar]=قم بإعداد اللوحة
+Name[az]=Paneli Quraşdır
+Name[be]=Настаўленне панэлі
+Name[bg]=Настройване на панела
+Name[bn]=প্যানেল কনফিগার করো
+Name[br]=Kefluniañ ar panell
+Name[bs]=Podesite Panel
+Name[ca]=Configura el plafó
+Name[cs]=Nastavit panel
+Name[csb]=Kònfigùracëjô panelu
+Name[cy]=Ffurfweddu'r Panel
+Name[da]=Indstil panelet
+Name[de]=Kontrollleiste einrichten
+Name[el]=Ρύθμιση του πίνακα
+Name[eo]=Agordo de Panelo
+Name[es]=Configuración del panel
+Name[et]=Paneeli seadistamine
+Name[eu]=Konfiguratu panela
+Name[fa]=پیکربندی تابلو
+Name[fi]=Paneelin asetukset
+Name[fr]=Configuration du tableau de bord
+Name[fy]=Paniel ynstelle
+Name[ga]=Cumraigh an Painéal
+Name[gl]=Configurar o Painel
+Name[he]=הגדר את הלוח
+Name[hi]=फलक कॉन्फ़िगर करें
+Name[hr]=Konfiguriranje ploče
+Name[hu]=A panel beállítása
+Name[is]=Stilla spjaldið
+Name[it]=Configura il pannello
+Name[ja]=パネルの設定
+Name[ka]=პანელის კონფიგურირება
+Name[kk]=Панельді баптау
+Name[km]=កំណត់​រចនាសម្ព័ន្ធ​បន្ទះ
+Name[ko]=패널 작업 표시줄 설정
+Name[lt]=Konfigūruoti pultą
+Name[lv]=Konfigurēt paneli
+Name[mk]=Конфигурација на панелот
+Name[mn]=Удирдах самбар тохируулах
+Name[ms]=Konfigur Panel
+Name[mt]=Ikkonfigura l-pannell
+Name[nb]=Tilpass panelet
+Name[nds]=Dat Paneel instellen
+Name[ne]=प्यानल कन्फिगर गर्नुहोस्
+Name[nl]=Paneel instellen
+Name[nn]=Set opp panelet
+Name[pa]=ਪੈਨਲ ਸੰਰਚਨਾ
+Name[pl]=Konfiguracja panelu
+Name[pt]=Configurar o Painel
+Name[pt_BR]=Configurar o Painel
+Name[ro]=Configurează panoul
+Name[ru]=Настройка панели
+Name[rw]=Kuboneza Umwanya
+Name[se]=Heivet panela
+Name[sk]=Nastaviť panel
+Name[sl]=Nastavi pult
+Name[sr]=Подешавање панела
+Name[sr@Latn]=Podešavanje panela
+Name[sv]=Anpassa panelen
+Name[ta]=பலகத்தை வடிவமை
+Name[tg]=Танзими сафҳа
+Name[th]=ปรับแต่งพาเนล
+Name[tr]=Paneli Yapılandır
+Name[tt]=Taqtanı Caylaw
+Name[uk]=Налаштування панелі
+Name[uz]=Panelni moslash
+Name[uz@cyrillic]=Панелни мослаш
+Name[vi]=Cấu hình Bảng điều khiển
+Name[wa]=Apontyî li scriftôr
+Name[zh_CN]=配置面板
+Name[zh_TW]=設定面板
+X-KDE-StartupNotify=true
+OnlyShowIn=KDE;
+Categories=Qt;KDE;Settings;
diff --git a/kicker/kicker/kicker-3.1-properSizeSetting.pl b/kicker/kicker/kicker-3.1-properSizeSetting.pl
new file mode 100644
index 000000000..1fba4eaeb
--- /dev/null
+++ b/kicker/kicker/kicker-3.1-properSizeSetting.pl
@@ -0,0 +1,34 @@
+#!/usr/bin/perl
+
+while (<>)
+{
+ ($key, $sizeSetting) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/);
+ if ($key eq "Size")
+ {
+ print "[General]\n";
+
+ if ($sizeSetting == '24')
+ {
+ print "Size=0\n";
+ }
+ elsif ($sizeSetting == '30')
+ {
+ print "Size=1\n";
+ }
+ elsif ($sizeSetting == '46')
+ {
+ print "Size=2\n";
+ }
+ elsif ($sizeSetting == '58')
+ {
+ print "Size=3\n";
+ }
+ elsif ($sizeSetting > 10)
+ {
+ print "Size=4\n";
+ print "CustomSize=" . $sizeSetting . "\n";
+ }
+ exit(0);
+ }
+}
+
diff --git a/kicker/kicker/kicker-3.4-reverseLayout.cpp b/kicker/kicker/kicker-3.4-reverseLayout.cpp
new file mode 100644
index 000000000..bfcea5629
--- /dev/null
+++ b/kicker/kicker/kicker-3.4-reverseLayout.cpp
@@ -0,0 +1,152 @@
+#include <qfile.h>
+#include <qmap.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qtextstream.h>
+
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <ktempfile.h>
+
+struct AppletInfo
+{
+ double freeSpace;
+ QString configFile;
+ QString desktopFile;
+};
+typedef QMap<QString, AppletInfo> AppletInfoMap;
+
+int main(int argc, char** argv)
+{
+ // We must disguise as Kicker in order to obtain the correct reverseLayout setting.
+ KCmdLineArgs::init(argc, argv, "kicker", "", "", "", false);
+ KApplication app(false, false);
+
+ QStringList stretchableApplets;
+ stretchableApplets << "taskbarapplet.desktop";
+
+ QTextStream in (stdin, IO_ReadOnly);
+ QTextStream out(stdout, IO_WriteOnly);
+
+ QStringList appletIds;
+ AppletInfoMap applets;
+
+ QRegExp rxGroup("^\\[(.+)\\]$");
+ QRegExp rxKeyValue("([^=]+)=[ \t]*([^\n]+)");
+ QString currentGroup;
+
+ QString line;
+ while (!(line = in.readLine()).isNull())
+ {
+ if (rxGroup.search(line) != -1)
+ {
+ currentGroup = rxGroup.cap(1);
+ continue;
+ }
+
+ if (rxKeyValue.search(line) != -1)
+ {
+ QString key = rxKeyValue.cap(1);
+ QString value = rxKeyValue.cap(2);
+
+ if (key == "Applets")
+ {
+ appletIds = QStringList::split(",", value);
+ }
+ else if (key == "FreeSpace")
+ {
+ applets[currentGroup].freeSpace = value.toDouble();
+ }
+ else if (key == "ConfigFile")
+ {
+ applets[currentGroup].configFile = value;
+ }
+ else if (key == "DesktopFile")
+ {
+ applets[currentGroup].desktopFile = value;
+ }
+ }
+ }
+
+ if (QApplication::reverseLayout())
+ {
+ // Reverse appletIds
+ QStringList appletIdsRev;
+ QStringList::ConstIterator it;
+ for (it = appletIds.begin(); it != appletIds.end(); ++it)
+ {
+ appletIdsRev.prepend(*it);
+ }
+ appletIds = appletIdsRev;
+
+ // Adjust the FreeSpace values
+ for (it = appletIds.begin(); it != appletIds.end(); ++it)
+ {
+ applets[*it].freeSpace = 1 - applets[*it].freeSpace;
+
+ // Take care of stretchable applets.
+ if (stretchableApplets.contains(applets[*it].desktopFile))
+ {
+ if (it != appletIds.begin())
+ {
+ applets[*it].freeSpace = applets[*(--it)].freeSpace;
+ ++it;
+ }
+ else
+ {
+ applets[*it].freeSpace = 0;
+ }
+ }
+ }
+ }
+
+ // Write the changed entries to stdout.
+ if (!appletIds.empty())
+ {
+ out << "[General]" << endl;
+ out << "Applets2=" << appletIds.join(",") << endl;
+ QStringList::ConstIterator it;
+ for (it = appletIds.begin(); it != appletIds.end(); ++it)
+ {
+ out << "[" << *it << "]" << endl;
+ out << "FreeSpace2=" << applets[*it].freeSpace << endl;
+ }
+ }
+
+ // Build a list of childpanel config files.
+ QStringList childPanelConfigFiles;
+ AppletInfoMap::ConstIterator it2;
+ QStringList::ConstIterator it;
+ for (it2 = applets.begin(); it2 != applets.end(); ++it2)
+ {
+ if (it2.data().desktopFile == "childpanelextension.desktop")
+ {
+ childPanelConfigFiles << it2.data().configFile;
+ }
+ }
+
+ if (!childPanelConfigFiles.isEmpty())
+ {
+ // Create a temporary kconf_update .upd file for updating the childpanels
+ KTempFile tempFile(QString::null, ".upd");
+ QTextStream* upd = tempFile.textStream();
+ for (it = childPanelConfigFiles.begin(); it != childPanelConfigFiles.end(); ++it)
+ {
+ *upd << "Id=kde_3.4_reverseLayout" << endl;
+ *upd << "File=" << *it << endl;
+ *upd << "Script=kicker-3.4-reverseLayout" << endl;
+ *upd << endl;
+ }
+ tempFile.close();
+
+ // Run kconf_update on the childpanel config files.
+ KProcess kconf_update;
+ kconf_update << "kconf_update" << tempFile.name();
+ kconf_update.start(KProcess::Block);
+
+ tempFile.unlink();
+ }
+}
diff --git a/kicker/kicker/kicker-3.5-kconfigXTize.pl b/kicker/kicker/kicker-3.5-kconfigXTize.pl
new file mode 100755
index 000000000..e836116d7
--- /dev/null
+++ b/kicker/kicker/kicker-3.5-kconfigXTize.pl
@@ -0,0 +1,37 @@
+#!/usr/bin/perl
+
+$detailed = 1;
+$namesfirst = 1;
+
+while (<>)
+{
+ ($key, $value) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/);
+ if ($key eq "DetailedMenuEntries")
+ {
+ if ($value eq "false")
+ {
+ $detailed = 0;
+ }
+ }
+ elsif ($key eq "DetailedEntriesNamesFirst")
+ {
+ if ($value eq "false")
+ {
+ $namesfirst = 0;
+ }
+ }
+}
+
+if (not $detailed)
+{
+ print "MenuEntryFormat=NameOnly\n";
+}
+elsif ($namesfirst)
+{
+ print "MenuEntryFormat=NameAndDescription\n";
+}
+else
+{
+ print "MenuEntryFormat=DescriptionAndName\n";
+}
+
diff --git a/kicker/kicker/kicker-3.5-taskbarEnums.pl b/kicker/kicker/kicker-3.5-taskbarEnums.pl
new file mode 100755
index 000000000..1379e0c9d
--- /dev/null
+++ b/kicker/kicker/kicker-3.5-taskbarEnums.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+
+while (<>)
+{
+ ($key, $value) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/);
+ if ($key eq "GroupTasks")
+ {
+ if ($value eq "Never")
+ {
+ print "GroupTasks=GroupNever\n";
+ }
+ elsif ($value eq "When Taskbar Full")
+ {
+ print "GroupTasks=GroupWhenFull\n";
+ }
+ elsif ($value eq "Always")
+ {
+ print "GroupTasks=GroupAlways\n";
+ }
+ }
+ elsif ($key =~ /ButtonAction/)
+ {
+ if ($value eq "Show Task List")
+ {
+ print "$key=ShowTaskList\n";
+ }
+ elsif ($value eq "Show Operations Menu")
+ {
+ print "$key=ShowOperationsMenu\n";
+ }
+ elsif ($value eq "Activate, Raise or Minimize Task")
+ {
+ print "$key=ActivateRaiseOrMinimize\n";
+ }
+ elsif ($value eq "Activate Task")
+ {
+ print "$key=Activate\n";
+ }
+ elsif ($value eq "Raise Task")
+ {
+ print "$key=Raise\n";
+ }
+ elsif ($value eq "Lower Task")
+ {
+ print "$key=Lower\n";
+ }
+ elsif ($value eq "Minimize Task")
+ {
+ print "$key=Minimize\n";
+ }
+
+ }
+}
+
diff --git a/kicker/kicker/kickerrc.upd b/kicker/kicker/kickerrc.upd
new file mode 100644
index 000000000..282a52cb1
--- /dev/null
+++ b/kicker/kicker/kickerrc.upd
@@ -0,0 +1,22 @@
+Id=kde_3_1_sizeChanges
+File=kickerrc
+Group=General
+Options=overwrite
+Script=kicker-3.1-properSizeSetting.pl,perl
+
+Id=kde_3_4_reverseLayout
+File=kickerrc
+Script=kicker-3.4-reverseLayout
+
+Id=kde_3_5_taskbarEnums
+File=ktaskbarrc
+Group=General
+Options=overwrite
+Script=kicker-3.5-taskbarEnums.pl,perl
+
+Id=kde_3_5_kconfigXTize
+File=kickerrc
+Group=menus
+Script=kicker-3.5-kconfigXTize.pl,perl
+RemoveKey=DetailedEntriesNamesFirst
+RemoveKey=DetailedMenuEntries
diff --git a/kicker/kicker/panel.desktop b/kicker/kicker/panel.desktop
new file mode 100644
index 000000000..605610841
--- /dev/null
+++ b/kicker/kicker/panel.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Exec=kicker
+Name=KDE Panel
+Name[af]=KDE Paneel
+Name[ar]=لوحة KDE
+Name[az]=KDE Paneli
+Name[be]=Панэль KDE
+Name[bg]=Системен панел
+Name[bn]=কে.ডি.ই. প্যানেল
+Name[br]=Panell KDE
+Name[bs]=KDE panel
+Name[ca]=Plafó KDE
+Name[cs]=Panel KDE
+Name[cy]=Panel KDE
+Name[de]=KDE-Kontrollleiste
+Name[el]=Πίνακας KDE
+Name[eo]=Panelo
+Name[es]=Panel de KDE
+Name[et]=KDE paneel
+Name[eu]=KDE panela
+Name[fa]=تابلوی KDE
+Name[fi]=KDE-paneeli
+Name[fr]=Tableau de bord de KDE
+Name[fy]=KDE Paniel
+Name[ga]=Painéal KDE
+Name[gl]=Painel de KDE
+Name[he]=הלוח של KDE
+Name[hi]=केडीई फलक
+Name[hr]=KDE ploča
+Name[hu]=Panel
+Name[id]=Panel KDE
+Name[is]=KDE spjald
+Name[it]=Pannello di KDE
+Name[ja]=KDE パネル
+Name[ka]=KDE-ს პანელი
+Name[kk]=KDE панелі
+Name[km]=បន្ទះ KDE
+Name[ku]=Panela KDE'yê
+Name[lo]=ຖາດພາເນລຂອง KDE
+Name[lt]=KDE pultas
+Name[lv]=KDE Panelis
+Name[mk]=Панелот на KDE
+Name[mn]=КДЭ-Удирдлагын самбар
+Name[ms]=Panel KDE
+Name[mt]=Pannell KDE
+Name[nb]=KDE-Panel
+Name[nds]=KDE-Paneel
+Name[ne]=KDE प्यानल
+Name[nl]=KDE Paneel
+Name[nn]=KDE-panel
+Name[nso]=Panel ya KDE
+Name[pa]=KDE ਪੈਨਲ
+Name[pl]=Panel
+Name[pt]=Painel do KDE
+Name[pt_BR]=Painel do KDE
+Name[ro]=Panou KDE
+Name[ru]=Панель KDE
+Name[rw]=KDE Umwanya
+Name[se]=KDE-panela
+Name[sk]=KDE panel
+Name[sl]=Pult KDE
+Name[sr]=KDE панел
+Name[sr@Latn]=KDE panel
+Name[sv]=KDE-panel
+Name[ta]=KDE பலகம்
+Name[te]=కెడిఈ పెనల్
+Name[tg]=Сафҳаи KDE
+Name[th]=ถาดพาเนล KDE
+Name[tr]=KDE Paneli
+Name[tt]=KDE Üzäge
+Name[uk]=Панель KDE
+Name[uz]=KDE paneli
+Name[uz@cyrillic]=KDE панели
+Name[ven]=Phanele ya KDE
+Name[vi]=Bảng điều khiển KDE
+Name[wa]=Scriftôr KDE
+Name[xh]=Ipanel ye KDE
+Name[zh_CN]=KDE 面板
+Name[zh_TW]=KDE 面板
+Name[zu]=Iwindi lemininingwane le-KDE
+X-DCOP-ServiceType=wait
+X-KDE-autostart-after=kdesktop
+DocPath=kicker/index.html
+Type=Service
+OnlyShowIn=KDE;
+X-KDE-autostart-phase=0
diff --git a/kicker/kicker/ui/Makefile.am b/kicker/kicker/ui/Makefile.am
new file mode 100644
index 000000000..e60e99bfd
--- /dev/null
+++ b/kicker/kicker/ui/Makefile.am
@@ -0,0 +1,41 @@
+INCLUDES = -I$(srcdir)/../core -I../core -I$(srcdir)/../buttons \
+ -I../../libkicker -I$(srcdir)/../../libkicker \
+ -I$(top_srcdir)/libkonq -I$(top_srcdir)/kdmlib $(all_includes)
+
+noinst_LTLIBRARIES = libkicker_ui.la
+
+libkicker_ui_la_SOURCES = addbutton_mnu.cpp appletitem.ui appletview.ui addapplet.cpp \
+ addapplet_mnu.cpp appletop_mnu.cpp \
+ browser_mnu.cpp client_mnu.cpp dirdrop_mnu.cpp \
+ nonKDEButtonSettings.ui exe_dlg.cpp k_mnu.cpp k_mnu.skel\
+ quickbrowser_mnu.cpp service_mnu.cpp \
+ addextension_mnu.cpp extensionop_mnu.cpp \
+ recentapps.cpp browser_dlg.cpp \
+ removeapplet_mnu.cpp removeextension_mnu.cpp removecontainer_mnu.cpp \
+ removebutton_mnu.cpp popupmenutitle.cpp hidebutton.cpp \
+ addappletvisualfeedback.cpp
+
+libkicker_ui_la_LIBADD = $(top_builddir)/libkonq/libkonq.la $(top_builddir)/kdmlib/libdmctl.la
+
+libkicker_ui_la_METASOURCES = AUTO
+
+noinst_HEADERS = addapplet.h appletwidget.h addbutton_mnu.h addapplet_mnu.h appletop_mnu.h \
+ browser_mnu.h client_mnu.h dirdrop_mnu.h exe_dlg.h k_mnu.h \
+ quickbrowser_mnu.h service_mnu.h \
+ addextension_mnu.h extensionop_mnu.h \
+ recentapps.h browser_dlg.h \
+ removeapplet_mnu.h removeextension_mnu.h removecontainer_mnu.h \
+ removebutton_mnu.h popupmenutitle.h hidebutton.h addappletvisualfeedback.h
+
+removecontainer_mnu.lo: ../../libkicker/kickerSettings.h
+removeextension_mnu.lo: ../../libkicker/kickerSettings.h
+addextension_mnu.lo: ../core/extensionSettings.h
+appletop_mnu.lo: ../../libkicker/kickerSettings.h
+extensionop_mnu.lo: ../../libkicker/kickerSettings.h
+k_mnu.lo: ../../libkicker/kickerSettings.h
+removecontainer_mnu.lo: ../core/extensionSettings.h
+removeextension_mnu.lo: ../core/extensionSettings.h
+service_mnu.lo: ../../libkicker/kickerSettings.h
+browser_mnu.lo: ../../libkicker/kickerSettings.h
+recentapps.lo: ../../libkicker/kickerSettings.h
+
diff --git a/kicker/kicker/ui/addapplet.cpp b/kicker/kicker/ui/addapplet.cpp
new file mode 100644
index 000000000..e7ac47c9c
--- /dev/null
+++ b/kicker/kicker/ui/addapplet.cpp
@@ -0,0 +1,542 @@
+/*****************************************************************
+
+Copyright (c) 2005 Marc Cramdal
+Copyright (c) 2005 Aaron Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qapplication.h>
+#include <qcombobox.h>
+#include <qdir.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpalette.h>
+#include <qscrollview.h>
+#include <qtimer.h>
+#include <qsizepolicy.h>
+
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+#include <kstdguiitem.h>
+
+#include <paneldrag.h>
+
+#include "addapplet.h"
+#include "addappletvisualfeedback.h"
+#include "appletwidget.h"
+#include "appletview.h"
+#include "container_applet.h"
+#include "container_extension.h"
+#include "containerarea.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "menuinfo.h"
+#include "pluginmanager.h"
+
+AppletWidget::AppletWidget(const AppletInfo& info, bool odd, QWidget *parent)
+ : AppletItem(parent),
+ m_appletInfo(info),
+ m_odd(odd),
+ m_selected(false)
+{
+ setFocusPolicy(QWidget::StrongFocus);
+ setSelected(m_selected);
+
+ itemTitle->setText("<h3>" + info.name() + "</h3>");
+ itemTitle->installEventFilter(this);
+
+ if (info.comment() != info.name())
+ {
+ itemDescription->setText(info.comment());
+ }
+
+ itemDescription->installEventFilter(this);
+
+ KIconLoader * ldr = KGlobal::iconLoader();
+ QPixmap icon = ldr->loadIcon(info.icon(), KIcon::Panel, KIcon::SizeLarge);
+ itemPixmap->setPixmap(icon);
+ itemPixmap->installEventFilter(this);
+}
+
+bool AppletWidget::eventFilter(QObject*, QEvent* e)
+{
+ if (e->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ if (me->button() & LeftButton)
+ {
+ m_dragStart = me->pos();
+ }
+ }
+ else if (m_dragStart.isNull())
+ {
+ return false;
+ }
+
+ if (e->type() == QEvent::MouseMove)
+ {
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ if ((me->pos() - m_dragStart).manhattanLength() >
+ KGlobalSettings::dndEventDelay())
+ {
+ AppletInfoDrag* drag = new AppletInfoDrag(m_appletInfo, this);
+
+ if (itemPixmap->pixmap())
+ {
+ drag->setPixmap(*itemPixmap->pixmap());
+ }
+
+ drag->dragCopy();
+
+ return true;
+ }
+ }
+ else if (e->type() == QEvent::MouseButtonRelease)
+ {
+ m_dragStart = QPoint();
+ }
+
+ return false;
+}
+
+void AppletWidget::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Enter ||
+ e->key() == Qt::Key_Return)
+ {
+ emit doubleClicked(this);
+ }
+ else if (e->key() == Qt::Key_Up)
+ {
+ QKeyEvent fakedKeyPress(QEvent::KeyPress, Qt::Key_BackTab, 0, 0);
+ QKeyEvent fakedKeyRelease(QEvent::KeyRelease, Key_BackTab, 0, 0);
+ QApplication::sendEvent(this, &fakedKeyPress);
+ QApplication::sendEvent(this, &fakedKeyRelease);
+ }
+ else if (e->key() == Qt::Key_Down)
+ {
+ QKeyEvent fakedKeyPress(QEvent::KeyPress, Qt::Key_Tab, 0, 0);
+ QKeyEvent fakedKeyRelease(QEvent::KeyRelease, Key_Escape, 0, 0);
+ QApplication::sendEvent(this, &fakedKeyPress);
+ QApplication::sendEvent(this, &fakedKeyRelease);
+ }
+ else
+ {
+ AppletItem::keyPressEvent(e);
+ }
+}
+
+void AppletWidget::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == QMouseEvent::LeftButton)
+ {
+ emit clicked(this);
+ m_dragStart = e->pos();
+ }
+
+ setFocus();
+ QWidget::mousePressEvent(e);
+}
+
+void AppletWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ if (e->button() == QMouseEvent::LeftButton &&
+ !m_dragStart.isNull() &&
+ (e->pos() - m_dragStart).manhattanLength() >
+ KGlobalSettings::dndEventDelay())
+ {
+ AppletInfoDrag* drag = new AppletInfoDrag(m_appletInfo, this);
+
+ if (itemPixmap->pixmap())
+ {
+ drag->setPixmap(*itemPixmap->pixmap());
+ }
+
+ drag->dragCopy();
+ }
+}
+
+void AppletWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ m_dragStart = QPoint();
+ QWidget::mouseReleaseEvent(e);
+}
+
+void AppletWidget::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (!e->button() == QMouseEvent::LeftButton)
+ {
+ AppletItem::mouseDoubleClickEvent(e);
+ return;
+ }
+
+ emit doubleClicked(this);
+}
+
+void AppletWidget::setSelected(bool selected)
+{
+ m_selected = selected;
+
+ // for now just used to switch colours around =)
+ if (m_selected)
+ {
+ setPaletteBackgroundColor(KGlobalSettings::highlightColor());
+ setPaletteForegroundColor(KGlobalSettings::highlightedTextColor());
+ }
+ else if (m_odd)
+ {
+ setPaletteBackgroundColor(KGlobalSettings::baseColor());
+ setPaletteForegroundColor(KGlobalSettings::textColor());
+ }
+ else
+ {
+ setPaletteBackgroundColor(KGlobalSettings::alternateBackgroundColor());
+ setPaletteForegroundColor(KGlobalSettings::textColor());
+ }
+}
+
+void AppletWidget::setOdd(bool odd)
+{
+ m_odd = odd;
+ setSelected(m_selected);
+}
+
+void AppletWidget::focusInEvent(QFocusEvent*)
+{
+ emit clicked(this);
+}
+
+AddAppletDialog::AddAppletDialog(ContainerArea* cArea,
+ QWidget* parent,
+ const char* name)
+ : KDialogBase(parent, name, false, i18n("Add Applet"), 0),
+ m_selectedApplet(0),
+ m_containerArea(cArea),
+ m_insertionPoint(Kicker::the()->insertionPoint()),
+ m_closing(false),
+ m_searchDelay(new QTimer(this))
+{
+ m_mainWidget = new AppletView(this, "AddAppletDialog::m_mainWidget");
+ m_mainWidget->appletScrollView->setResizePolicy(QScrollView::Manual);
+ m_mainWidget->appletScrollView->setHScrollBarMode(QScrollView::AlwaysOff);
+ m_mainWidget->appletScrollView->viewport()->setPaletteBackgroundColor(KGlobalSettings::baseColor());
+
+ setMainWidget(m_mainWidget);
+
+ resize(configDialogSize("AddAppletDialog Settings"));
+ centerOnScreen(this);
+
+ KGuiItem addGuiItem = KStdGuiItem::add();
+ addGuiItem.setText(m_mainWidget->appletInstall->text());
+ m_mainWidget->appletInstall->setEnabled(false);
+ m_mainWidget->appletInstall->setGuiItem(addGuiItem);
+ m_mainWidget->closeButton->setGuiItem(KStdGuiItem::close());
+
+ connect(m_mainWidget->appletSearch, SIGNAL(textChanged(const QString&)), this, SLOT(delayedSearch()));
+ connect(m_searchDelay, SIGNAL(timeout()), this, SLOT(search()));
+ connect(m_mainWidget->appletFilter, SIGNAL(activated(int)), this, SLOT(filter(int)));
+ connect(m_mainWidget->appletInstall, SIGNAL(clicked()), this, SLOT(addCurrentApplet()));
+ connect(m_mainWidget->closeButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ m_selectedType = AppletInfo::Undefined;
+ m_appletBox = 0;
+
+ QTimer::singleShot(0, this, SLOT(populateApplets()));
+}
+
+void AddAppletDialog::updateInsertionPoint()
+{
+ m_insertionPoint = Kicker::the()->insertionPoint();
+}
+
+
+void AddAppletDialog::closeEvent(QCloseEvent* e)
+{
+ m_closing = true;
+ saveDialogSize("AddAppletDialog Settings");
+ KDialogBase::closeEvent(e);
+}
+
+void AddAppletDialog::resizeAppletView()
+{
+ int w, h;
+ QScrollView *v = m_mainWidget->appletScrollView;
+
+ if (m_closing)
+ return;
+
+ for (int i = 0; i < 3; i++)
+ {
+ m_appletBox->layout()->activate();
+ w = v->visibleWidth();
+ h = m_appletBox->layout()->minimumSize().height();
+ v->resizeContents(w, QMAX(h, v->visibleHeight()));
+ if (w == m_appletBox->width() && h == m_appletBox->height())
+ break;
+ m_appletBox->resize(w, h);
+ v->updateScrollBars();
+ }
+}
+
+bool AddAppletDialog::eventFilter(QObject *o, QEvent *e)
+{
+ if (e->type() == QEvent::Resize)
+ QTimer::singleShot(0, this, SLOT(resizeAppletView()));
+
+ return QObject::eventFilter(o, e);
+}
+
+void AddAppletDialog::populateApplets()
+{
+ m_appletBox = new QWidget(m_mainWidget->appletScrollView->viewport());
+ m_appletBox->setPaletteBackgroundColor(KGlobalSettings::baseColor());
+ m_mainWidget->appletScrollView->addChild(m_appletBox, 0, 0);
+ m_appletBox->show();
+ QVBoxLayout* layout = new QVBoxLayout(m_appletBox);
+ layout->setMargin(0);
+
+ m_mainWidget->appletScrollView->installEventFilter(this);
+
+ /* Three steps
+ * - First we load the applets
+ * - We load the special buttons
+ * - Then we begin to populate the scrollview with the AppletWidget(s)
+ */
+ AppletInfo::List appletInfoList;
+
+ // Loading applets
+ appletInfoList = PluginManager::applets(false, &appletInfoList);
+
+ // Loading built in buttons
+ appletInfoList = PluginManager::builtinButtons(false, &appletInfoList);
+
+ // Loading special buttons
+ appletInfoList = PluginManager::specialButtons(false, &appletInfoList);
+
+ qHeapSort(appletInfoList);
+
+ int i = 0;
+ bool odd = true;
+ QWidget* prevTabWidget = m_mainWidget->appletFilter;
+
+ for (AppletInfo::List::iterator it = appletInfoList.begin();
+ !m_closing && it != appletInfoList.end();
+ ++i)
+ {
+ if ((*it).isHidden() || (*it).name().isEmpty() ||
+ ((*it).isUniqueApplet() &&
+ PluginManager::the()->hasInstance(*it)))
+ {
+ it = appletInfoList.erase(it);
+ --i;
+ continue;
+ }
+
+ AppletWidget *itemWidget = new AppletWidget(*it, odd, m_appletBox);
+
+ if (m_mainWidget->appletSearch->text().isEmpty() ||
+ appletMatchesSearch(itemWidget, m_mainWidget->appletSearch->text()))
+ {
+ itemWidget->show();
+ odd = !odd;
+ }
+ else
+ {
+ itemWidget->hide();
+ }
+
+ layout->insertWidget(i, itemWidget);
+ m_appletWidgetList.append(itemWidget);
+ setTabOrder(prevTabWidget, itemWidget);
+ prevTabWidget = itemWidget;
+
+ connect(itemWidget, SIGNAL(clicked(AppletWidget*)),
+ this, SLOT(selectApplet(AppletWidget*)));
+ connect(itemWidget, SIGNAL(doubleClicked(AppletWidget*)),
+ this, SLOT(addApplet(AppletWidget*)));
+
+ if (m_closing)
+ {
+ return;
+ }
+
+ ++it;
+ }
+
+ resizeAppletView();
+
+ m_mainWidget->closeButton->setEnabled(true);
+}
+
+void AddAppletDialog::selectApplet(AppletWidget *applet)
+{
+ m_mainWidget->appletInstall->setEnabled(true);
+
+ if (m_selectedApplet)
+ {
+ m_selectedApplet->setSelected(false);
+ }
+
+ m_selectedApplet = applet;
+
+ if (m_selectedApplet)
+ {
+ m_selectedApplet->setSelected(true);
+ }
+}
+
+void AddAppletDialog::addCurrentApplet()
+{
+ addApplet(m_selectedApplet);
+}
+
+void AddAppletDialog::addApplet(AppletWidget* applet)
+{
+ if (!applet)
+ {
+ return;
+ }
+
+ QPoint prevInsertionPoint = Kicker::the()->insertionPoint();
+ Kicker::the()->setInsertionPoint(m_insertionPoint);
+
+ const QWidget* appletContainer = 0;
+
+ if (applet->info().type() == AppletInfo::Applet)
+ {
+ appletContainer = m_containerArea->addApplet(applet->info());
+
+ if (applet->info().isUniqueApplet() &&
+ PluginManager::the()->hasInstance(applet->info()))
+ {
+ applet->hide();
+
+ // reset the odd/even colouring from this item on down in the list
+ bool odd = applet->odd();
+ AppletWidget::List::const_iterator it = m_appletWidgetList.find(applet);
+ for (; it != m_appletWidgetList.constEnd(); ++it)
+ {
+ if ((*it)->isHidden())
+ {
+ continue;
+ }
+
+ (*it)->setOdd(odd);
+ odd = !odd;
+ }
+ }
+ }
+ else if (applet->info().type() & AppletInfo::Button)
+ {
+ appletContainer = m_containerArea->addButton(applet->info());
+ }
+
+ if (appletContainer)
+ {
+ ExtensionContainer* ec =
+ dynamic_cast<ExtensionContainer*>(m_containerArea->topLevelWidget());
+
+ if (ec)
+ {
+ // unhide the panel and keep it unhidden for at least the time the
+ // helper tip will be there
+ ec->unhideIfHidden(KickerSettings::mouseOversSpeed() + 2500);
+ }
+
+ new AddAppletVisualFeedback(applet, appletContainer,
+ m_containerArea->popupDirection());
+ }
+
+ Kicker::the()->setInsertionPoint(prevInsertionPoint);
+}
+
+bool AddAppletDialog::appletMatchesSearch(const AppletWidget* w,
+ const QString& s)
+{
+ if (w->info().type() == AppletInfo::Applet &&
+ w->info().isUniqueApplet() &&
+ PluginManager::the()->hasInstance(w->info()))
+ {
+ return false;
+ }
+
+ return (m_selectedType == AppletInfo::Undefined ||
+ w->info().type() & m_selectedType) &&
+ (w->info().name().contains(s, false) ||
+ w->info().comment().contains(s, false));
+}
+
+void AddAppletDialog::delayedSearch()
+{
+ if (!m_searchDelay->isActive())
+ {
+ m_searchDelay->start(300, true);
+ }
+}
+
+void AddAppletDialog::search()
+{
+ QString s = m_mainWidget->appletSearch->text();
+ bool odd = true;
+ AppletWidget::List::const_iterator it = m_appletWidgetList.constBegin();
+ AppletWidget::List::const_iterator itEnd = m_appletWidgetList.constEnd();
+
+ for (; it != itEnd; ++it)
+ {
+ AppletWidget* w = *it;
+ if (appletMatchesSearch(w, s))
+ {
+ w->setOdd(odd);
+ w->show();
+ odd = !odd;
+ }
+ else
+ {
+ w->hide();
+ }
+ }
+
+ QTimer::singleShot(0, this, SLOT(resizeAppletView()));
+}
+
+void AddAppletDialog::filter(int i)
+{
+ m_selectedType = AppletInfo::Undefined;
+
+ if (i == 1)
+ {
+ m_selectedType = AppletInfo::Applet;
+ }
+ else if (i == 2)
+ {
+ m_selectedType = AppletInfo::Button;
+ }
+
+ search();
+}
+
+#include "addapplet.moc"
+#include "appletwidget.moc"
+
diff --git a/kicker/kicker/ui/addapplet.h b/kicker/kicker/ui/addapplet.h
new file mode 100644
index 000000000..d2ce50a00
--- /dev/null
+++ b/kicker/kicker/ui/addapplet.h
@@ -0,0 +1,82 @@
+/*****************************************************************
+
+Copyright (c) 2005 Marc Cramdal
+Copyright (c) 2005 Aaron Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __addapplet_h__
+#define __addapplet_h__
+
+#include <qstringlist.h>
+#include <qpixmap.h>
+#include <qvaluelist.h>
+
+#include <klocale.h>
+#include <kdialogbase.h>
+
+#include "appletinfo.h"
+
+class ContainerArea;
+class AppletView;
+class AppletWidget;
+class QTimer;
+
+class AddAppletDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ AddAppletDialog(ContainerArea* cArea, QWidget* parent, const char* name);
+ void updateInsertionPoint();
+
+ protected:
+ void closeEvent(QCloseEvent*);
+ bool eventFilter(QObject *o, QEvent *e);
+
+ private slots:
+ void populateApplets();
+ void addCurrentApplet();
+ void addApplet(AppletWidget* applet);
+ void delayedSearch();
+ void search();
+ void filter(int i);
+ void selectApplet(AppletWidget* applet);
+ void resizeAppletView();
+
+ private:
+ bool appletMatchesSearch(const AppletWidget* w, const QString& s);
+
+ AppletView *m_mainWidget;
+ QWidget *m_appletBox;
+
+ AppletInfo::List m_applets;
+
+ QValueList<AppletWidget*> m_appletWidgetList;
+ AppletWidget* m_selectedApplet;
+
+ ContainerArea* m_containerArea;
+ AppletInfo::AppletType m_selectedType;
+ QPoint m_insertionPoint;
+ bool m_closing;
+ QTimer *m_searchDelay;
+};
+
+#endif
diff --git a/kicker/kicker/ui/addapplet_mnu.cpp b/kicker/kicker/ui/addapplet_mnu.cpp
new file mode 100644
index 000000000..3c3a3db87
--- /dev/null
+++ b/kicker/kicker/ui/addapplet_mnu.cpp
@@ -0,0 +1,75 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <kiconloader.h>
+
+#include "pluginmanager.h"
+#include "containerarea.h"
+
+#include "addapplet_mnu.h"
+#include "addapplet_mnu.moc"
+
+PanelAddAppletMenu::PanelAddAppletMenu(ContainerArea* cArea, QWidget *parent, const char *name)
+ : QPopupMenu(parent, name), containerArea(cArea)
+{
+ setCheckable(true);
+ connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
+ connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
+}
+
+void PanelAddAppletMenu::slotAboutToShow()
+{
+ clear();
+
+ applets = PluginManager::applets();
+
+ AppletInfo::List::const_iterator it = applets.constBegin();
+ for (int i = 0; it != applets.constEnd(); ++it, ++i)
+ {
+ const AppletInfo& ai = (*it);
+ if (ai.isHidden())
+ {
+ continue;
+ }
+
+ if (ai.icon().isEmpty() || ai.icon() == "unknown")
+ {
+ insertItem(ai.name().replace( "&", "&&" ), i);
+ }
+ else
+ {
+ insertItem(SmallIconSet(ai.icon()), ai.name().replace( "&", "&&" ), i);
+ }
+
+ if (ai.isUniqueApplet() && PluginManager::the()->hasInstance(ai))
+ {
+ setItemEnabled( i, false );
+ setItemChecked( i, true );
+ }
+ }
+}
+
+void PanelAddAppletMenu::slotExec(int id)
+{
+ containerArea->addApplet( applets[id].desktopFile() );
+}
diff --git a/kicker/kicker/ui/addapplet_mnu.h b/kicker/kicker/ui/addapplet_mnu.h
new file mode 100644
index 000000000..260de26dd
--- /dev/null
+++ b/kicker/kicker/ui/addapplet_mnu.h
@@ -0,0 +1,50 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __addapplet_mnu_h__
+#define __addapplet_mnu_h__
+
+#include <qvaluelist.h>
+#include <qpopupmenu.h>
+
+#include "appletinfo.h"
+
+class ContainerArea;
+
+class PanelAddAppletMenu : public QPopupMenu
+{
+ Q_OBJECT
+
+public:
+ PanelAddAppletMenu(ContainerArea *cArea, QWidget *parent=0, const char *name=0);
+
+protected slots:
+ virtual void slotExec(int id);
+ virtual void slotAboutToShow();
+
+private:
+ AppletInfo::List applets;
+ ContainerArea* containerArea;
+};
+
+#endif
diff --git a/kicker/kicker/ui/addappletvisualfeedback.cpp b/kicker/kicker/ui/addappletvisualfeedback.cpp
new file mode 100644
index 000000000..ce6e618a7
--- /dev/null
+++ b/kicker/kicker/ui/addappletvisualfeedback.cpp
@@ -0,0 +1,230 @@
+/*****************************************************************
+
+Copyright (c) 2004-2005 Aaron J. Seigo <aseigo@kde.org>
+Copyright (c) 2004 Zack Rusin <zrusin@kde.org>
+ Sami Kyostil <skyostil@kempele.fi>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qpainter.h>
+#include <qsimplerichtext.h>
+#include <qtimer.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+
+#include "global.h"
+
+#include "appletinfo.h"
+#include "appletwidget.h"
+#include "addappletvisualfeedback.h"
+#include "kickerSettings.h"
+
+#define DEFAULT_FRAMES_PER_SECOND 30
+
+AddAppletVisualFeedback::AddAppletVisualFeedback(AppletWidget* widget,
+ const QWidget* target,
+ KPanelApplet::Direction direction)
+ : QWidget(0, "animtt", WX11BypassWM),
+ m_target(target),
+ m_direction(direction),
+ m_icon(*widget->itemPixmap->pixmap()),
+ m_richText(0),
+ m_dissolveDelta(-1),
+ m_frames(1),
+ m_dirty(false)
+{
+ setFocusPolicy(NoFocus);
+ setBackgroundMode(NoBackground);
+ connect(&m_moveTimer, SIGNAL(timeout()), SLOT(swoopCloser()));
+
+ QString m = "<qt><h3>" + i18n("%1 Added").arg(widget->info().name());
+
+ if (widget->info().name() != widget->info().comment())
+ {
+ m += "</h3><p>" + widget->info().comment() + "</p></qt>";
+ }
+
+ m_richText = new QSimpleRichText(m, font());
+ m_richText->setWidth(400);
+
+ displayInternal();
+
+ m_destination = KickerLib::popupPosition(m_direction, this, m_target);
+ QPoint startAt = widget->itemPixmap->geometry().topLeft();
+ startAt = widget->itemPixmap->mapToGlobal(startAt);
+ move(startAt);
+
+ m_frames = (m_destination - startAt).manhattanLength() / 20;
+ m_moveTimer.start(10);
+
+ show();
+}
+
+AddAppletVisualFeedback::~AddAppletVisualFeedback()
+{
+ delete m_richText;
+}
+
+void AddAppletVisualFeedback::paintEvent(QPaintEvent * e)
+{
+ if (m_dirty)
+ {
+ displayInternal();
+ m_dirty = false;
+ }
+
+ QPainter p(this);
+ p.drawPixmap(e->rect().topLeft(), m_pixmap, e->rect());
+}
+
+void AddAppletVisualFeedback::mousePressEvent(QMouseEvent *)
+{
+ m_moveTimer.stop();
+ hide();
+ deleteLater();
+}
+
+void AddAppletVisualFeedback::makeMask()
+{
+ QPainter maskPainter(&m_mask);
+
+ m_mask.fill(Qt::black);
+
+ maskPainter.setBrush(Qt::white);
+ maskPainter.setPen(Qt::white);
+ maskPainter.drawRoundRect(m_mask.rect(), 1600 / m_mask.rect().width(),
+ 1600 / m_mask.rect().height());
+ setMask(m_mask);
+}
+
+void AddAppletVisualFeedback::displayInternal()
+{
+ // determine text rectangle
+ QRect textRect(0, 0, 0, 0);
+
+ if (m_frames < 1)
+ {
+ textRect.setWidth(m_richText->widthUsed());
+ textRect.setHeight(m_richText->height());
+ textRect.moveBy(-textRect.left(), -textRect.top());
+ textRect.addCoords(0, 0, 2, 2);
+ }
+
+ int margin = KDialog::marginHint();
+ int height = QMAX(m_icon.height(), textRect.height()) + 2 * margin;
+ int textX = m_icon.isNull() ? margin : 2 + m_icon.width() + 2 * margin;
+ int width = textX;
+
+ if (m_frames < 1)
+ {
+ width += textRect.width() + margin;
+ }
+
+ // resize pixmap, mask and widget
+ m_mask.resize(width, height);
+ m_pixmap.resize(width, height);
+ resize(width, height);
+
+ if (m_frames < 1)
+ {
+ move(KickerLib::popupPosition(m_direction, this, m_target));
+ }
+
+ // create and set transparency mask
+ makeMask();
+
+ // draw background
+ QPainter bufferPainter(&m_pixmap);
+ bufferPainter.setPen(Qt::black);
+ bufferPainter.setBrush(colorGroup().background());
+ bufferPainter.drawRoundRect(0, 0, width, height,
+ 1600 / width, 1600 / height);
+
+ // draw icon if present
+ if (!m_icon.isNull())
+ {
+ bufferPainter.drawPixmap(margin,
+ margin,
+ m_icon, 0, 0,
+ m_icon.width(), m_icon.height());
+ }
+
+ if (m_frames < 1)
+ {
+ int textY = (height - textRect.height()) / 2;
+
+ // draw text shadow
+ QColorGroup cg = colorGroup();
+ cg.setColor(QColorGroup::Text, cg.background().dark(115));
+ int shadowOffset = QApplication::reverseLayout() ? -1 : 1;
+ m_richText->draw(&bufferPainter, 5 + textX + shadowOffset,
+ textY + 1, QRect(), cg);
+
+ // draw text
+ cg = colorGroup();
+ m_richText->draw(&bufferPainter, 5 + textX, textY, rect(), cg);
+ }
+}
+
+void AddAppletVisualFeedback::swoopCloser()
+{
+ if (m_destination.isNull() || m_frames == 0)
+ {
+ return;
+ }
+
+ QPoint loc = geometry().topLeft();
+ bool isLeft = m_destination.x() > loc.x();
+ if (loc.x() != m_destination.x())
+ {
+ int newX = loc.x() + ((m_destination.x() - loc.x()) / m_frames * 2);
+ if ((m_destination.x() > newX) != isLeft)
+ {
+ newX = m_destination.x();
+ }
+ loc.setX(newX);
+ }
+
+ if (loc.y() != m_destination.y())
+ {
+ loc.setY(loc.y() + ((m_destination.y() - loc.y()) / m_frames));
+ }
+
+ move(loc);
+ --m_frames;
+
+ if (m_frames < 1)
+ {
+ m_moveTimer.stop();
+ displayInternal();
+ QTimer::singleShot(2000, this, SLOT(deleteLater()));
+ }
+}
+
+void AddAppletVisualFeedback::internalUpdate()
+{
+ m_dirty = true;
+ repaint(false);
+}
+
+#include "addappletvisualfeedback.moc"
diff --git a/kicker/kicker/ui/addappletvisualfeedback.h b/kicker/kicker/ui/addappletvisualfeedback.h
new file mode 100644
index 000000000..084154704
--- /dev/null
+++ b/kicker/kicker/ui/addappletvisualfeedback.h
@@ -0,0 +1,80 @@
+/*****************************************************************
+
+Copyright (c) 2004-2005 Aaron J. Seigo <aseigo@kde.org>
+Copyright (c) 2004 Zack Rusin <zrusin@kde.org>
+ Sami Kyostil <skyostil@kempele.fi>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef ADDAPPLETVISUALFEEDBACK_H
+#define ADDAPPLETVISUALFEEDBACK_H
+
+#include <qbitmap.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include <kpanelapplet.h>
+
+class AppletItem;
+class QPaintEvent;
+class QSimpleRichText;
+class QTimer;
+
+class AddAppletVisualFeedback : QWidget
+{
+ Q_OBJECT
+
+ public:
+ AddAppletVisualFeedback(AppletWidget* parent,
+ const QWidget* destination,
+ KPanelApplet::Direction direction);
+ ~AddAppletVisualFeedback();
+
+ protected slots:
+ void internalUpdate();
+ void swoopCloser();
+
+ protected:
+ void paintEvent(QPaintEvent * e);
+ void mousePressEvent(QMouseEvent * e);
+
+ void makeMask();
+ void displayInternal();
+
+ private:
+ const QWidget* m_target;
+ KPanelApplet::Direction m_direction;
+ QBitmap m_mask;
+ QPixmap m_pixmap;
+ QPixmap m_icon;
+ QSimpleRichText* m_richText;
+
+ int m_dissolveSize;
+ int m_dissolveDelta;
+ int m_frames;
+
+ QTimer m_moveTimer;
+ bool m_dirty;
+
+ QPoint m_destination;
+};
+
+#endif
diff --git a/kicker/kicker/ui/addbutton_mnu.cpp b/kicker/kicker/ui/addbutton_mnu.cpp
new file mode 100644
index 000000000..65a60eea4
--- /dev/null
+++ b/kicker/kicker/ui/addbutton_mnu.cpp
@@ -0,0 +1,73 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qdragobject.h>
+
+#include <ksycocaentry.h>
+#include <kservice.h>
+#include <kservicegroup.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+
+#include "addbutton_mnu.h"
+#include "addbutton_mnu.moc"
+#include "containerarea.h"
+
+PanelAddButtonMenu::PanelAddButtonMenu(ContainerArea* cArea, const QString & label,
+ const QString & relPath, QWidget * parent, const char * name, const QString& _inlineHeader)
+ : PanelServiceMenu(label, relPath, parent, name, true, _inlineHeader), containerArea(cArea)
+{
+}
+
+PanelAddButtonMenu::PanelAddButtonMenu(ContainerArea* cArea, QWidget * parent, const char * name, const QString& _inlineHeader)
+ : PanelServiceMenu(QString::null, QString::null, parent, name, true, _inlineHeader), containerArea(cArea)
+{
+}
+
+void PanelAddButtonMenu::slotExec(int id)
+{
+ if (!entryMap_.contains(id))
+ return;
+
+ KSycocaEntry * e = entryMap_[id];
+
+ if (e->isType(KST_KServiceGroup)) {
+ KServiceGroup::Ptr g = static_cast<KServiceGroup *>(e);
+ containerArea->addServiceMenuButton(g->relPath());
+ } else if (e->isType(KST_KService)) {
+ KService::Ptr service = static_cast<KService *>(e);
+ containerArea->addServiceButton( service->desktopEntryPath() );
+ }
+}
+
+PanelServiceMenu * PanelAddButtonMenu::newSubMenu(const QString & label, const QString & relPath,
+ QWidget * parent, const char * name, const QString& _inlineHeader)
+{
+ return new PanelAddButtonMenu(containerArea, label, relPath, parent, name, _inlineHeader);
+}
+
+void PanelAddButtonMenu::addNonKDEApp()
+{
+ containerArea->addNonKDEAppButton();
+}
+
diff --git a/kicker/kicker/ui/addbutton_mnu.h b/kicker/kicker/ui/addbutton_mnu.h
new file mode 100644
index 000000000..8a9a7e348
--- /dev/null
+++ b/kicker/kicker/ui/addbutton_mnu.h
@@ -0,0 +1,51 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __addbutton_mnu_h__
+#define __addbutton_mnu_h__
+
+#include "service_mnu.h"
+
+class ContainerArea;
+
+class PanelAddButtonMenu : public PanelServiceMenu
+{
+ Q_OBJECT
+
+public:
+ PanelAddButtonMenu(ContainerArea* cArea, const QString & label, const QString & relPath,
+ QWidget * parent = 0, const char * name = 0,const QString& _inlineHeader= QString::null);
+ PanelAddButtonMenu(ContainerArea* cArea, QWidget * parent = 0, const char * name = 0, const QString& _inlineHeader= QString::null);
+
+protected slots:
+ virtual void slotExec(int id);
+ virtual void addNonKDEApp();
+
+protected:
+ virtual PanelServiceMenu * newSubMenu(const QString & label, const QString & relPath,
+ QWidget * parent, const char * name, const QString & _inlineHeader=QString::null);
+private:
+ ContainerArea *containerArea;
+};
+
+#endif
diff --git a/kicker/kicker/ui/addextension_mnu.cpp b/kicker/kicker/ui/addextension_mnu.cpp
new file mode 100644
index 000000000..4ca467f46
--- /dev/null
+++ b/kicker/kicker/ui/addextension_mnu.cpp
@@ -0,0 +1,58 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include "extensionmanager.h"
+#include "pluginmanager.h"
+
+#include "addextension_mnu.h"
+#include "addextension_mnu.moc"
+
+PanelAddExtensionMenu::PanelAddExtensionMenu(QWidget *parent, const char *name)
+ : QPopupMenu(parent, name)
+{
+ setCheckable(true);
+ connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
+ connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
+}
+
+void PanelAddExtensionMenu::slotAboutToShow()
+{
+ clear();
+
+ extensions = PluginManager::extensions();
+
+ AppletInfo::List::const_iterator it = extensions.constBegin();
+ for( int i = 0; it != extensions.constEnd(); ++it, ++i ) {
+ const AppletInfo& ai = (*it);
+ insertItem( ai.name().replace( "&", "&&" ), i );
+ if ( ai.isUniqueApplet() && PluginManager::the()->hasInstance(ai) ) {
+ setItemEnabled( i, false );
+ setItemChecked( i, true );
+ }
+ }
+}
+
+void PanelAddExtensionMenu::slotExec(int id)
+{
+ ExtensionManager::the()->addExtension( extensions[id].desktopFile() );
+}
diff --git a/kicker/kicker/ui/addextension_mnu.h b/kicker/kicker/ui/addextension_mnu.h
new file mode 100644
index 000000000..60db0c201
--- /dev/null
+++ b/kicker/kicker/ui/addextension_mnu.h
@@ -0,0 +1,47 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __addextension_mnu_h__
+#define __addextension_mnu_h__
+
+#include <qvaluelist.h>
+#include <qpopupmenu.h>
+
+#include "appletinfo.h"
+
+class PanelAddExtensionMenu : public QPopupMenu
+{
+ Q_OBJECT
+
+public:
+ PanelAddExtensionMenu(QWidget *parent=0, const char *name=0);
+
+protected slots:
+ virtual void slotExec(int id);
+ virtual void slotAboutToShow();
+
+private:
+ AppletInfo::List extensions;
+};
+
+#endif
diff --git a/kicker/kicker/ui/appletitem.ui b/kicker/kicker/ui/appletitem.ui
new file mode 100644
index 000000000..d9cc2d9b0
--- /dev/null
+++ b/kicker/kicker/ui/appletitem.ui
@@ -0,0 +1,129 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>AppletItem</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>AppletItem</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>506</width>
+ <height>80</height>
+ </rect>
+ </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>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>80</height>
+ </size>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>itemTitle</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>itemDescription</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>itemPixmap</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>64</width>
+ <height>64</height>
+ </size>
+ </property>
+ <property name="margin">
+ <number>4</number>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kicker/kicker/ui/appletop_mnu.cpp b/kicker/kicker/ui/appletop_mnu.cpp
new file mode 100644
index 000000000..435911bbe
--- /dev/null
+++ b/kicker/kicker/ui/appletop_mnu.cpp
@@ -0,0 +1,208 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpanelapplet.h>
+#include <kstdguiitem.h>
+
+#include "kicker.h"
+#include "appletop_mnu.h"
+#include "container_button.h"
+#include "containerarea.h"
+
+PanelAppletOpMenu::PanelAppletOpMenu(int actions, QPopupMenu *opMenu, const QPopupMenu* appletsMenu,
+ const QString & title, const QString &icon,
+ QWidget *parent, const char *name)
+ : QPopupMenu(parent, name)
+{
+ bool needSeparator = false;
+ bool isButton = (parent && parent->inherits("ButtonContainer"));
+ bool isMenu = false;
+ QString titleText = title;
+ titleText = titleText.replace('&', "&&");
+ if (isButton)
+ {
+ isMenu = static_cast<ButtonContainer*>(parent)->isAMenu();
+ }
+
+ if (!Kicker::the()->isImmutable())
+ {
+ QString text = isButton ? (isMenu ? i18n("&Move %1 Menu") :
+ i18n("&Move %1 Button")) :
+ i18n("&Move %1");
+ insertItem(SmallIcon("move"), text.arg(titleText), Move);
+
+ // we look for a container area to see if we can add containers
+ // this is part of the kiosk support in kicker, allowing
+ // one to block users from adding new containers
+ ContainerArea* area = 0;
+ QObject* findTheArea = parent ? parent->parent() : 0;
+ while (findTheArea)
+ {
+ area = dynamic_cast<ContainerArea*>(findTheArea);
+
+ if (area)
+ {
+ break;
+ }
+
+ findTheArea = findTheArea->parent();
+ }
+
+ if (!area || area->canAddContainers())
+ {
+ text = isButton ? (isMenu ? i18n("&Remove %1 Menu") :
+ i18n("&Remove %1 Button")) :
+ i18n("&Remove %1");
+ insertItem(SmallIcon("remove"), text.arg(titleText), Remove);
+ needSeparator = true;
+ }
+ }
+
+ if (actions & KPanelApplet::ReportBug)
+ {
+ if (needSeparator)
+ {
+ insertSeparator();
+ needSeparator = false;
+ }
+
+ insertItem(i18n("Report &Bug..."), ReportBug);
+ }
+
+ if (actions & KPanelApplet::About)
+ {
+ if (needSeparator)
+ {
+ insertSeparator();
+ }
+
+ QPixmap iconPix(kapp->iconLoader()->loadIcon(icon,
+ KIcon::Small, 0,
+ KIcon::DefaultState,
+ 0, true));
+ insertItem(iconPix, i18n("&About %1").arg( titleText ), About);
+ needSeparator = !(actions & KPanelApplet::Help);
+ }
+
+ if (actions & KPanelApplet::Help)
+ {
+ if (needSeparator)
+ {
+ insertSeparator();
+ }
+
+ insertItem(SmallIcon("help"), KStdGuiItem::help().text(), Help);
+ needSeparator = true;
+ }
+
+ if (!Kicker::the()->isImmutable() && (actions & KPanelApplet::Preferences))
+ {
+ if (isButton)
+ {
+ insertItem(SmallIcon("configure"),
+ i18n("&Configure %1 Button...").arg(titleText), Preferences);
+ }
+ else
+ {
+ insertItem(SmallIcon("configure"),
+ i18n("&Configure %1...").arg(titleText), Preferences);
+ }
+ needSeparator = true;
+ }
+
+ if (appletsMenu)
+ {
+ if (needSeparator)
+ {
+ insertSeparator();
+ needSeparator = false;
+ }
+
+ QString text = title.isEmpty() ? i18n("Applet Menu") :
+ i18n("%1 Menu").arg(titleText);
+
+ // the 2 const_cast's below prevents const_cast'ing in multiple places
+ // elsewhere in the kicker code base. it's ugly, but unavoidable
+ // unless either QPopupMenu one day allows inserting const
+ // QPopupMenu's or we uglify other bits of kicker's API,
+ // notably KPanelApplet::customMeu()
+ if (icon.isEmpty())
+ {
+ insertItem(text, const_cast<QPopupMenu*>(appletsMenu));
+ }
+ else
+ {
+ insertItem(SmallIcon(icon), text,
+ const_cast<QPopupMenu*>(appletsMenu));
+ }
+ }
+
+ if ((actions & PanelAppletOpMenu::KMenuEditor) && kapp->authorizeKAction("menuedit"))
+ {
+ if (needSeparator)
+ {
+ insertSeparator();
+ needSeparator = false;
+ }
+
+ insertItem(SmallIcon("kmenuedit"), i18n("&Menu Editor"), Preferences);
+ }
+
+ if ((actions & PanelAppletOpMenu::BookmarkEditor) &&
+ kapp->authorizeKAction("edit_bookmarks"))
+ {
+ if (needSeparator)
+ {
+ insertSeparator();
+ }
+ needSeparator = false;
+
+ // NOTE: keditbookmarks is from konqueror. seeing as this is in kdebase
+ // as well this should be ok?
+ insertItem(SmallIcon("keditbookmarks"),
+ i18n("&Edit Bookmarks"),
+ Preferences);
+ }
+
+ if (needSeparator)
+ {
+ insertSeparator();
+ }
+
+ insertItem(SmallIcon("panel"), i18n("Panel Menu"), opMenu);
+ adjustSize();
+}
+
+void PanelAppletOpMenu::keyPressEvent(QKeyEvent* e)
+{
+ if (e->key() == Qt::Key_Escape)
+ {
+ emit escapePressed();
+ }
+
+ QPopupMenu::keyPressEvent(e);
+}
+
+#include "appletop_mnu.moc"
diff --git a/kicker/kicker/ui/appletop_mnu.h b/kicker/kicker/ui/appletop_mnu.h
new file mode 100644
index 000000000..25f03ada6
--- /dev/null
+++ b/kicker/kicker/ui/appletop_mnu.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef PANEL_APPLET_OP_MENU_H
+#define PANEL_APPLET_OP_MENU_H
+
+#include <qpopupmenu.h>
+
+class AppletInfo;
+
+// The button operations menu (usually right click)
+class PanelAppletOpMenu : public QPopupMenu
+{
+Q_OBJECT
+
+public:
+ enum OpButton{Move = 9900, Remove = 9901, Help = 9902, About = 9903, Preferences = 9904, ReportBug = 9905 };
+
+ // Note: these entries have to be | and &-able with KPanelApplet::Actions!
+ // they also are treated just like KPanelApplet::Preferences on selection
+ // KDE4: look at merging them there? perhaps under a generic "Editor" option?
+ enum { KMenuEditor = 1048576, BookmarkEditor = 2097152 };
+ PanelAppletOpMenu(int actions, QPopupMenu *opMenu, const QPopupMenu* appletsMenu = 0,
+ const QString &title = 0, const QString &icon = 0,
+ QWidget *parent=0, const char *name=0);
+
+signals:
+ void escapePressed();
+
+protected:
+ void keyPressEvent(QKeyEvent* e);
+};
+
+
+#endif // PANEL_APPLET_OP_MENU_H
diff --git a/kicker/kicker/ui/appletview.ui b/kicker/kicker/ui/appletview.ui
new file mode 100644
index 000000000..a2fa1e91b
--- /dev/null
+++ b/kicker/kicker/ui/appletview.ui
@@ -0,0 +1,204 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>AppletView</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>AppletView</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>490</width>
+ <height>334</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel8</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Search:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>appletSearch</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>appletSearch</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>10</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Type here some text to filter on the applet names and comments&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>S&amp;how:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>appletFilter</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>All</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Applets</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Special Buttons</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>appletFilter</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select here the only applet category that you want to show&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QScrollView">
+ <property name="name">
+ <cstring>appletScrollView</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;This is the applet list. Select an applet and click on &lt;b&gt;Add to panel&lt;/b&gt; to add it&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>284</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>appletInstall</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Add to Panel</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>closeButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>QScrollView</class>
+ <header location="global">qscrollview.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="872">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032f49444154789cb5953148254718c77f1e5b7c030ab3e0c12e5ce00927f88a14af7d87c5590ac29d6013b0497b844008a9120e1248938354a6b1482131cde5a510b4f03081f07c8d4421c2063cd85708bbe0831938613ec8c0a5588dd1dc33452e5f33bb33c36f7ffbed7fd889fe7e9fcb7ad07df09ab750fdfdfec4c425787b6bfb757bae8df79e6a54e1bcc36008845b47e71dc549c1e06000f10a9e5c9a3effee39690ef92cb4a25e2c3b4804709844807035cfd57d7122f0ad65f0c25f0703d4a39af41d28473fa0af4a42548c81f007f85aa86a4510cc34cccc8288420405640ad2bbcadfeb2fb01b39021e7d5513a2c74c59ca43d8db510e0f6a24018d8a2496ecbeb0b892d29d0f08cdbc9d149ac7dc0057bea2831262853196fd5d6573dd43046b85fcbe2002d55019be54bef9a2a45ecd585e059106fe46639318403153427908bd0be8e2a38c874b90e70692806acade4ea0b7eee96d0cc9b2360b8f0d92e835e33b97172106400801b6b73c1a95c54719cbef439a2b9a54f833c3f68f8ec59594f73eb090089b1b153afa67e4ae1b270e5fa7144725d636a6228d853fcf59fbca511e7bdc193cf92467b0eb297f578a2220721d7ccdd82442553b48206f417a1714c5fb94b5cf2b8a638f58a13b9fc2a4a3ddb16854aa53d03806dcf4180481a8d8c98b8f7296b3f6a5a33c6ee2652785fc1ea4d2bcaf248246901bca377a0c661a482cc5505135ecbd088de9a490ddb30c8735cf9e5614872955a96854665a066e4f85a33d0bad96500f95bd9dc0f26a8a3b53ba0f53f20c9e3d85e1cb9a4f3facd0734f9659da1da8ea5b7a0c02a22cae081a95deba676fc7f1e4a39cce7ca0d5097cfc594e9659fca88608dd25cbccdcbfe6384014baf3509f66f436866c7e0d835d4ffb5d0b0954a5c38fb4e92d4af18b521c19ac8c39796ee42ecebe22c0f2aa90656d7adf5714c74a71346c7647b0d39685c7965f7f52aa738fc6947a34c6b83829284a41d2c6441258580a74e7738a22509d36d0bc65687760660e8a25033187c451fec69bc1838301ac0b69de444ad53779c32317bb2481f2d437b9dd6adae13d14874a558f3126c2e0e7cbc59be3b81abf7e67ecca7fac3bd0fca3fe17f0db86f7f7fb137f0208c29bb28f971c5b0000000049454e44ae426082</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>appletSearch</tabstop>
+ <tabstop>appletFilter</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>qscrollview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kicker/kicker/ui/appletwidget.h b/kicker/kicker/ui/appletwidget.h
new file mode 100644
index 000000000..77d05c2b3
--- /dev/null
+++ b/kicker/kicker/ui/appletwidget.h
@@ -0,0 +1,72 @@
+/*****************************************************************
+
+Copyright (c) 2005 Marc Cramdal
+Copyright (c) 2005 Aaron Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef _appletwidget_h_
+#define _appletwidget_h_
+
+#include <qpoint.h>
+#include <qvaluelist.h>
+
+#include <klocale.h>
+#include <kdialogbase.h>
+
+#include "appletinfo.h"
+#include "appletitem.h"
+
+class AppletWidget: public AppletItem
+{
+ Q_OBJECT
+
+ public:
+ typedef QValueList<AppletWidget*> List;
+
+ AppletWidget(const AppletInfo& info, bool odd, QWidget *parent);
+ const AppletInfo& info() const { return m_appletInfo; }
+ virtual bool eventFilter(QObject* watched, QEvent* e);
+
+ void setSelected(bool selected);
+ void setOdd(bool odd);
+ bool odd() { return m_odd; }
+
+ signals:
+ void clicked(AppletWidget*);
+ void doubleClicked(AppletWidget*);
+
+ protected:
+ void keyPressEvent(QKeyEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
+ void focusInEvent(QFocusEvent* e);
+
+ private:
+ AppletInfo m_appletInfo;
+ bool m_odd;
+ bool m_selected;
+ QPoint m_dragStart;
+};
+
+#endif
+
diff --git a/kicker/kicker/ui/browser_dlg.cpp b/kicker/kicker/ui/browser_dlg.cpp
new file mode 100644
index 000000000..1fd5d47f6
--- /dev/null
+++ b/kicker/kicker/ui/browser_dlg.cpp
@@ -0,0 +1,114 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qvbox.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kicondialog.h>
+#include <kfiledialog.h>
+#include <klineedit.h>
+#include <kmessagebox.h>
+
+#include "browser_dlg.h"
+#include "browser_dlg.moc"
+
+PanelBrowserDialog::PanelBrowserDialog( const QString& path, const QString &icon, QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Quick Browser Configuration" ), Ok|Cancel, Ok, true )
+{
+ setMinimumWidth( 300 );
+
+ QVBox *page = makeVBoxMainWidget();
+
+ QHBox *hbox2 = new QHBox( page );
+ hbox2->setSpacing( KDialog::spacingHint() );
+ QLabel *label1 = new QLabel( i18n( "Button icon:" ), hbox2 );
+
+ iconBtn = new KIconButton( hbox2 );
+ iconBtn->setFixedSize( 50, 50 );
+ iconBtn->setIconType( KIcon::Panel, KIcon::FileSystem );
+ label1->setBuddy( iconBtn );
+
+ QHBox *hbox1 = new QHBox( page );
+ hbox1->setSpacing( KDialog::spacingHint() );
+ QLabel *label2 = new QLabel( i18n ( "Path:" ), hbox1 );
+ pathInput = new KLineEdit( hbox1 );
+ connect( pathInput, SIGNAL( textChanged ( const QString & )), this, SLOT( slotPathChanged( const QString & )));
+
+ pathInput->setText( path );
+ pathInput->setFocus();
+ label2->setBuddy( pathInput );
+ browseBtn = new QPushButton( i18n( "&Browse..." ), hbox1 );
+ if ( icon.isEmpty() ) {
+ KURL u;
+ u.setPath( path );
+ iconBtn->setIcon( KMimeType::iconForURL( u ) );
+ }
+ else
+ iconBtn->setIcon( icon );
+
+ connect( browseBtn, SIGNAL( clicked() ), this, SLOT( browse() ) );
+}
+
+PanelBrowserDialog::~PanelBrowserDialog()
+{
+
+}
+
+void PanelBrowserDialog::slotPathChanged( const QString &_text )
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+void PanelBrowserDialog::browse()
+{
+ QString dir = KFileDialog::getExistingDirectory( pathInput->text(), 0, i18n( "Select Folder" ) );
+ if ( !dir.isEmpty() ) {
+ pathInput->setText( dir );
+ KURL u;
+ u.setPath( dir );
+ iconBtn->setIcon( KMimeType::iconForURL( u ) );
+ }
+}
+
+void PanelBrowserDialog::slotOk()
+{
+ QDir dir(path());
+ if( !dir.exists() ) {
+ KMessageBox::sorry( this, i18n("'%1' is not a valid folder.").arg(path()) );
+ return;
+ }
+ KDialogBase::slotOk();
+}
+
+const QString PanelBrowserDialog::icon()
+{
+ return iconBtn->icon();
+}
+
+QString PanelBrowserDialog::path()
+{
+ return pathInput->text();
+}
diff --git a/kicker/kicker/ui/browser_dlg.h b/kicker/kicker/ui/browser_dlg.h
new file mode 100644
index 000000000..dc675c11c
--- /dev/null
+++ b/kicker/kicker/ui/browser_dlg.h
@@ -0,0 +1,53 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __browser_dlg_h__
+#define __browser_dlg_h__
+
+#include <kdialogbase.h>
+
+class KIconButton;
+class KLineEdit;
+
+class PanelBrowserDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ PanelBrowserDialog( const QString &path = QString::null, const QString &icon = QString::null, QWidget *parent = 0, const char *name = 0 );
+ ~PanelBrowserDialog();
+
+ const QString icon();
+ QString path();
+
+protected slots:
+ void browse();
+ virtual void slotOk();
+ void slotPathChanged( const QString &_text );
+protected:
+ KIconButton *iconBtn;
+ KLineEdit *pathInput;
+ QPushButton *browseBtn;
+};
+
+#endif
diff --git a/kicker/kicker/ui/browser_mnu.cpp b/kicker/kicker/ui/browser_mnu.cpp
new file mode 100644
index 000000000..9561881eb
--- /dev/null
+++ b/kicker/kicker/ui/browser_mnu.cpp
@@ -0,0 +1,552 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qdir.h>
+#include <qpixmap.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kdirwatch.h>
+#include <kfileitem.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <kio/global.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <konq_operations.h>
+#include <kprocess.h>
+#include <krun.h>
+#include <ksimpleconfig.h>
+#include <kstringhandler.h>
+#include <kurldrag.h>
+
+#include "kickerSettings.h"
+
+#include "browser_mnu.h"
+#include "browser_mnu.moc"
+
+#define CICON(a) (*_icons)[a]
+
+QMap<QString, QPixmap> *PanelBrowserMenu::_icons = 0;
+
+PanelBrowserMenu::PanelBrowserMenu(QString path, QWidget *parent, const char *name, int startid)
+ : KPanelMenu(path, parent, name)
+ , _mimecheckTimer(0)
+ , _startid(startid)
+ , _dirty(false)
+ , _filesOnly(false)
+{
+ _lastpress = QPoint(-1, -1);
+ setAcceptDrops(true); // Should depend on permissions of path.
+
+ // we are not interested for dirty events on files inside the
+ // directory (see slotClearIfNeeded)
+ connect( &_dirWatch, SIGNAL(dirty(const QString&)),
+ this, SLOT(slotClearIfNeeded(const QString&)) );
+ connect( &_dirWatch, SIGNAL(created(const QString&)),
+ this, SLOT(slotClear()) );
+ connect( &_dirWatch, SIGNAL(deleted(const QString&)),
+ this, SLOT(slotClear()) );
+
+ kdDebug() << "PanelBrowserMenu Constructor " << path << endl;
+}
+
+PanelBrowserMenu::~PanelBrowserMenu()
+{
+ kdDebug() << "PanelBrowserMenu Destructor " << path() << endl;
+}
+
+void PanelBrowserMenu::slotClearIfNeeded(const QString& p)
+{
+ if (p == path())
+ slotClear();
+}
+
+void PanelBrowserMenu::initialize()
+{
+ _lastpress = QPoint(-1, -1);
+
+ // don't change menu if already visible
+ if (isVisible())
+ return;
+
+ if (_dirty) {
+ // directory content changed while menu was visible
+ slotClear();
+ setInitialized(false);
+ _dirty = false;
+ }
+
+ if (initialized()) return;
+ setInitialized(true);
+
+ // start watching if not already done
+ if (!_dirWatch.contains(path()))
+ _dirWatch.addDir( path() );
+
+ // setup icon map
+ initIconMap();
+
+ // clear maps
+ _filemap.clear();
+ _mimemap.clear();
+
+ int filter = QDir::Dirs | QDir::Files;
+ if (KickerSettings::showHiddenFiles())
+ {
+ filter |= QDir::Hidden;
+ }
+
+ QDir dir(path(), QString::null, QDir::DirsFirst | QDir::Name | QDir::IgnoreCase, filter);
+
+ // does the directory exist?
+ if (!dir.exists()) {
+ insertItem(i18n("Failed to Read Folder"));
+ return;
+ }
+
+ // get entry list
+ const QFileInfoList *list = dir.entryInfoList();
+
+ // no list -> read error
+ if (!list) {
+ insertItem(i18n("Failed to Read Folder"));
+ return;
+ }
+
+ KURL url;
+ url.setPath(path());
+ if (!kapp->authorizeURLAction("list", KURL(), url))
+ {
+ insertItem(i18n("Not Authorized to Read Folder"));
+ return;
+ }
+
+ // insert file manager and terminal entries
+ // only the first part menu got them
+ if(_startid == 0 && !_filesOnly) {
+ insertTitle(path());
+ insertItem(CICON("kfm"), i18n("Open in File Manager"), this, SLOT(slotOpenFileManager()));
+ if (kapp->authorize("shell_access"))
+ insertItem(CICON("terminal"), i18n("Open in Terminal"), this, SLOT(slotOpenTerminal()));
+ }
+
+
+ bool first_entry = true;
+ bool dirfile_separator = false;
+ unsigned int item_count = 0;
+ int run_id = _startid;
+
+ // get list iterator
+ QFileInfoListIterator it(*list);
+
+ // jump to startid
+ it += _startid;
+
+ // iterate over entry list
+ for (; it.current(); ++it)
+ {
+ // bump id
+ run_id++;
+
+ QFileInfo *fi = it.current();
+ // handle directories
+ if (fi->isDir())
+ {
+ QString name = fi->fileName();
+
+ // ignore . and .. entries
+ if (name == "." || name == "..") continue;
+
+ QPixmap icon;
+ QString path = fi->absFilePath();
+
+ // parse .directory if it does exist
+ if (QFile::exists(path + "/.directory")) {
+
+ KSimpleConfig c(path + "/.directory", true);
+ c.setDesktopGroup();
+ QString iconPath = c.readEntry("Icon");
+
+ if ( iconPath.startsWith("./") )
+ iconPath = path + '/' + iconPath.mid(2);
+
+ icon = KGlobal::iconLoader()->loadIcon(iconPath,
+ KIcon::Small, KIcon::SizeSmall,
+ KIcon::DefaultState, 0, true);
+ if(icon.isNull())
+ icon = CICON("folder");
+ name = c.readEntry("Name", name);
+ }
+
+ // use cached folder icon for directories without special icon
+ if (icon.isNull())
+ icon = CICON("folder");
+
+ // insert separator if we are the first menu entry
+ if(first_entry) {
+ if (_startid == 0 && !_filesOnly)
+ insertSeparator();
+ first_entry = false;
+ }
+
+ // append menu entry
+ PanelBrowserMenu *submenu = new PanelBrowserMenu(path, this);
+ submenu->_filesOnly = _filesOnly;
+ append(icon, name, submenu);
+
+ // bump item count
+ item_count++;
+
+ dirfile_separator = true;
+ }
+ // handle files
+ else if(fi->isFile())
+ {
+ QString name = fi->fileName();
+ QString title = KIO::decodeFileName(name);
+
+ QPixmap icon;
+ QString path = fi->absFilePath();
+
+ bool mimecheck = false;
+
+ // .desktop files
+ if(KDesktopFile::isDesktopFile(path))
+ {
+ KSimpleConfig c(path, true);
+ c.setDesktopGroup();
+ title = c.readEntry("Name", title);
+
+ QString s = c.readEntry("Icon");
+ if(!_icons->contains(s)) {
+ icon = KGlobal::iconLoader()->loadIcon(s, KIcon::Small, KIcon::SizeSmall,
+ KIcon::DefaultState, 0, true);
+
+ if(icon.isNull()) {
+ QString type = c.readEntry("Type", "Application");
+ if (type == "Directory")
+ icon = CICON("folder");
+ else if (type == "Mimetype")
+ icon = CICON("txt");
+ else if (type == "FSDevice")
+ icon = CICON("chardevice");
+ else
+ icon = CICON("exec");
+ }
+ else
+ _icons->insert(s, icon);
+ }
+ else
+ icon = CICON(s);
+ }
+ else {
+ // set unknown icon
+ icon = CICON("unknown");
+
+ // mark for delayed mimetime check
+ mimecheck = true;
+ }
+
+ // insert separator if we are the first menu entry
+ if(first_entry) {
+ if(_startid == 0 && !_filesOnly)
+ insertSeparator();
+ first_entry = false;
+ }
+
+ // insert separator if we we first file after at least one directory
+ if (dirfile_separator) {
+ insertSeparator();
+ dirfile_separator = false;
+ }
+
+ // append file entry
+ append(icon, title, name, mimecheck);
+
+ // bump item count
+ item_count++;
+ }
+
+ if (item_count == KickerSettings::maxEntries2())
+ {
+ // Only insert a "More" item if there are actually more items.
+ ++it;
+ if( it.current() ) {
+ insertSeparator();
+ append(CICON("kdisknav"), i18n("More"), new PanelBrowserMenu(path(), this, 0, run_id));
+ }
+ break;
+ }
+ }
+
+#if 0
+ // WABA: tear off handles don't work together with dynamically updated
+ // menus. We can't update the menu while torn off, and we don't know
+ // when it is torn off.
+ if(KGlobalSettings::insertTearOffHandle() && item_count > 0)
+ insertTearOffHandle();
+#endif
+
+ adjustSize();
+
+ QString dirname = path();
+
+ int maxlen = contentsRect().width() - 40;
+ if(item_count == 0)
+ maxlen = fontMetrics().width(dirname);
+
+ if (fontMetrics().width(dirname) > maxlen) {
+ while ((!dirname.isEmpty()) && (fontMetrics().width(dirname) > (maxlen - fontMetrics().width("..."))))
+ dirname = dirname.remove(0, 1);
+ dirname.prepend("...");
+ }
+ setCaption(dirname);
+
+ // setup and start delayed mimetype check timer
+ if(_mimemap.count() > 0) {
+
+ if(!_mimecheckTimer)
+ _mimecheckTimer = new QTimer(this);
+
+ connect(_mimecheckTimer, SIGNAL(timeout()), SLOT(slotMimeCheck()));
+ _mimecheckTimer->start(0);
+ }
+}
+
+void PanelBrowserMenu::append(const QPixmap &pixmap, const QString &title, const QString &file, bool mimecheck)
+{
+ // avoid &'s being converted to accelerators
+ QString newTitle = title;
+ newTitle = KStringHandler::cEmSqueeze( newTitle, fontMetrics(), 20 );
+ newTitle.replace("&", "&&");
+
+ // insert menu item
+ int id = insertItem(pixmap, newTitle);
+
+ // insert into file map
+ _filemap.insert(id, file);
+
+ // insert into mimetype check map
+ if(mimecheck)
+ _mimemap.insert(id, true);
+}
+
+void PanelBrowserMenu::append(const QPixmap &pixmap, const QString &title, PanelBrowserMenu *subMenu)
+{
+ // avoid &'s being converted to accelerators
+ QString newTitle = title;
+ newTitle = KStringHandler::cEmSqueeze( newTitle, fontMetrics(), 20 );
+ newTitle.replace("&", "&&");
+
+ // insert submenu
+ insertItem(pixmap, newTitle, subMenu);
+ // remember submenu for later deletion
+ _subMenus.append(subMenu);
+}
+
+void PanelBrowserMenu::mousePressEvent(QMouseEvent *e)
+{
+ QPopupMenu::mousePressEvent(e);
+ _lastpress = e->pos();
+}
+
+void PanelBrowserMenu::mouseMoveEvent(QMouseEvent *e)
+{
+ QPopupMenu::mouseMoveEvent(e);
+
+ if (!(e->state() & LeftButton)) return;
+ if(_lastpress == QPoint(-1, -1)) return;
+
+ // DND delay
+ if((_lastpress - e->pos()).manhattanLength() < 12) return;
+
+ // get id
+ int id = idAt(_lastpress);
+ if(!_filemap.contains(id)) return;
+
+ // reset _lastpress
+ _lastpress = QPoint(-1, -1);
+
+ // start drag
+ KURL url;
+ url.setPath(path() + "/" + _filemap[id]);
+ KURL::List files(url);
+ KURLDrag *d = new KURLDrag(files, this);
+ connect(d, SIGNAL(destroyed()), this, SLOT(slotDragObjectDestroyed()));
+ d->setPixmap(iconSet(id)->pixmap());
+ d->drag();
+}
+
+void PanelBrowserMenu::slotDragObjectDestroyed()
+{
+ if (KURLDrag::target() != this)
+ {
+ close();
+ }
+}
+
+void PanelBrowserMenu::dragEnterEvent( QDragEnterEvent *ev )
+{
+ if (KURLDrag::canDecode(ev))
+ {
+ ev->accept();
+ }
+ KPanelMenu::dragEnterEvent(ev);
+}
+
+void PanelBrowserMenu::dragMoveEvent(QDragMoveEvent *ev)
+{
+ QMouseEvent mev(QEvent::MouseMove, ev->pos(), Qt::NoButton, Qt::LeftButton);
+ QPopupMenu::mouseMoveEvent(&mev);
+}
+
+void PanelBrowserMenu::dropEvent( QDropEvent *ev )
+{
+ KURL u( path() );
+ KFileItem item( u, QString::fromLatin1( "inode/directory" ), KFileItem::Unknown );
+ KonqOperations::doDrop( &item, u, ev, this );
+ KPanelMenu::dropEvent(ev);
+ // ### TODO: Update list
+}
+
+void PanelBrowserMenu::slotExec(int id)
+{
+ kapp->propagateSessionManager();
+
+ if(!_filemap.contains(id)) return;
+
+ KURL url;
+ url.setPath(path() + "/" + _filemap[id]);
+ new KRun(url, 0, true); // will delete itself
+ _lastpress = QPoint(-1, -1);
+}
+
+void PanelBrowserMenu::slotOpenTerminal()
+{
+ KConfig * config = kapp->config();
+ config->setGroup("General");
+ QString term = config->readPathEntry("TerminalApplication", "konsole");
+
+ KProcess proc;
+ proc << term;
+ if (term == "konsole")
+ proc << "--workdir" << path();
+ else
+ proc.setWorkingDirectory(path());
+ proc.start(KProcess::DontCare);
+}
+
+void PanelBrowserMenu::slotOpenFileManager()
+{
+ new KRun(path());
+}
+
+void PanelBrowserMenu::slotMimeCheck()
+{
+ // get the first map entry
+ QMap<int, bool>::Iterator it = _mimemap.begin();
+
+ // no mime types left to check -> stop timer
+ if(it == _mimemap.end()) {
+ _mimecheckTimer->stop();
+ delete _mimecheckTimer;
+ _mimecheckTimer = 0;
+ return;
+ }
+
+ int id = it.key();
+ QString file = _filemap[id];
+
+ _mimemap.remove(it);
+
+ KURL url;
+ url.setPath( path() + '/' + file );
+
+// KMimeType::Ptr mt = KMimeType::findByURL(url, 0, true, false);
+// QString icon(mt->icon(url, true));
+ QString icon = KMimeType::iconForURL( url );
+// kdDebug() << url.url() << ": " << icon << endl;
+
+ file = KStringHandler::cEmSqueeze( file, fontMetrics(), 20 );
+ file.replace("&", "&&");
+
+ if(!_icons->contains(icon)) {
+ QPixmap pm = SmallIcon(icon);
+ if( pm.height() > 16 )
+ {
+ QPixmap cropped( 16, 16 );
+ copyBlt( &cropped, 0, 0, &pm, 0, 0, 16, 16 );
+ pm = cropped;
+ }
+ _icons->insert(icon, pm);
+ changeItem(id, pm, file);
+ }
+ else
+ changeItem(id, CICON(icon), file);
+}
+
+void PanelBrowserMenu::slotClear()
+{
+ // no need to watch any further
+ if (_dirWatch.contains(path()))
+ _dirWatch.removeDir( path() );
+
+ // don't change menu if already visible
+ if (isVisible()) {
+ _dirty = true;
+ return;
+ }
+ KPanelMenu::slotClear();
+
+ for (QValueVector<PanelBrowserMenu*>::iterator it = _subMenus.begin();
+ it != _subMenus.end();
+ ++it)
+ {
+ delete *it;
+ }
+ _subMenus.clear(); // deletes submenus
+}
+
+void PanelBrowserMenu::initIconMap()
+{
+ if(_icons) return;
+
+// kdDebug() << "PanelBrowserMenu::initIconMap" << endl;
+
+ _icons = new QMap<QString, QPixmap>;
+
+ _icons->insert("folder", SmallIcon("folder"));
+ _icons->insert("unknown", SmallIcon("mime_empty"));
+ _icons->insert("folder_open", SmallIcon("folder_open"));
+ _icons->insert("kdisknav", SmallIcon("kdisknav"));
+ _icons->insert("kfm", SmallIcon("kfm"));
+ _icons->insert("terminal", SmallIcon("terminal"));
+ _icons->insert("txt", SmallIcon("txt"));
+ _icons->insert("exec", SmallIcon("exec"));
+ _icons->insert("chardevice", SmallIcon("chardevice"));
+}
+
+// vim: sw=4 et
diff --git a/kicker/kicker/ui/browser_mnu.h b/kicker/kicker/ui/browser_mnu.h
new file mode 100644
index 000000000..5999db2cb
--- /dev/null
+++ b/kicker/kicker/ui/browser_mnu.h
@@ -0,0 +1,81 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __browser_mnu_h__
+#define __browser_mnu_h__
+
+#include <qmap.h>
+#include <qvaluevector.h>
+#include <kpanelmenu.h>
+#include <kdirwatch.h>
+
+class PanelBrowserMenu : public KPanelMenu
+{
+ Q_OBJECT
+
+public:
+ PanelBrowserMenu(QString path, QWidget *parent = 0, const char *name = 0, int startid = 0);
+ ~PanelBrowserMenu();
+
+ void append(const QPixmap &pixmap, const QString &title, const QString &filename, bool mimecheck);
+ void append(const QPixmap &pixmap, const QString &title, PanelBrowserMenu *subMenu);
+
+public slots:
+ void initialize();
+
+protected slots:
+ void slotExec(int id);
+ void slotOpenTerminal();
+ void slotOpenFileManager();
+ void slotMimeCheck();
+ void slotClearIfNeeded(const QString&);
+ void slotClear();
+ void slotDragObjectDestroyed();
+
+protected:
+ void mousePressEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void dropEvent(QDropEvent *ev);
+ void dragEnterEvent(QDragEnterEvent *ev);
+ void dragMoveEvent(QDragMoveEvent *);
+ void initIconMap();
+
+ QPoint _lastpress;
+ QMap<int, QString> _filemap;
+ QMap<int, bool> _mimemap;
+ QTimer *_mimecheckTimer;
+ KDirWatch _dirWatch;
+ QValueVector<PanelBrowserMenu*> _subMenus;
+
+ int _startid;
+ bool _dirty;
+
+ // With this flag set to 'true' the menu only displays files and
+ // directories. i.e. the "Open in File Manager" and "Open in Terminal"
+ // entries are not inserted in the menu and its submenus.
+ bool _filesOnly;
+
+ static QMap<QString, QPixmap> *_icons;
+};
+
+#endif
diff --git a/kicker/kicker/ui/client_mnu.cpp b/kicker/kicker/ui/client_mnu.cpp
new file mode 100644
index 000000000..f098e40d4
--- /dev/null
+++ b/kicker/kicker/ui/client_mnu.cpp
@@ -0,0 +1,139 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qpixmap.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <dcopclient.h>
+
+#include "client_mnu.h"
+#include "client_mnu.moc"
+
+KickerClientMenu::KickerClientMenu( QWidget * parent, const char *name )
+ : QPopupMenu( parent, name), DCOPObject( name )
+{
+}
+
+KickerClientMenu::~KickerClientMenu()
+{
+}
+
+void KickerClientMenu::clear()
+{
+ QPopupMenu::clear();
+}
+
+void KickerClientMenu::insertItem( QPixmap icon, QString text, int id )
+{
+ int globalid = QPopupMenu::insertItem( icon, text, this, SLOT( slotActivated(int) ) );
+ setItemParameter( globalid, id );
+}
+
+void KickerClientMenu::insertItem( QString text, int id )
+{
+ int globalid = QPopupMenu::insertItem( text, this, SLOT( slotActivated(int) ) );
+ setItemParameter( globalid, id );
+}
+
+QCString KickerClientMenu::insertMenu( QPixmap icon, QString text, int id )
+{
+ QString subname("%1-submenu%2");
+ QCString subid = subname.arg(objId()).arg(id).local8Bit();
+ KickerClientMenu *sub = new KickerClientMenu(this, subid);
+ int globalid = QPopupMenu::insertItem( icon, text, sub, id);
+ setItemParameter( globalid, id );
+
+ return subid;
+}
+
+void KickerClientMenu::connectDCOPSignal( QCString signal, QCString appId, QCString objId )
+{
+ // very primitive right now
+ if ( signal == "activated(int)" ) {
+ app = appId;
+ obj = objId;
+ } else {
+ kdWarning() << "DCOP: no such signal " << className() << "::" << signal.data() << endl;
+ }
+}
+
+bool KickerClientMenu::process(const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData)
+{
+ if ( fun == "clear()" ) {
+ clear();
+ replyType = "void";
+ return true;
+ }
+ else if ( fun == "insertItem(QPixmap,QString,int)" ) {
+ QDataStream dataStream( data, IO_ReadOnly );
+ QPixmap icon;
+ QString text;
+ int id;
+ dataStream >> icon >> text >> id;
+ insertItem( icon, text, id );
+ replyType = "void";
+ return true;
+ }
+ else if ( fun == "insertMenu(QPixmap,QString,int)" ) {
+ QDataStream dataStream( data, IO_ReadOnly );
+ QPixmap icon;
+ QString text;
+ int id;
+ dataStream >> icon >> text >> id;
+ QCString ref = insertMenu( icon, text, id );
+ replyType = "QCString";
+ QDataStream replyStream( replyData, IO_WriteOnly );
+ replyStream << ref;
+ return true;
+ }
+ else if ( fun == "insertItem(QString,int)" ) {
+ QDataStream dataStream( data, IO_ReadOnly );
+ QString text;
+ int id;
+ dataStream >> text >> id;
+ insertItem( text, id );
+ replyType = "void";
+ return true;
+ }
+ else if ( fun == "connectDCOPSignal(QCString,QCString,QCString)" ) {
+ QDataStream dataStream( data, IO_ReadOnly );
+ QCString signal, appId, objId;
+ dataStream >> signal >> appId >> objId;
+ connectDCOPSignal( signal, appId, objId );
+ replyType = "void";
+ return true;
+ }
+ return false;
+}
+
+void KickerClientMenu::slotActivated(int id)
+{
+ if ( !app.isEmpty() ) {
+ QByteArray data;
+ QDataStream dataStream( data, IO_WriteOnly );
+ dataStream << id;
+ kapp->dcopClient()->send( app, obj, "activated(int)", data );
+ }
+}
diff --git a/kicker/kicker/ui/client_mnu.h b/kicker/kicker/ui/client_mnu.h
new file mode 100644
index 000000000..fe8e4a113
--- /dev/null
+++ b/kicker/kicker/ui/client_mnu.h
@@ -0,0 +1,81 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef PANEL_CLIENTMENU_H
+#define PANEL_CLIENTMENU_H
+
+#include <qstringlist.h>
+#include <qpopupmenu.h>
+
+#include <dcopobject.h>
+
+
+class PanelKMenu;
+
+// Classes to handle client application menus. Used by PanelKButton, which
+// also manages the toplevel K Button Menu.
+
+/**
+ * Small additions to QPopupMenu to contain data we need for DCop handling
+ */
+class KickerClientMenu : public QPopupMenu, DCOPObject
+{
+ Q_OBJECT
+public:
+ KickerClientMenu( QWidget *parent=0, const char *name=0);
+ ~KickerClientMenu();
+
+ // dcop exported
+ void clear();
+ void insertItem( QPixmap icon, QString text, int id );
+ void insertItem( QString text, int id );
+
+ QCString insertMenu( QPixmap icon, QString test, int id );
+
+ // dcop signals:
+ // void activated(int)
+
+ void connectDCOPSignal( QCString signal, QCString appId, QCString objId );
+
+ // dcop internal
+ virtual bool process(const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &reply);
+
+protected slots:
+ void slotActivated(int id);
+
+private:
+ QCString app, obj; // for the signal
+
+ // for the panel menu, internal
+ friend class PanelKMenu;
+ QString text;
+ QPixmap icon;
+
+ // for the KickerClientMenu, internal
+ friend class MenuManager;
+ int idInParentMenu;
+ QCString createdBy;
+};
+
+#endif
diff --git a/kicker/kicker/ui/dirdrop_mnu.cpp b/kicker/kicker/ui/dirdrop_mnu.cpp
new file mode 100644
index 000000000..2f64fdd12
--- /dev/null
+++ b/kicker/kicker/ui/dirdrop_mnu.cpp
@@ -0,0 +1,39 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include "dirdrop_mnu.h"
+
+PanelDirDropMenu::PanelDirDropMenu(QWidget *parent, const char *name)
+ :QPopupMenu(parent, name)
+{
+ insertItem(SmallIconSet("folder"), i18n("Add as &File Manager URL"), Url);
+ setAccel(CTRL+Key_F, Url);
+ insertItem(SmallIconSet("kdisknav"), i18n("Add as Quick&Browser"), Browser);
+ setAccel(CTRL+Key_B, Browser);
+ adjustSize();
+}
+
+
diff --git a/kicker/kicker/ui/dirdrop_mnu.h b/kicker/kicker/ui/dirdrop_mnu.h
new file mode 100644
index 000000000..15fa799c2
--- /dev/null
+++ b/kicker/kicker/ui/dirdrop_mnu.h
@@ -0,0 +1,37 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __dirdrop_mnu_h__
+#define __dirdrop_mnu_h__
+
+#include <qpopupmenu.h>
+
+// The directory dropped menu
+class PanelDirDropMenu : public QPopupMenu
+{
+public:
+ enum OpButton{Url=1, Browser};
+ PanelDirDropMenu(QWidget *parent=0, const char *name=0);
+};
+
+#endif
diff --git a/kicker/kicker/ui/exe_dlg.cpp b/kicker/kicker/ui/exe_dlg.cpp
new file mode 100644
index 000000000..19583444e
--- /dev/null
+++ b/kicker/kicker/ui/exe_dlg.cpp
@@ -0,0 +1,204 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qfileinfo.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <qcheckbox.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qlineedit.h>
+#include <qvbox.h>
+
+#include <kicondialog.h>
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <kstandarddirs.h>
+#include <kurlcompletion.h>
+#include <kurlrequester.h>
+#include <kurl.h>
+
+#include <kdebug.h>
+
+#include "exe_dlg.h"
+#include "nonKDEButtonSettings.h"
+
+PanelExeDialog::PanelExeDialog(const QString& title, const QString& description,
+ const QString &path, const QString &icon,
+ const QString &cmd, bool inTerm,
+ QWidget *parent, const char *name)
+ : KDialogBase(parent, name, false, i18n("Non-KDE Application Configuration"), Ok|Cancel, Ok, true),
+ m_icon(icon.isEmpty() ? "exec" : icon),
+ m_iconChanged(false)
+{
+ setCaption(i18n("Non-KDE Application Configuration"));
+ QFileInfo fi(path);
+
+ ui = new NonKDEButtonSettings(makeVBoxMainWidget());
+ fillCompletion();
+
+ ui->m_title->setText(title);
+ ui->m_description->setText(description);
+ ui->m_exec->setURL(path);
+ ui->m_commandLine->setText(cmd);
+ ui->m_inTerm->setChecked(inTerm);
+ ui->m_icon->setIconType(KIcon::Panel, KIcon::Application);
+
+ updateIcon();
+
+ connect(ui->m_exec, SIGNAL(urlSelected(const QString &)),
+ this, SLOT(slotSelect(const QString &)));
+ connect(ui->m_exec, SIGNAL(textChanged(const QString &)),
+ this, SLOT(slotTextChanged(const QString &)));
+ connect(ui->m_exec, SIGNAL(returnPressed()),
+ this, SLOT(slotReturnPressed()));
+ connect(ui->m_icon, SIGNAL(iconChanged(QString)),
+ this, SLOT(slotIconChanged(QString)));
+
+ // leave decent space for the commandline
+ resize(sizeHint().width() > 300 ? sizeHint().width() : 300,
+ sizeHint().height());
+}
+
+void PanelExeDialog::slotOk()
+{
+ KDialogBase::slotOk();
+ // WARNING! we get delete after this, so don't do anything after it!
+ emit updateSettings(this);
+}
+
+bool PanelExeDialog::useTerminal() const
+{
+ return ui->m_inTerm->isChecked();
+}
+
+QString PanelExeDialog::title() const
+{
+ return ui->m_title->text();
+}
+
+QString PanelExeDialog::description() const
+{
+ return ui->m_description->text();
+}
+
+QString PanelExeDialog::commandLine() const
+{
+ return ui->m_commandLine->text();
+}
+
+QString PanelExeDialog::iconPath() const
+{
+ return ui->m_icon->icon();
+}
+
+QString PanelExeDialog::command() const
+{
+ return ui->m_exec->url();
+}
+
+void PanelExeDialog::updateIcon()
+{
+ if(!m_icon.isEmpty())
+ ui->m_icon->setIcon(m_icon);
+}
+
+void PanelExeDialog::fillCompletion()
+{
+ KCompletion *comp = ui->m_exec->completionObject();
+ QStringList exePaths = KStandardDirs::systemPaths();
+
+ for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); it++)
+ {
+ QDir d( (*it) );
+ d.setFilter( QDir::Files | QDir::Executable );
+
+ const QFileInfoList *list = d.entryInfoList();
+ if (!list)
+ continue;
+
+ QFileInfoListIterator it2( *list );
+ QFileInfo *fi;
+
+ while ( (fi = it2.current()) != 0 ) {
+ m_partialPath2full.insert(fi->fileName(), fi->filePath(), false);
+ comp->addItem(fi->fileName());
+ comp->addItem(fi->filePath());
+ ++it2;
+ }
+ }
+}
+
+void PanelExeDialog::slotIconChanged(QString)
+{
+ m_iconChanged = true;
+}
+
+void PanelExeDialog::slotTextChanged(const QString &str)
+{
+ if (m_iconChanged)
+ {
+ return;
+ }
+
+ QString exeLocation = str;
+ QMap<QString, QString>::iterator it = m_partialPath2full.find(str);
+
+ if (it != m_partialPath2full.end())
+ exeLocation = it.data();
+ KMimeType::pixmapForURL(KURL( exeLocation ), 0, KIcon::Panel, 0, KIcon::DefaultState, &m_icon);
+ updateIcon();
+}
+
+void PanelExeDialog::slotReturnPressed()
+{
+ if (m_partialPath2full.contains(ui->m_exec->url()))
+ ui->m_exec->setURL(m_partialPath2full[ui->m_exec->url()]);
+}
+
+void PanelExeDialog::slotSelect(const QString& exec)
+{
+ if ( exec.isEmpty() )
+ return;
+
+ QFileInfo fi(exec);
+ if (!fi.isExecutable())
+ {
+ if(KMessageBox::warningYesNo(0, i18n("The selected file is not executable.\n"
+ "Do you want to select another file?"), i18n("Not Executable"), i18n("Select Other"), KStdGuiItem::cancel())
+ == KMessageBox::Yes)
+ {
+ ui->m_exec->button()->animateClick();
+ }
+
+ return;
+ }
+
+ KMimeType::pixmapForURL(KURL( exec ), 0, KIcon::Panel, 0, KIcon::DefaultState, &m_icon);
+ updateIcon();
+}
+
+#include "exe_dlg.moc"
+
diff --git a/kicker/kicker/ui/exe_dlg.h b/kicker/kicker/ui/exe_dlg.h
new file mode 100644
index 000000000..f7624fa35
--- /dev/null
+++ b/kicker/kicker/ui/exe_dlg.h
@@ -0,0 +1,65 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __exe_dlg_h__
+#define __exe_dlg_h__
+
+#include <kdialogbase.h>
+class NonKDEButtonSettings;
+
+class PanelExeDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ PanelExeDialog(const QString& title, const QString& description,
+ const QString &path, const QString &pixmap=QString::null,
+ const QString &cmd=QString::null, bool inTerm=false,
+ QWidget *parent=0, const char *name=0);
+ QString iconPath() const;
+ QString command() const;
+ QString commandLine() const;
+ QString title() const;
+ QString description() const;
+ bool useTerminal() const;
+
+signals:
+ void updateSettings(PanelExeDialog*);
+
+protected slots:
+ void slotSelect(const QString& exec);
+ void slotTextChanged(const QString &);
+ void slotReturnPressed();
+ void slotIconChanged(QString);
+ void slotOk();
+
+protected:
+ void fillCompletion();
+ void updateIcon();
+
+ NonKDEButtonSettings* ui;
+ QString m_icon;
+ QMap<QString, QString> m_partialPath2full;
+ bool m_iconChanged;
+};
+
+#endif
diff --git a/kicker/kicker/ui/extensionop_mnu.cpp b/kicker/kicker/ui/extensionop_mnu.cpp
new file mode 100644
index 000000000..9389f9cd4
--- /dev/null
+++ b/kicker/kicker/ui/extensionop_mnu.cpp
@@ -0,0 +1,66 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpanelextension.h>
+#include <kstdguiitem.h>
+
+#include "kicker.h"
+#include "extensionop_mnu.h"
+
+PanelExtensionOpMenu::PanelExtensionOpMenu(const QString& extension, int actions, QWidget *parent, const char *name)
+ : QPopupMenu(parent, name)
+{
+ if (!Kicker::the()->isImmutable())
+ {
+ insertItem(SmallIcon("remove"), i18n("&Remove"), Remove);
+ }
+
+ if (actions & KPanelExtension::ReportBug)
+ {
+ insertSeparator();
+ insertItem(i18n("Report &Bug..."), ReportBug);
+ }
+
+ if (actions & KPanelExtension::Help
+ || actions & KPanelExtension::About)
+ insertSeparator();
+
+ if (actions & KPanelExtension::About)
+ {
+ insertItem(i18n("&About"), About);
+ }
+
+ if (actions & KPanelExtension::Help)
+ {
+ insertItem(SmallIcon("help"), KStdGuiItem::help().text(), Help);
+ }
+
+ if (!Kicker::the()->isImmutable() && (actions & KPanelExtension::Preferences)) {
+ insertSeparator();
+ insertItem(SmallIcon("configure"), i18n("&Configure %1...").arg(extension), Preferences);
+ }
+
+ adjustSize();
+}
diff --git a/kicker/kicker/ui/extensionop_mnu.h b/kicker/kicker/ui/extensionop_mnu.h
new file mode 100644
index 000000000..85bf914af
--- /dev/null
+++ b/kicker/kicker/ui/extensionop_mnu.h
@@ -0,0 +1,36 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __extensionop_mnu_h__
+#define __extensionop_mnu_h__
+
+#include <qpopupmenu.h>
+
+class PanelExtensionOpMenu : public QPopupMenu
+{
+public:
+ enum OpButton{Move = 9900, Remove = 9901, Help = 9902, About = 9903, Preferences = 9904, ReportBug = 9905, Shade = 9906 };
+ PanelExtensionOpMenu(const QString& extension, int actions, QWidget *parent=0, const char *name=0);
+};
+
+#endif
diff --git a/kicker/kicker/ui/hidebutton.cpp b/kicker/kicker/ui/hidebutton.cpp
new file mode 100644
index 000000000..31d614006
--- /dev/null
+++ b/kicker/kicker/ui/hidebutton.cpp
@@ -0,0 +1,202 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2004 Nadeem Hasan <nhasan@kde.org>
+ Copyright (C) 2004 Aaron J. Seigo <aseigo@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "hidebutton.h"
+
+#include <qpainter.h>
+
+#include <kapplication.h>
+#include <kcursor.h>
+#include <kglobalsettings.h>
+#include <kiconeffect.h>
+#include <kiconloader.h>
+#include <kicontheme.h>
+#include <kipc.h>
+#include <kstandarddirs.h>
+
+HideButton::HideButton(QWidget *parent, const char *name)
+ : QButton(parent, name),
+ m_highlight(false),
+ m_arrow(Qt::LeftArrow)
+{
+ setBackgroundOrigin(AncestorOrigin);
+
+ connect(kapp, SIGNAL(settingsChanged(int)), SLOT(slotSettingsChanged(int)));
+ connect(kapp, SIGNAL(iconChanged(int)), SLOT(slotIconChanged(int)));
+
+ kapp->addKipcEventMask(KIPC::SettingsChanged);
+ kapp->addKipcEventMask(KIPC::IconChanged);
+
+ slotSettingsChanged(KApplication::SETTINGS_MOUSE);
+}
+
+void HideButton::drawButton(QPainter *p)
+{
+ if (m_arrow == Qt::LeftArrow)
+ {
+ p->setPen(colorGroup().mid());
+ p->drawLine(width()-1, 0, width()-1, height());
+ }
+ else if (m_arrow == Qt::RightArrow)
+ {
+ p->setPen(colorGroup().mid());
+ p->drawLine(0, 0, 0, height());
+ }
+ else if (m_arrow == Qt::UpArrow)
+ {
+ p->setPen(colorGroup().mid());
+ p->drawLine(0, height()-1, width(), height()-1);
+ }
+ else if (m_arrow == Qt::DownArrow)
+ {
+ p->setPen(colorGroup().mid());
+ p->drawLine(0, 0, width(), 0);
+ }
+
+ drawButtonLabel(p);
+}
+
+void HideButton::drawButtonLabel(QPainter *p)
+{
+ if (pixmap())
+ {
+ QPixmap pix = m_highlight? m_activeIcon : m_normalIcon;
+
+ if (isOn() || isDown())
+ {
+ p->translate(2, 2);
+ }
+
+ QPoint origin(2, 2);
+
+ if (pix.height() < (height() - 4))
+ {
+ origin.setY(origin.y() + ((height() - pix.height()) / 2));
+ }
+
+ if (pix.width() < (width() - 4))
+ {
+ origin.setX(origin.x() + ((width() - pix.width()) / 2));
+ }
+
+ p->drawPixmap(origin, pix);
+ }
+}
+
+void HideButton::setPixmap(const QPixmap &pix)
+{
+ QButton::setPixmap(pix);
+ generateIcons();
+}
+
+void HideButton::setArrowType(Qt::ArrowType arrow)
+{
+ m_arrow = arrow;
+ switch (arrow)
+ {
+ case Qt::LeftArrow:
+ setPixmap(SmallIcon("1leftarrow"));
+ break;
+
+ case Qt::RightArrow:
+ setPixmap(SmallIcon("1rightarrow"));
+ break;
+
+ case Qt::UpArrow:
+ setPixmap(SmallIcon("1uparrow"));
+ break;
+
+ case Qt::DownArrow:
+ default:
+ setPixmap(SmallIcon("1downarrow"));
+ break;
+ }
+}
+
+void HideButton::generateIcons()
+{
+ if (!pixmap())
+ {
+ return;
+ }
+
+ QImage image = pixmap()->convertToImage();
+ image = image.smoothScale(size() - QSize(4, 4), QImage::ScaleMin);
+
+ KIconEffect effect;
+
+ m_normalIcon = effect.apply(image, KIcon::Panel, KIcon::DefaultState);
+ m_activeIcon = effect.apply(image, KIcon::Panel, KIcon::ActiveState);
+}
+
+void HideButton::slotSettingsChanged(int category)
+{
+ if (category != KApplication::SETTINGS_MOUSE)
+ {
+ return;
+ }
+
+ bool changeCursor = KGlobalSettings::changeCursorOverIcon();
+
+ if (changeCursor)
+ {
+ setCursor(KCursor::handCursor());
+ }
+ else
+ {
+ unsetCursor();
+ }
+}
+
+void HideButton::slotIconChanged(int group)
+{
+ if (group != KIcon::Panel)
+ {
+ return;
+ }
+
+ generateIcons();
+ repaint(false);
+}
+
+void HideButton::enterEvent(QEvent *e)
+{
+ m_highlight = true;
+
+ repaint(false);
+ QButton::enterEvent(e);
+}
+
+void HideButton::leaveEvent(QEvent *e)
+{
+ m_highlight = false;
+
+ repaint(false);
+ QButton::enterEvent(e);
+}
+
+void HideButton::resizeEvent(QResizeEvent *)
+{
+ generateIcons();
+}
+
+#include "hidebutton.moc"
+
+// vim:ts=4:sw=4:et
diff --git a/kicker/kicker/ui/hidebutton.h b/kicker/kicker/ui/hidebutton.h
new file mode 100644
index 000000000..da387cde7
--- /dev/null
+++ b/kicker/kicker/ui/hidebutton.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2004 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef HIDEBUTTON_H
+#define HIDEBUTTON_H
+
+#include <qbutton.h>
+#include <qpixmap.h>
+
+class HideButton : public QButton
+{
+ Q_OBJECT
+
+ public:
+ HideButton(QWidget *parent, const char *name = 0);
+ void setArrowType(Qt::ArrowType arrow);
+ void setPixmap(const QPixmap &pix);
+
+ protected:
+ void drawButton(QPainter *p);
+ void drawButtonLabel(QPainter *p);
+ void generateIcons();
+
+ void enterEvent(QEvent *e);
+ void leaveEvent( QEvent *e );
+ void resizeEvent(QResizeEvent *e);
+
+ bool m_highlight;
+ QPixmap m_normalIcon;
+ QPixmap m_activeIcon;
+ Qt::ArrowType m_arrow;
+
+ protected slots:
+ void slotSettingsChanged( int category );
+ void slotIconChanged( int group );
+};
+
+#endif // HIDEBUTTON_H
+
+// vim:ts=4:sw=4:et
diff --git a/kicker/kicker/ui/k_mnu.cpp b/kicker/kicker/ui/k_mnu.cpp
new file mode 100644
index 000000000..609ce84be
--- /dev/null
+++ b/kicker/kicker/ui/k_mnu.cpp
@@ -0,0 +1,739 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <dmctl.h>
+
+#include <qimage.h>
+#include <qpainter.h>
+#include <qstyle.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kaboutkde.h>
+#include <kaction.h>
+#include <kbookmarkmenu.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kwin.h>
+
+#include "client_mnu.h"
+#include "container_base.h"
+#include "global.h"
+#include "kbutton.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "konqbookmarkmanager.h"
+#include "menuinfo.h"
+#include "menumanager.h"
+#include "popupmenutitle.h"
+#include "quickbrowser_mnu.h"
+#include "recentapps.h"
+
+#include "k_mnu.h"
+#include "k_mnu.moc"
+
+PanelKMenu::PanelKMenu()
+ : PanelServiceMenu(QString::null, QString::null, 0, "KMenu")
+ , bookmarkMenu(0)
+ , bookmarkOwner(0)
+{
+ static const QCString dcopObjId("KMenu");
+ DCOPObject::setObjId(dcopObjId);
+ // set the first client id to some arbitrarily large value.
+ client_id = 10000;
+ // Don't automatically clear the main menu.
+ disableAutoClear();
+ actionCollection = new KActionCollection(this);
+ setCaption(i18n("K Menu"));
+ connect(Kicker::the(), SIGNAL(configurationChanged()),
+ this, SLOT(configChanged()));
+ DCOPClient *dcopClient = KApplication::dcopClient();
+ dcopClient->connectDCOPSignal(0, "appLauncher",
+ "serviceStartedByStorageId(QString,QString)",
+ dcopObjId,
+ "slotServiceStartedByStorageId(QString,QString)",
+ false);
+}
+
+PanelKMenu::~PanelKMenu()
+{
+ clearSubmenus();
+ delete bookmarkMenu;
+ delete bookmarkOwner;
+}
+
+void PanelKMenu::slotServiceStartedByStorageId(QString starter,
+ QString storageId)
+{
+ if (starter != "kmenu")
+ {
+ kdDebug() << "KMenu - updating recently used applications: " <<
+ storageId << endl;
+ KService::Ptr service = KService::serviceByStorageId(storageId);
+ updateRecentlyUsedApps(service);
+ }
+}
+
+
+bool PanelKMenu::loadSidePixmap()
+{
+ if (!KickerSettings::useSidePixmap())
+ {
+ return false;
+ }
+
+ QString sideName = KickerSettings::sidePixmapName();
+ QString sideTileName = KickerSettings::sideTileName();
+
+ QImage image;
+ image.load(locate("data", "kicker/pics/" + sideName));
+
+ if (image.isNull())
+ {
+ kdDebug(1210) << "Can't find a side pixmap" << endl;
+ return false;
+ }
+
+ KickerLib::colorize(image);
+ sidePixmap.convertFromImage(image);
+
+ image.load(locate("data", "kicker/pics/" + sideTileName));
+
+ if (image.isNull())
+ {
+ kdDebug(1210) << "Can't find a side tile pixmap" << endl;
+ return false;
+ }
+
+ KickerLib::colorize(image);
+ sideTilePixmap.convertFromImage(image);
+
+ if (sidePixmap.width() != sideTilePixmap.width())
+ {
+ kdDebug(1210) << "Pixmaps have to be the same size" << endl;
+ return false;
+ }
+
+ // pretile the pixmap to a height of at least 100 pixels
+ if (sideTilePixmap.height() < 100)
+ {
+ int tiles = (int)(100 / sideTilePixmap.height()) + 1;
+ QPixmap preTiledPixmap(sideTilePixmap.width(), sideTilePixmap.height() * tiles);
+ QPainter p(&preTiledPixmap);
+ p.drawTiledPixmap(preTiledPixmap.rect(), sideTilePixmap);
+ sideTilePixmap = preTiledPixmap;
+ }
+
+ return true;
+}
+
+void PanelKMenu::paletteChanged()
+{
+ if (!loadSidePixmap())
+ {
+ sidePixmap = sideTilePixmap = QPixmap();
+ setMinimumSize( sizeHint() );
+ }
+}
+
+void PanelKMenu::initialize()
+{
+// kdDebug(1210) << "PanelKMenu::initialize()" << endl;
+ updateRecent();
+
+ if (initialized())
+ {
+ return;
+ }
+
+ if (loadSidePixmap())
+ {
+ // in case we've been through here before, let's disconnect
+ disconnect(kapp, SIGNAL(kdisplayPaletteChanged()),
+ this, SLOT(paletteChanged()));
+ connect(kapp, SIGNAL(kdisplayPaletteChanged()),
+ this, SLOT(paletteChanged()));
+ }
+ else
+ {
+ sidePixmap = sideTilePixmap = QPixmap();
+ }
+
+ // add services
+ PanelServiceMenu::initialize();
+
+ if (KickerSettings::showMenuTitles())
+ {
+ int id;
+ id = insertItem(new PopupMenuTitle(i18n("All Applications"), font()), -1 /* id */, 0);
+ setItemEnabled( id, false );
+ id = insertItem(new PopupMenuTitle(i18n("Actions"), font()), -1 /* id */, -1);
+ setItemEnabled( id, false );
+ }
+
+ // create recent menu section
+ createRecentMenuItems();
+
+ bool need_separator = false;
+
+ // insert bookmarks
+ if (KickerSettings::useBookmarks() && kapp->authorizeKAction("bookmarks"))
+ {
+ // Need to create a new popup each time, it's deleted by subMenus.clear()
+ KPopupMenu * bookmarkParent = new KPopupMenu( this, "bookmarks" );
+ if(!bookmarkOwner)
+ bookmarkOwner = new KBookmarkOwner;
+ delete bookmarkMenu; // can't reuse old one, the popup has been deleted
+ bookmarkMenu = new KBookmarkMenu( KonqBookmarkManager::self(), bookmarkOwner, bookmarkParent, actionCollection, true, false );
+
+ insertItem(KickerLib::menuIconSet("bookmark"), i18n("Bookmarks"), bookmarkParent);
+
+ subMenus.append(bookmarkParent);
+ need_separator = true;
+ }
+
+ // insert quickbrowser
+ if (KickerSettings::useBrowser())
+ {
+ PanelQuickBrowser *browserMnu = new PanelQuickBrowser(this);
+ browserMnu->initialize();
+
+ insertItem(KickerLib::menuIconSet("kdisknav"),
+ i18n("Quick Browser"),
+ KickerLib::reduceMenu(browserMnu));
+ subMenus.append(browserMnu);
+ need_separator = true;
+ }
+
+ // insert dynamic menus
+ QStringList menu_ext = KickerSettings::menuExtensions();
+ if (!menu_ext.isEmpty())
+ {
+ for (QStringList::ConstIterator it=menu_ext.begin(); it!=menu_ext.end(); ++it)
+ {
+ MenuInfo info(*it);
+ if (!info.isValid())
+ continue;
+
+ KPanelMenu *menu = info.load();
+ if (menu)
+ {
+ insertItem(KickerLib::menuIconSet(info.icon()), info.name(), menu);
+ dynamicSubMenus.append(menu);
+ need_separator = true;
+ }
+ }
+ }
+
+ if (need_separator)
+ insertSeparator();
+
+ // insert client menus, if any
+ if (clients.count() > 0) {
+ QIntDictIterator<KickerClientMenu> it(clients);
+ while (it){
+ if (it.current()->text.at(0) != '.')
+ insertItem(
+ it.current()->icon,
+ it.current()->text,
+ it.current(),
+ it.currentKey()
+ );
+ ++it;
+ }
+ insertSeparator();
+ }
+
+ // run command
+ if (kapp->authorize("run_command"))
+ {
+ insertItem(KickerLib::menuIconSet("run"),
+ i18n("Run Command..."),
+ this,
+ SLOT( slotRunCommand()));
+ insertSeparator();
+ }
+
+ if (DM().isSwitchable() && kapp->authorize("switch_user"))
+ {
+ sessionsMenu = new QPopupMenu( this );
+ insertItem(KickerLib::menuIconSet("switchuser"), i18n("Switch User"), sessionsMenu);
+ connect( sessionsMenu, SIGNAL(aboutToShow()), SLOT(slotPopulateSessions()) );
+ connect( sessionsMenu, SIGNAL(activated(int)), SLOT(slotSessionActivated(int)) );
+ }
+
+ /*
+ If the user configured ksmserver to
+ */
+ KConfig ksmserver("ksmserverrc", false, false);
+ ksmserver.setGroup("General");
+ if (ksmserver.readEntry( "loginMode" ) == "restoreSavedSession")
+ {
+ insertItem(KickerLib::menuIconSet("filesave"), i18n("Save Session"), this, SLOT(slotSaveSession()));
+ }
+
+ if (kapp->authorize("lock_screen"))
+ {
+ insertItem(KickerLib::menuIconSet("lock"), i18n("Lock Session"), this, SLOT(slotLock()));
+ }
+
+ if (kapp->authorize("logout"))
+ {
+ insertItem(KickerLib::menuIconSet("exit"), i18n("Log Out..."), this, SLOT(slotLogout()));
+ }
+
+#if 0
+ // WABA: tear off handles don't work together with dynamically updated
+ // menus. We can't update the menu while torn off, and we don't know
+ // when it is torn off.
+ if (KGlobalSettings::insertTearOffHandle())
+ insertTearOffHandle();
+#endif
+
+ setInitialized(true);
+}
+
+int PanelKMenu::insertClientMenu(KickerClientMenu *p)
+{
+ int id = client_id;
+ clients.insert(id, p);
+ slotClear();
+ return id;
+}
+
+void PanelKMenu::removeClientMenu(int id)
+{
+ clients.remove(id);
+ removeItem(id);
+ slotClear();
+}
+
+extern int kicker_screen_number;
+
+void PanelKMenu::slotLock()
+{
+ QCString appname( "kdesktop" );
+ if ( kicker_screen_number )
+ appname.sprintf("kdesktop-screen-%d", kicker_screen_number);
+ kapp->dcopClient()->send(appname, "KScreensaverIface", "lock()", "");
+}
+
+void PanelKMenu::slotLogout()
+{
+ kapp->requestShutDown();
+}
+
+void PanelKMenu::slotPopulateSessions()
+{
+ int p = 0;
+ DM dm;
+
+ sessionsMenu->clear();
+ if (kapp->authorize("start_new_session") && (p = dm.numReserve()) >= 0)
+ {
+ if (kapp->authorize("lock_screen"))
+ sessionsMenu->insertItem(/*SmallIconSet("lockfork"),*/ i18n("Lock Current && Start New Session"), 100 );
+ sessionsMenu->insertItem(SmallIconSet("fork"), i18n("Start New Session"), 101 );
+ if (!p) {
+ sessionsMenu->setItemEnabled( 100, false );
+ sessionsMenu->setItemEnabled( 101, false );
+ }
+ sessionsMenu->insertSeparator();
+ }
+ SessList sess;
+ if (dm.localSessions( sess ))
+ for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ int id = sessionsMenu->insertItem( DM::sess2Str( *it ), (*it).vt );
+ if (!(*it).vt)
+ sessionsMenu->setItemEnabled( id, false );
+ if ((*it).self)
+ sessionsMenu->setItemChecked( id, true );
+ }
+}
+
+void PanelKMenu::slotSessionActivated( int ent )
+{
+ if (ent == 100)
+ doNewSession( true );
+ else if (ent == 101)
+ doNewSession( false );
+ else if (!sessionsMenu->isItemChecked( ent ))
+ DM().lockSwitchVT( ent );
+}
+
+void PanelKMenu::doNewSession( bool lock )
+{
+ int result = KMessageBox::warningContinueCancel(
+ kapp->desktop()->screen(kapp->desktop()->screenNumber(this)),
+ i18n("<p>You have chosen to open another desktop session.<br>"
+ "The current session will be hidden "
+ "and a new login screen will be displayed.<br>"
+ "An F-key is assigned to each session; "
+ "F%1 is usually assigned to the first session, "
+ "F%2 to the second session and so on. "
+ "You can switch between sessions by pressing "
+ "Ctrl, Alt and the appropriate F-key at the same time. "
+ "Additionally, the KDE Panel and Desktop menus have "
+ "actions for switching between sessions.</p>")
+ .arg(7).arg(8),
+ i18n("Warning - New Session"),
+ KGuiItem(i18n("&Start New Session"), "fork"),
+ ":confirmNewSession",
+ KMessageBox::PlainCaption | KMessageBox::Notify);
+
+ if (result==KMessageBox::Cancel)
+ return;
+
+ if (lock)
+ slotLock();
+
+ DM().startReserve();
+}
+
+void PanelKMenu::slotSaveSession()
+{
+ QByteArray data;
+ kapp->dcopClient()->send( "ksmserver", "default",
+ "saveCurrentSession()", data );
+}
+
+void PanelKMenu::slotRunCommand()
+{
+ QByteArray data;
+ QCString appname( "kdesktop" );
+ if ( kicker_screen_number )
+ appname.sprintf("kdesktop-screen-%d", kicker_screen_number);
+
+ kapp->updateRemoteUserTimestamp( appname );
+ kapp->dcopClient()->send( appname, "KDesktopIface",
+ "popupExecuteCommand()", data );
+}
+
+void PanelKMenu::slotEditUserContact()
+{
+}
+
+void PanelKMenu::setMinimumSize(const QSize & s)
+{
+ KPanelMenu::setMinimumSize(s.width() + sidePixmap.width(), s.height());
+}
+
+void PanelKMenu::setMaximumSize(const QSize & s)
+{
+ KPanelMenu::setMaximumSize(s.width() + sidePixmap.width(), s.height());
+}
+
+void PanelKMenu::setMinimumSize(int w, int h)
+{
+ KPanelMenu::setMinimumSize(w + sidePixmap.width(), h);
+}
+
+void PanelKMenu::setMaximumSize(int w, int h)
+{
+ KPanelMenu::setMaximumSize(w + sidePixmap.width(), h);
+}
+
+void PanelKMenu::showMenu()
+{
+ kdDebug( 1210 ) << "PanelKMenu::showMenu()" << endl;
+ PanelPopupButton *kButton = MenuManager::the()->findKButtonFor(this);
+ if (kButton)
+ {
+ adjustSize();
+ kButton->showMenu();
+ }
+ else
+ {
+ show();
+ }
+}
+
+QRect PanelKMenu::sideImageRect()
+{
+ return QStyle::visualRect( QRect( frameWidth(), frameWidth(), sidePixmap.width(),
+ height() - 2*frameWidth() ), this );
+}
+
+void PanelKMenu::resizeEvent(QResizeEvent * e)
+{
+// kdDebug(1210) << "PanelKMenu::resizeEvent():" << endl;
+// kdDebug(1210) << geometry().width() << ", " << geometry().height() << endl;
+
+ PanelServiceMenu::resizeEvent(e);
+
+ setFrameRect( QStyle::visualRect( QRect( sidePixmap.width(), 0,
+ width() - sidePixmap.width(), height() ), this ) );
+}
+
+//Workaround Qt3.3.x sizing bug, by ensuring we're always wide enough.
+void PanelKMenu::resize(int width, int height)
+{
+ width = kMax(width, maximumSize().width());
+ PanelServiceMenu::resize(width, height);
+}
+
+QSize PanelKMenu::sizeHint() const
+{
+ QSize s = PanelServiceMenu::sizeHint();
+// kdDebug(1210) << "PanelKMenu::sizeHint()" << endl;
+// kdDebug(1210) << s.width() << ", " << s.height() << endl;
+ return s;
+}
+
+void PanelKMenu::paintEvent(QPaintEvent * e)
+{
+ if (sidePixmap.isNull()) {
+ PanelServiceMenu::paintEvent(e);
+ return;
+ }
+
+ QPainter p(this);
+ p.setClipRegion(e->region());
+
+ style().drawPrimitive( QStyle::PE_PanelPopup, &p,
+ QRect( 0, 0, width(), height() ),
+ colorGroup(), QStyle::Style_Default,
+ QStyleOption( frameWidth(), 0 ) );
+
+ QRect r = sideImageRect();
+ r.setBottom( r.bottom() - sidePixmap.height() );
+ if ( r.intersects( e->rect() ) )
+ {
+ p.drawTiledPixmap( r, sideTilePixmap );
+ }
+
+ r = sideImageRect();
+ r.setTop( r.bottom() - sidePixmap.height() );
+ if ( r.intersects( e->rect() ) )
+ {
+ QRect drawRect = r.intersect( e->rect() );
+ QRect pixRect = drawRect;
+ pixRect.moveBy( -r.left(), -r.top() );
+ p.drawPixmap( drawRect.topLeft(), sidePixmap, pixRect );
+ }
+
+ drawContents( &p );
+}
+
+QMouseEvent PanelKMenu::translateMouseEvent( QMouseEvent* e )
+{
+ QRect side = sideImageRect();
+
+ if ( !side.contains( e->pos() ) )
+ return *e;
+
+ QPoint newpos( e->pos() );
+ QApplication::reverseLayout() ?
+ newpos.setX( newpos.x() - side.width() ) :
+ newpos.setX( newpos.x() + side.width() );
+ QPoint newglobal( e->globalPos() );
+ QApplication::reverseLayout() ?
+ newglobal.setX( newpos.x() - side.width() ) :
+ newglobal.setX( newpos.x() + side.width() );
+
+ return QMouseEvent( e->type(), newpos, newglobal, e->button(), e->state() );
+}
+
+void PanelKMenu::mousePressEvent(QMouseEvent * e)
+{
+ QMouseEvent newEvent = translateMouseEvent(e);
+ PanelServiceMenu::mousePressEvent( &newEvent );
+}
+
+void PanelKMenu::mouseReleaseEvent(QMouseEvent *e)
+{
+ QMouseEvent newEvent = translateMouseEvent(e);
+ PanelServiceMenu::mouseReleaseEvent( &newEvent );
+}
+
+void PanelKMenu::mouseMoveEvent(QMouseEvent *e)
+{
+ QMouseEvent newEvent = translateMouseEvent(e);
+ PanelServiceMenu::mouseMoveEvent( &newEvent );
+}
+
+void PanelKMenu::configChanged()
+{
+ RecentlyLaunchedApps::the().m_bNeedToUpdate = false;
+ RecentlyLaunchedApps::the().configChanged();
+ PanelServiceMenu::configChanged();
+}
+
+// create and fill "recent" section at first
+void PanelKMenu::createRecentMenuItems()
+{
+ RecentlyLaunchedApps::the().m_nNumMenuItems = 0;
+
+ QStringList RecentApps;
+ RecentlyLaunchedApps::the().getRecentApps(RecentApps);
+
+ if (RecentApps.count() > 0)
+ {
+ bool bSeparator = KickerSettings::showMenuTitles();
+ int nId = serviceMenuEndId() + 1;
+ int nIndex = KickerSettings::showMenuTitles() ? 1 : 0;
+
+ for (QValueList<QString>::ConstIterator it =
+ RecentApps.fromLast(); /*nop*/; --it)
+ {
+ KService::Ptr s = KService::serviceByDesktopPath(*it);
+ if (!s)
+ {
+ RecentlyLaunchedApps::the().removeItem(*it);
+ }
+ else
+ {
+ if (bSeparator)
+ {
+ bSeparator = false;
+ int id = insertItem(
+ new PopupMenuTitle(
+ RecentlyLaunchedApps::the().caption(), font()),
+ serviceMenuEndId(), 0);
+ setItemEnabled( id, false );
+ }
+ insertMenuItem(s, nId++, nIndex);
+ RecentlyLaunchedApps::the().m_nNumMenuItems++;
+ }
+
+ if (it == RecentApps.begin())
+ {
+ break;
+ }
+ }
+
+ if (!KickerSettings::showMenuTitles())
+ {
+ insertSeparator(RecentlyLaunchedApps::the().m_nNumMenuItems);
+ }
+ }
+}
+
+void PanelKMenu::clearSubmenus()
+{
+ // we don't need to delete these on the way out since the libloader
+ // handles them for us
+ if (QApplication::closingDown())
+ {
+ return;
+ }
+
+ for (PopupMenuList::const_iterator it = dynamicSubMenus.constBegin();
+ it != dynamicSubMenus.constEnd();
+ ++it)
+ {
+ delete *it;
+ }
+ dynamicSubMenus.clear();
+
+ PanelServiceMenu::clearSubmenus();
+}
+
+void PanelKMenu::updateRecent()
+{
+ if (!RecentlyLaunchedApps::the().m_bNeedToUpdate)
+ {
+ return;
+ }
+
+ RecentlyLaunchedApps::the().m_bNeedToUpdate = false;
+
+ int nId = serviceMenuEndId() + 1;
+
+ // remove previous items
+ if (RecentlyLaunchedApps::the().m_nNumMenuItems > 0)
+ {
+ // -1 --> menu title
+ int i = KickerSettings::showMenuTitles() ? -1 : 0;
+ for (; i < RecentlyLaunchedApps::the().m_nNumMenuItems; i++)
+ {
+ removeItem(nId + i);
+ entryMap_.remove(nId + i);
+ }
+ RecentlyLaunchedApps::the().m_nNumMenuItems = 0;
+
+ if (!KickerSettings::showMenuTitles())
+ {
+ removeItemAt(0);
+ }
+ }
+
+ // insert new items
+ QStringList RecentApps;
+ RecentlyLaunchedApps::the().getRecentApps(RecentApps);
+
+ if (RecentApps.count() > 0)
+ {
+ bool bNeedSeparator = KickerSettings::showMenuTitles();
+ for (QValueList<QString>::ConstIterator it = RecentApps.fromLast();
+ /*nop*/; --it)
+ {
+ KService::Ptr s = KService::serviceByDesktopPath(*it);
+ if (!s)
+ {
+ RecentlyLaunchedApps::the().removeItem(*it);
+ }
+ else
+ {
+ if (bNeedSeparator)
+ {
+ bNeedSeparator = false;
+ int id = insertItem(new PopupMenuTitle(
+ RecentlyLaunchedApps::the().caption(),
+ font()), nId - 1, 0);
+ setItemEnabled( id, false );
+ }
+ insertMenuItem(s, nId++, KickerSettings::showMenuTitles() ?
+ 1 : 0);
+ RecentlyLaunchedApps::the().m_nNumMenuItems++;
+ }
+
+ if (it == RecentApps.begin())
+ break;
+ }
+
+ if (!KickerSettings::showMenuTitles())
+ {
+ insertSeparator(RecentlyLaunchedApps::the().m_nNumMenuItems);
+ }
+ }
+}
+
+void PanelKMenu::clearRecentMenuItems()
+{
+ RecentlyLaunchedApps::the().clearRecentApps();
+ RecentlyLaunchedApps::the().save();
+ RecentlyLaunchedApps::the().m_bNeedToUpdate = true;
+ updateRecent();
+}
+
+
diff --git a/kicker/kicker/ui/k_mnu.h b/kicker/kicker/ui/k_mnu.h
new file mode 100644
index 000000000..f20cde06d
--- /dev/null
+++ b/kicker/kicker/ui/k_mnu.h
@@ -0,0 +1,106 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __k_mnu_h__
+#define __k_mnu_h__
+
+#include <dcopobject.h>
+#include <qintdict.h>
+#include <qpixmap.h>
+
+#include "service_mnu.h"
+
+class KickerClientMenu;
+class KBookmarkMenu;
+class KActionCollection;
+class KBookmarkOwner;
+class Panel;
+
+class PanelKMenu : public PanelServiceMenu, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+k_dcop:
+ void slotServiceStartedByStorageId(QString starter, QString desktopPath);
+
+public:
+ PanelKMenu();
+ ~PanelKMenu();
+
+ int insertClientMenu(KickerClientMenu *p);
+ void removeClientMenu(int id);
+
+ virtual QSize sizeHint() const;
+ virtual void setMinimumSize(const QSize &);
+ virtual void setMaximumSize(const QSize &);
+ virtual void setMinimumSize(int, int);
+ virtual void setMaximumSize(int, int);
+ virtual void showMenu();
+ void clearRecentMenuItems();
+
+public slots:
+ virtual void initialize();
+
+ //### KDE4: workaround for Qt bug, remove later
+ virtual void resize(int width, int height);
+
+protected slots:
+ void slotLock();
+ void slotLogout();
+ void slotPopulateSessions();
+ void slotSessionActivated( int );
+ void slotSaveSession();
+ void slotRunCommand();
+ void slotEditUserContact();
+ void paletteChanged();
+ virtual void configChanged();
+ void updateRecent();
+
+protected:
+ QRect sideImageRect();
+ QMouseEvent translateMouseEvent(QMouseEvent* e);
+ void resizeEvent(QResizeEvent *);
+ void paintEvent(QPaintEvent *);
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ bool loadSidePixmap();
+ void doNewSession(bool lock);
+ void createRecentMenuItems();
+ virtual void clearSubmenus();
+
+private:
+ QPopupMenu *sessionsMenu;
+ QPixmap sidePixmap;
+ QPixmap sideTilePixmap;
+ int client_id;
+ bool delay_init;
+ QIntDict<KickerClientMenu> clients;
+ KBookmarkMenu *bookmarkMenu;
+ KActionCollection *actionCollection;
+ KBookmarkOwner *bookmarkOwner;
+ PopupMenuList dynamicSubMenus;
+};
+
+#endif
diff --git a/kicker/kicker/ui/nonKDEButtonSettings.ui b/kicker/kicker/ui/nonKDEButtonSettings.ui
new file mode 100644
index 000000000..5c44aca85
--- /dev/null
+++ b/kicker/kicker/ui/nonKDEButtonSettings.ui
@@ -0,0 +1,221 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>NonKDEButtonSettings</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>NonKDEButtonSettings</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>436</width>
+ <height>225</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KURLRequester" row="7" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_exec</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name of the executable file to be run when this button is selected. If it is not in your $PATH then you will need to provide an absolute path.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="8" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Co&amp;mmand line arguments (optional):</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_commandLine</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any command line options that should be passed to the command here.
+
+&lt;i&gt;Example&lt;/i&gt;: For the command `rm -rf` enter "-rf" in this text box.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="10" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_inTerm</cstring>
+ </property>
+ <property name="text">
+ <string>Run in a &amp;terminal window</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select this option if the command is a command line application and you wish to be able to see its output when run.</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="9" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_commandLine</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any command line options that should be passed to the command here.
+
+&lt;i&gt;Example&lt;/i&gt;: For the command `rm -rf` enter "-rf" in this text box.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="6" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Executable:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_exec</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name of the executable file to be run when this button is selected. If it is not in your $PATH then you will need to provide an absolute path.</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>15</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name you would like to appear for this button here.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Button title:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name you would like to appear for this button here.</string>
+ </property>
+ </widget>
+ <spacer row="11" column="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KIconButton" row="0" column="0" rowspan="3" 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>58</width>
+ <height>58</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>58</width>
+ <height>58</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSize">
+ <number>48</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Description:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name you would like to appear for this button here.</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_description</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>15</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name you would like to appear for this button here.</string>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>8</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>m_icon</tabstop>
+ <tabstop>m_title</tabstop>
+ <tabstop>m_description</tabstop>
+ <tabstop>m_exec</tabstop>
+ <tabstop>m_commandLine</tabstop>
+ <tabstop>m_inTerm</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/kicker/kicker/ui/panelmenuiteminfo.h b/kicker/kicker/ui/panelmenuiteminfo.h
new file mode 100644
index 000000000..29faca50f
--- /dev/null
+++ b/kicker/kicker/ui/panelmenuiteminfo.h
@@ -0,0 +1,103 @@
+/*****************************************************************
+
+Copyright (c) 2003 Aaron J. Seigo
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef PANELMENUITEMINFO_H
+#define PANELMENUITEMINFO_H
+
+#include <qpopupmenu.h>
+#include <qstring.h>
+
+#include <kiconloader.h>
+
+// a little class meant to be used to store menu items for sorting then later
+// plugging into a popup menu
+
+class PanelMenuItemInfo
+{
+ public:
+ PanelMenuItemInfo()
+ : m_recvr(0), m_id(-1) {}
+
+ PanelMenuItemInfo(const QString& iconName, const QString& visibleName, const QObject* recvr, const QCString& slot, int id = -1)
+ : m_icon(iconName), m_name(visibleName), m_slot_(slot), m_recvr(recvr), m_id(id) {}
+
+ PanelMenuItemInfo(const QString& iconName, const QString& visibleName, int id = -1)
+ : m_icon(iconName), m_name(visibleName), m_recvr(0), m_id(id) {}
+
+ PanelMenuItemInfo(const PanelMenuItemInfo& c)
+ : m_icon(c.m_icon), m_name(c.m_name), m_slot_(c.m_slot_), m_recvr(c.m_recvr), m_id(c.m_id) {}
+
+ PanelMenuItemInfo& operator=(const PanelMenuItemInfo& c)
+ {
+ m_icon = c.m_icon;
+ m_name = c.m_name;
+ m_slot_ = c.m_slot_;
+ m_recvr = c.m_recvr;
+ m_id = c.m_id;
+ return *this;
+ }
+
+ bool operator<(const PanelMenuItemInfo& rh)
+ {
+ return m_name.lower() < rh.m_name.lower();
+ }
+
+ bool operator<=(const PanelMenuItemInfo& rh)
+ {
+ return m_name.lower() <= rh.m_name.lower();
+ }
+
+ bool operator>(const PanelMenuItemInfo& rh)
+ {
+ return m_name.lower() > rh.m_name.lower();
+ }
+
+ int plug(QPopupMenu* menu)
+ {
+ if (!m_icon.isEmpty() && m_icon != "unknown")
+ {
+ if (m_recvr && !m_slot_.isEmpty())
+ {
+ return menu->insertItem(SmallIconSet(m_icon), m_name, m_recvr, m_slot_, 0, m_id);
+ }
+
+ return menu->insertItem(SmallIconSet(m_icon), m_name, m_id);
+ }
+ else if (m_recvr && !m_slot_.isEmpty())
+ {
+ return menu->insertItem(m_name, m_recvr, m_slot_, 0, m_id);
+ }
+
+ return menu->insertItem(m_name, m_id);
+ }
+
+ private:
+ QString m_icon;
+ QString m_name;
+ QCString m_slot_; // HPUX namespace is polluted with m_slot
+ const QObject* m_recvr;
+ int m_id;
+};
+
+#endif
+
diff --git a/kicker/kicker/ui/popupmenutitle.cpp b/kicker/kicker/ui/popupmenutitle.cpp
new file mode 100644
index 000000000..adf44b802
--- /dev/null
+++ b/kicker/kicker/ui/popupmenutitle.cpp
@@ -0,0 +1,33 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <elter@kde.org>
+ Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include "popupmenutitle.h"
+
+PopupMenuTitle::PopupMenuTitle(const QString &name, const QFont &font) :
+ QCustomMenuItem(),
+ m_desktopName(name),
+ m_font(font)
+{
+ m_font.setBold(true);
+}
diff --git a/kicker/kicker/ui/popupmenutitle.h b/kicker/kicker/ui/popupmenutitle.h
new file mode 100644
index 000000000..4724c88c7
--- /dev/null
+++ b/kicker/kicker/ui/popupmenutitle.h
@@ -0,0 +1,85 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <elter@kde.org>
+ Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef POPUPMENUTITLE_H
+#define POPUPMENUTITLE_H
+
+#include <qfont.h>
+#include <qstring.h>
+#include <qstyle.h>
+#include <qpainter.h>
+#include <qmenudata.h>
+
+#include <kapplication.h>
+
+class PopupMenuTitle : public QCustomMenuItem
+{
+public:
+ PopupMenuTitle(const QString &name, const QFont &font);
+
+ bool fullSpan () const { return true; }
+
+ void paint(QPainter* p, const QColorGroup& cg,
+ bool /* act */, bool /*enabled*/,
+ int x, int y, int w, int h)
+ {
+ p->save();
+ QRect r(x, y, w, h);
+ kapp->style().drawPrimitive(QStyle::PE_HeaderSection,
+ p, r, cg);
+
+ if (!m_desktopName.isEmpty())
+ {
+ p->setPen(cg.buttonText());
+ p->setFont(m_font);
+ p->drawText(x, y, w, h,
+ AlignCenter | SingleLine,
+ m_desktopName);
+ }
+
+ p->setPen(cg.highlight());
+ p->drawLine(0, 0, r.right(), 0);
+ p->restore();
+ }
+
+ void setFont(const QFont &font)
+ {
+ m_font = font;
+ m_font.setBold(true);
+ }
+
+ QSize sizeHint()
+ {
+ QSize size = QFontMetrics(m_font).size(AlignHCenter, m_desktopName);
+ size.setHeight(size.height() +
+ (kapp->style().pixelMetric(QStyle::PM_DefaultFrameWidth) * 2 + 1));
+ return size;
+ }
+
+ private:
+ QString m_desktopName;
+ QFont m_font;
+};
+
+#endif
diff --git a/kicker/kicker/ui/quickbrowser_mnu.cpp b/kicker/kicker/ui/quickbrowser_mnu.cpp
new file mode 100644
index 000000000..583fc1deb
--- /dev/null
+++ b/kicker/kicker/ui/quickbrowser_mnu.cpp
@@ -0,0 +1,60 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qdir.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kurl.h>
+
+#include "browser_mnu.h"
+#include "quickbrowser_mnu.h"
+#include "quickbrowser_mnu.moc"
+
+PanelQuickBrowser::PanelQuickBrowser(QWidget *parent, const char *name)
+ : KPanelMenu("", parent, name) {}
+
+void PanelQuickBrowser::initialize()
+{
+ if(initialized()) return;
+ setInitialized(true);
+
+ KURL url;
+
+ url.setPath(QDir::homeDirPath());
+ if (kapp->authorizeURLAction("list", KURL(), url))
+ insertItem(SmallIcon("kfm_home"), i18n("&Home Folder"),
+ new PanelBrowserMenu(url.path(), this));
+
+ url.setPath(QDir::rootDirPath());
+ if (kapp->authorizeURLAction("list", KURL(), url))
+ insertItem(SmallIcon("folder_red"), i18n("&Root Folder"),
+ new PanelBrowserMenu(url.path(), this));
+
+ url.setPath(QDir::rootDirPath() + "etc");
+ if (kapp->authorizeURLAction("list", KURL(), url))
+ insertItem(SmallIcon("folder_yellow"), i18n("System &Configuration"),
+ new PanelBrowserMenu(url.path(), this));
+}
diff --git a/kicker/kicker/ui/quickbrowser_mnu.h b/kicker/kicker/ui/quickbrowser_mnu.h
new file mode 100644
index 000000000..9d9582a8b
--- /dev/null
+++ b/kicker/kicker/ui/quickbrowser_mnu.h
@@ -0,0 +1,43 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __quickbrowser_mnu_h__
+#define __quickbrowser_mnu_h__
+
+#include <kpanelmenu.h>
+
+class PanelQuickBrowser : public KPanelMenu
+{
+ Q_OBJECT
+
+public:
+ PanelQuickBrowser(QWidget *parent=0, const char *name=0);
+
+public slots:
+ virtual void initialize();
+
+protected slots:
+ void slotExec(int) {}
+};
+
+#endif
diff --git a/kicker/kicker/ui/recentapps.cpp b/kicker/kicker/ui/recentapps.cpp
new file mode 100644
index 000000000..54241cb29
--- /dev/null
+++ b/kicker/kicker/ui/recentapps.cpp
@@ -0,0 +1,172 @@
+/*****************************************************************
+
+Copyright (c) 2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <time.h>
+
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "kickerSettings.h"
+
+#include "recentapps.h"
+
+RecentlyLaunchedApps& RecentlyLaunchedApps::the()
+{
+ static RecentlyLaunchedApps obj;
+ return obj;
+}
+
+RecentlyLaunchedApps::RecentlyLaunchedApps()
+{
+ // set defaults
+ m_nNumMenuItems = 0;
+ m_bNeedToUpdate = false;
+ m_bInitialised = false;
+ init();
+}
+
+void RecentlyLaunchedApps::init()
+{
+ if (m_bInitialised)
+ {
+ return;
+ }
+
+ m_nNumMenuItems = 0;
+ m_appInfos.clear();
+
+ configChanged();
+
+ QStringList recentApps = KickerSettings::recentAppsStat();
+
+ for (QStringList::ConstIterator it = recentApps.begin();
+ it != recentApps.end(); ++it )
+ {
+ QRegExp re( "(\\d*) (\\d*) (.*)" );
+ if (re.search(*it) != -1)
+ {
+ int nCount = re.cap(1).toInt();
+ long lTime = re.cap(2).toLong();
+ QString szPath = re.cap(3);
+ m_appInfos.append(RecentlyLaunchedAppInfo(
+ szPath, nCount, time_t(lTime)));
+ }
+ }
+
+ qHeapSort(m_appInfos);
+
+ m_bInitialised = true;
+}
+
+void RecentlyLaunchedApps::configChanged()
+{
+ qHeapSort(m_appInfos);
+}
+
+void RecentlyLaunchedApps::save()
+{
+ QStringList recentApps;
+
+ for (QValueList<RecentlyLaunchedAppInfo>::const_iterator it =
+ m_appInfos.constBegin(); it != m_appInfos.constEnd(); ++it)
+ {
+ recentApps.append(QString("%1 %2 %3").arg((*it).getLaunchCount())
+ .arg((*it).getLastLaunchTime())
+ .arg((*it).getDesktopPath()));
+ }
+
+ KickerSettings::setRecentAppsStat(recentApps);
+ KickerSettings::writeConfig();
+}
+
+void RecentlyLaunchedApps::appLaunched(const QString& strApp)
+{
+ // Inform other applications (like the quickstarter applet)
+ // that an application was started
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << launchDCOPSignalSource() << strApp;
+ KApplication::kApplication()->dcopClient()->emitDCOPSignal("appLauncher",
+ "serviceStartedByStorageId(QString,QString)", params);
+
+ for (QValueList<RecentlyLaunchedAppInfo>::iterator it = m_appInfos.begin();
+ it != m_appInfos.end(); ++it)
+ {
+ if ((*it).getDesktopPath() == strApp)
+ {
+ (*it).increaseLaunchCount();
+ (*it).setLastLaunchTime(time(0));
+ qHeapSort(m_appInfos);
+ return;
+ }
+ }
+
+ m_appInfos.append(RecentlyLaunchedAppInfo(strApp, 1, time(0)));
+ qHeapSort(m_appInfos);
+}
+
+void RecentlyLaunchedApps::getRecentApps(QStringList& recentApps)
+{
+ recentApps.clear();
+
+ int maximumNum = KickerSettings::numVisibleEntries();
+ int i = 0;
+ for (QValueList<RecentlyLaunchedAppInfo>::const_iterator it =
+ m_appInfos.constBegin();
+ it != m_appInfos.constEnd() && i < maximumNum;
+ ++it, ++i)
+ {
+ recentApps.append((*it).getDesktopPath());
+ }
+}
+
+void RecentlyLaunchedApps::removeItem( const QString& strName )
+{
+ for (QValueList<RecentlyLaunchedAppInfo>::iterator it = m_appInfos.begin();
+ it != m_appInfos.end(); ++it)
+ {
+ if ((*it).getDesktopPath() == strName)
+ {
+ m_appInfos.erase(it);
+ return;
+ }
+ }
+}
+
+void RecentlyLaunchedApps::clearRecentApps()
+{
+ m_appInfos.clear();
+}
+
+QString RecentlyLaunchedApps::caption() const
+{
+ return KickerSettings::recentVsOften() ?
+ i18n("Recently Used Applications") :
+ i18n("Most Used Applications");
+}
diff --git a/kicker/kicker/ui/recentapps.h b/kicker/kicker/ui/recentapps.h
new file mode 100644
index 000000000..0582cc166
--- /dev/null
+++ b/kicker/kicker/ui/recentapps.h
@@ -0,0 +1,99 @@
+/*****************************************************************
+
+Copyright (c) 2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __recentapps_h__
+#define __recentapps_h__
+
+#include <qvaluelist.h>
+
+class RecentlyLaunchedApps;
+
+class RecentlyLaunchedAppInfo
+{
+public:
+ RecentlyLaunchedAppInfo()
+ {
+ m_launchCount = 0;
+ m_lastLaunchTime = 0;
+ }
+
+ RecentlyLaunchedAppInfo(const QString& desktopPath, int nLaunchCount, time_t lastLaunchTime)
+ {
+ m_desktopPath = desktopPath;
+ m_launchCount = nLaunchCount;
+ m_lastLaunchTime = lastLaunchTime;
+ }
+
+ RecentlyLaunchedAppInfo(const RecentlyLaunchedAppInfo& clone)
+ {
+ m_desktopPath = clone.m_desktopPath;
+ m_launchCount = clone.m_launchCount;
+ m_lastLaunchTime = clone.m_lastLaunchTime;
+ }
+
+ bool operator<(const RecentlyLaunchedAppInfo& rhs)
+ {
+ // Sort items in descending order according to either last launch time or launch count.
+ return KickerSettings::recentVsOften() ?
+ m_lastLaunchTime > rhs.m_lastLaunchTime:
+ m_launchCount > rhs.m_launchCount;
+ }
+
+ QString getDesktopPath() const { return m_desktopPath; }
+ int getLaunchCount() const { return m_launchCount; };
+ time_t getLastLaunchTime() const { return m_lastLaunchTime; };
+ void increaseLaunchCount() { m_launchCount++; };
+ void setLaunchCount(int nLaunchCount) { m_launchCount = nLaunchCount; };
+ void setLastLaunchTime(time_t lastLaunch) { m_lastLaunchTime = lastLaunch; };
+
+private:
+ QString m_desktopPath;
+ int m_launchCount;
+ time_t m_lastLaunchTime;
+};
+
+class RecentlyLaunchedApps
+{
+public:
+ static RecentlyLaunchedApps& the();
+ void init();
+ void configChanged();
+ void save();
+ void clearRecentApps();
+ void appLaunched(const QString & strApp);
+ void getRecentApps(QStringList & RecentApps);
+ void removeItem(const QString &strName);
+ QString caption() const;
+
+ int m_nNumMenuItems;
+ bool m_bNeedToUpdate;
+
+private:
+ QString launchDCOPSignalSource() { return "kmenu"; }
+ RecentlyLaunchedApps();
+
+ QValueList<RecentlyLaunchedAppInfo> m_appInfos;
+ bool m_bInitialised;
+};
+
+#endif
diff --git a/kicker/kicker/ui/removeapplet_mnu.cpp b/kicker/kicker/ui/removeapplet_mnu.cpp
new file mode 100644
index 000000000..fce885f39
--- /dev/null
+++ b/kicker/kicker/ui/removeapplet_mnu.cpp
@@ -0,0 +1,99 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <klocale.h>
+#include <kglobal.h>
+
+#include "pluginmanager.h"
+#include "containerarea.h"
+#include "container_applet.h"
+
+#include "panelmenuiteminfo.h"
+#include "removeapplet_mnu.h"
+#include "removeapplet_mnu.moc"
+
+PanelRemoveAppletMenu::PanelRemoveAppletMenu(ContainerArea* cArea,
+ QWidget *parent,
+ const char *name)
+ : QPopupMenu(parent, name), m_containerArea(cArea)
+{
+ connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
+ connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
+}
+
+void PanelRemoveAppletMenu::slotAboutToShow()
+{
+ int id = 0;
+
+ clear();
+ m_containers = m_containerArea->containers("Applet") +
+ m_containerArea->containers("Special Button");
+
+ QValueList<PanelMenuItemInfo> items;
+
+ for (BaseContainer::List::const_iterator it = m_containers.constBegin();
+ it != m_containers.constEnd();)
+ {
+ BaseContainer* container = *it;
+ if (container->isImmutable())
+ {
+ ++it;
+ m_containers.remove(container);
+ continue;
+ }
+
+ items.append(PanelMenuItemInfo(container->icon(),
+ container->visibleName().replace("&", "&&"),
+ id));
+ ++id;
+ ++it;
+ }
+
+ qHeapSort(items);
+
+ for (QValueList<PanelMenuItemInfo>::iterator it = items.begin();
+ it != items.end();
+ ++it)
+ {
+ (*it).plug(this);
+ }
+
+ if (m_containers.count() > 1)
+ {
+ insertSeparator();
+ insertItem(i18n("All"), this, SLOT(slotRemoveAll()), 0, id);
+ }
+}
+
+void PanelRemoveAppletMenu::slotExec(int id)
+{
+ if (m_containers.at(id) != m_containers.end())
+ {
+ m_containerArea->removeContainer(*m_containers.at(id));
+ }
+}
+
+void PanelRemoveAppletMenu::slotRemoveAll()
+{
+ m_containerArea->removeContainers(m_containers);
+}
diff --git a/kicker/kicker/ui/removeapplet_mnu.h b/kicker/kicker/ui/removeapplet_mnu.h
new file mode 100644
index 000000000..455a93afd
--- /dev/null
+++ b/kicker/kicker/ui/removeapplet_mnu.h
@@ -0,0 +1,52 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __removeapplet_mnu_h__
+#define __removeapplet_mnu_h__
+
+#include <qptrlist.h>
+#include <qpopupmenu.h>
+
+#include "appletinfo.h"
+#include "container_base.h"
+
+class ContainerArea;
+
+class PanelRemoveAppletMenu : public QPopupMenu
+{
+ Q_OBJECT
+
+public:
+ PanelRemoveAppletMenu(ContainerArea* cArea, QWidget* parent = 0, const char* name = 0);
+
+protected slots:
+ void slotExec( int id );
+ void slotAboutToShow();
+ void slotRemoveAll();
+
+private:
+ BaseContainer::List m_containers;
+ ContainerArea* m_containerArea;
+};
+
+#endif
diff --git a/kicker/kicker/ui/removebutton_mnu.cpp b/kicker/kicker/ui/removebutton_mnu.cpp
new file mode 100644
index 000000000..33dc48e14
--- /dev/null
+++ b/kicker/kicker/ui/removebutton_mnu.cpp
@@ -0,0 +1,111 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qregexp.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include "panelbutton.h"
+#include "pluginmanager.h"
+#include "containerarea.h"
+#include "container_button.h"
+
+#include "panelmenuiteminfo.h"
+#include "removebutton_mnu.h"
+#include "removebutton_mnu.moc"
+
+PanelRemoveButtonMenu::PanelRemoveButtonMenu( ContainerArea* cArea,
+ QWidget *parent, const char *name )
+ : QPopupMenu( parent, name ), containerArea( cArea )
+{
+ connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
+ connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
+}
+
+void PanelRemoveButtonMenu::addToContainers(const QString& type)
+{
+ BaseContainer::List list = containerArea->containers(type);
+ for (BaseContainer::Iterator it = list.begin();
+ it != list.end();
+ ++it)
+ {
+ if ((*it)->isImmutable())
+ {
+ continue;
+ }
+ containers.append(*it);
+ }
+}
+
+void PanelRemoveButtonMenu::slotAboutToShow()
+{
+ clear();
+ containers.clear();
+
+ addToContainers("URLButton");
+ addToContainers("ServiceButton");
+ addToContainers("ServiceMenuButton");
+ addToContainers("ExecButton");
+
+ int id = 0;
+ QValueList<PanelMenuItemInfo> items;
+ for (BaseContainer::Iterator it = containers.begin(); it != containers.end(); ++it)
+ {
+ items.append(PanelMenuItemInfo((*it)->icon(), (*it)->visibleName(), id));
+ id++;
+ }
+
+ qHeapSort(items);
+
+ for (QValueList<PanelMenuItemInfo>::iterator it = items.begin();
+ it != items.end();
+ ++it)
+ {
+ (*it).plug(this);
+ }
+
+ if (containers.count() > 1)
+ {
+ insertSeparator();
+ insertItem(i18n("All"), this, SLOT(slotRemoveAll()), 0, id);
+ }
+}
+
+void PanelRemoveButtonMenu::slotExec( int id )
+{
+ if (containers.at(id) != containers.end())
+ {
+ containerArea->removeContainer(*containers.at(id));
+ }
+}
+
+PanelRemoveButtonMenu::~PanelRemoveButtonMenu()
+{
+}
+
+void PanelRemoveButtonMenu::slotRemoveAll()
+{
+ containerArea->removeContainers(containers);
+}
diff --git a/kicker/kicker/ui/removebutton_mnu.h b/kicker/kicker/ui/removebutton_mnu.h
new file mode 100644
index 000000000..20d29c171
--- /dev/null
+++ b/kicker/kicker/ui/removebutton_mnu.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __removebutton_mnu_h__
+#define __removebutton_mnu_h__
+
+#include <qptrlist.h>
+#include <qpopupmenu.h>
+
+#include "appletinfo.h"
+#include "container_base.h"
+
+class ContainerArea;
+
+class PanelRemoveButtonMenu : public QPopupMenu
+{
+ Q_OBJECT
+
+public:
+ PanelRemoveButtonMenu( ContainerArea *cArea, QWidget *parent=0, const char *name=0 );
+ ~PanelRemoveButtonMenu();
+
+protected slots:
+ void slotExec( int id );
+ void slotAboutToShow();
+ void slotRemoveAll();
+
+private:
+ void addToContainers(const QString& type);
+
+ BaseContainer::List containers;
+ ContainerArea* containerArea;
+};
+
+#endif
diff --git a/kicker/kicker/ui/removecontainer_mnu.cpp b/kicker/kicker/ui/removecontainer_mnu.cpp
new file mode 100644
index 000000000..ddce1f2df
--- /dev/null
+++ b/kicker/kicker/ui/removecontainer_mnu.cpp
@@ -0,0 +1,61 @@
+/*****************************************************************
+
+Copyreght (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <klocale.h>
+#include <kglobal.h>
+
+#include "removecontainer_mnu.h"
+#include "removecontainer_mnu.moc"
+
+#include "removeapplet_mnu.h"
+#include "removebutton_mnu.h"
+#include "removeextension_mnu.h"
+
+#include "kicker.h"
+#include "extensionmanager.h"
+#include "containerarea.h"
+
+RemoveContainerMenu::RemoveContainerMenu( ContainerArea* cArea,
+ QWidget *parent, const char *name)
+ : QPopupMenu( parent, name ), containerArea( cArea )
+{
+ appletId = insertItem(i18n("&Applet"),
+ new PanelRemoveAppletMenu(containerArea, this));
+ buttonId = insertItem(i18n("Appli&cation"),
+ new PanelRemoveButtonMenu( containerArea, this ) );
+ adjustSize();
+ connect( this, SIGNAL( aboutToShow() ), SLOT( slotAboutToShow() ) );
+}
+
+RemoveContainerMenu::~RemoveContainerMenu()
+{
+}
+
+void RemoveContainerMenu::slotAboutToShow()
+{
+ setItemEnabled(appletId, containerArea->containerCount("Applet") > 0 ||
+ containerArea->containerCount("Special Button") > 0);
+ setItemEnabled(buttonId, (containerArea->containerCount("ServiceMenuButton") +
+ containerArea->containerCount("ServiceButton")) > 0);
+}
+
diff --git a/kicker/kicker/ui/removecontainer_mnu.h b/kicker/kicker/ui/removecontainer_mnu.h
new file mode 100644
index 000000000..9d7142671
--- /dev/null
+++ b/kicker/kicker/ui/removecontainer_mnu.h
@@ -0,0 +1,47 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __removecontainer_mnu_h__
+#define __removecontainer_mnu_h__
+
+#include <qpopupmenu.h>
+
+class ContainerArea;
+
+class RemoveContainerMenu : public QPopupMenu
+{
+ Q_OBJECT
+
+public:
+ RemoveContainerMenu(ContainerArea* cArea, QWidget *parent=0, const char *name=0);
+ ~RemoveContainerMenu();
+
+protected slots:
+ void slotAboutToShow();
+
+private:
+ int appletId, buttonId;
+ ContainerArea *containerArea;
+};
+
+#endif
diff --git a/kicker/kicker/ui/removeextension_mnu.cpp b/kicker/kicker/ui/removeextension_mnu.cpp
new file mode 100644
index 000000000..7f7d09075
--- /dev/null
+++ b/kicker/kicker/ui/removeextension_mnu.cpp
@@ -0,0 +1,108 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <klocale.h>
+#include <kglobal.h>
+
+#include "kicker.h"
+#include "extensionmanager.h"
+#include "pluginmanager.h"
+
+#include "panelmenuiteminfo.h"
+#include "removeextension_mnu.h"
+#include "removeextension_mnu.moc"
+
+static const int REMOVEALLID = 1000;
+
+PanelRemoveExtensionMenu::PanelRemoveExtensionMenu( QWidget *parent, const char *name )
+ : QPopupMenu( parent, name )
+{
+ connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
+ connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
+}
+
+PanelRemoveExtensionMenu::PanelRemoveExtensionMenu()
+{
+}
+
+void PanelRemoveExtensionMenu::slotAboutToShow()
+{
+ int id = 0;
+
+ clear();
+ m_containers = ExtensionManager::the()->containers();
+ QValueList<PanelMenuItemInfo> items;
+
+ ExtensionList::iterator itEnd = m_containers.end();
+ for (ExtensionList::iterator it = m_containers.begin(); it != itEnd; ++it)
+ {
+ const AppletInfo info = (*it)->info();
+ QString name = info.name().replace("&", "&&");
+ switch ((*it)->position())
+ {
+ case KPanelExtension::Top:
+ name = i18n("%1 (Top)").arg(name);
+ break;
+ case KPanelExtension::Right:
+ name = i18n("%1 (Right)").arg(name);
+ break;
+ case KPanelExtension::Bottom:
+ name = i18n("%1 (Bottom)").arg(name);
+ break;
+ case KPanelExtension::Left:
+ name = i18n("%1 (Left)").arg(name);
+ break;
+ case KPanelExtension::Floating:
+ name = i18n("%1 (Floating)").arg(name);
+ break;
+ }
+ items.append(PanelMenuItemInfo(QString::null, name, id));
+ ++id;
+ }
+
+ qHeapSort(items);
+ QValueList<PanelMenuItemInfo>::iterator itEnd2 = items.end();
+ for (QValueList<PanelMenuItemInfo>::iterator it = items.begin(); it != itEnd2; ++it)
+ {
+ (*it).plug(this);
+ }
+
+ if (m_containers.count() > 1)
+ {
+ insertSeparator();
+ insertItem(i18n("All"), REMOVEALLID);
+ }
+}
+
+void PanelRemoveExtensionMenu::slotExec( int id )
+{
+ if (id == REMOVEALLID)
+ {
+ ExtensionManager::the()->removeAllContainers();
+ }
+ else if (m_containers.at(id) != m_containers.end())
+ {
+ ExtensionManager::the()->removeContainer(*m_containers.at(id));
+ }
+}
+
diff --git a/kicker/kicker/ui/removeextension_mnu.h b/kicker/kicker/ui/removeextension_mnu.h
new file mode 100644
index 000000000..bc0e08b00
--- /dev/null
+++ b/kicker/kicker/ui/removeextension_mnu.h
@@ -0,0 +1,48 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __removeextension_mnu_h__
+#define __removeextension_mnu_h__
+
+#include <qptrlist.h>
+#include <qpopupmenu.h>
+
+#include "container_extension.h"
+
+class PanelRemoveExtensionMenu : public QPopupMenu
+{
+ Q_OBJECT
+
+public:
+ PanelRemoveExtensionMenu( QWidget *parent=0, const char *name=0 );
+ PanelRemoveExtensionMenu();
+
+protected slots:
+ void slotExec( int id );
+ void slotAboutToShow();
+
+private:
+ ExtensionList m_containers;
+};
+
+#endif
diff --git a/kicker/kicker/ui/service_mnu.cpp b/kicker/kicker/ui/service_mnu.cpp
new file mode 100644
index 000000000..a59c14ce8
--- /dev/null
+++ b/kicker/kicker/ui/service_mnu.cpp
@@ -0,0 +1,823 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <typeinfo>
+#include <qcursor.h>
+#include <qbitmap.h>
+#include <qpixmap.h>
+#include <qimage.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kprocess.h>
+#include <krun.h>
+#include <kservicegroup.h>
+#include <ksycoca.h>
+#include <ksycocaentry.h>
+#include <kservice.h>
+#include <kurldrag.h>
+#include <kio/job.h>
+
+#include "global.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "menumanager.h"
+#include "popupmenutitle.h"
+#include "panelbutton.h"
+#include "recentapps.h"
+#include "service_mnu.h"
+#include "service_mnu.moc"
+
+PanelServiceMenu::PanelServiceMenu(const QString & label, const QString & relPath, QWidget * parent,
+ const char * name, bool addmenumode, const QString & insertInlineHeader)
+ : KPanelMenu(label, parent, name),
+ relPath_(relPath),
+ insertInlineHeader_( insertInlineHeader ),
+ clearOnClose_(false),
+ addmenumode_(addmenumode),
+ popupMenu_(0)
+{
+ excludeNoDisplay_=true;
+
+ connect(KSycoca::self(), SIGNAL(databaseChanged()),
+ SLOT(slotClearOnClose()));
+ connect(this, SIGNAL(aboutToHide()), this, SLOT(slotClose()));
+}
+
+PanelServiceMenu::~PanelServiceMenu()
+{
+ clearSubmenus();
+}
+
+
+void PanelServiceMenu::setExcludeNoDisplay( bool flag )
+{
+ excludeNoDisplay_=flag;
+}
+
+void PanelServiceMenu::showMenu()
+{
+ activateParent(QString::null);
+}
+
+// the initialization is split in initialize() and
+// doInitialize() so that a subclass does not have to
+// redo all the service parsing (see e.g. kicker/menuext/prefmenu)
+
+void PanelServiceMenu::initialize()
+{
+ if (initialized()) return;
+
+ setInitialized(true);
+ entryMap_.clear();
+ clear();
+
+ clearSubmenus();
+ doInitialize();
+}
+
+void PanelServiceMenu::fillMenu(KServiceGroup::Ptr& _root,
+ KServiceGroup::List& _list,
+ const QString& /* _relPath */,
+ int& id)
+{
+ QStringList suppressGenericNames = _root->suppressGenericNames();
+
+ KServiceGroup::List::ConstIterator it = _list.begin();
+ bool separatorNeeded = false;
+ for (; it != _list.end(); ++it)
+ {
+ KSycocaEntry * e = *it;
+
+ if (e->isType(KST_KServiceGroup))
+ {
+
+ KServiceGroup::Ptr g(static_cast<KServiceGroup *>(e));
+ QString groupCaption = g->caption();
+
+ // Avoid adding empty groups.
+ KServiceGroup::Ptr subMenuRoot = KServiceGroup::group(g->relPath());
+
+ int nbChildCount = subMenuRoot->childCount();
+ if (nbChildCount == 0 && !g->showEmptyMenu())
+ {
+ continue;
+ }
+
+ QString inlineHeaderName = g->showInlineHeader() ? groupCaption : "";
+ // Item names may contain ampersands. To avoid them being converted
+ // to accelerators, replace them with two ampersands.
+ groupCaption.replace("&", "&&");
+
+ if ( nbChildCount == 1 && g->allowInline() && g->inlineAlias())
+ {
+ KServiceGroup::Ptr element = KServiceGroup::group(g->relPath());
+ if ( element )
+ {
+ //just one element
+ KServiceGroup::List listElement = element->entries(true, excludeNoDisplay_, true, KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName || KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly);
+ KSycocaEntry * e1 = *( listElement.begin() );
+ if ( e1->isType( KST_KService ) )
+ {
+ if (separatorNeeded)
+ {
+ insertSeparator();
+ separatorNeeded = false;
+ }
+
+ KService::Ptr s(static_cast<KService *>(e1));
+ insertMenuItem(s, id++, -1, &suppressGenericNames);
+ continue;
+ }
+ }
+ }
+
+ if (g->allowInline() && ((nbChildCount <= g->inlineValue() ) || (g->inlineValue() == 0)))
+ {
+ //inline all entries
+ KServiceGroup::Ptr rootElement = KServiceGroup::group(g->relPath());
+
+ if (!rootElement || !rootElement->isValid())
+ {
+ break;
+ }
+
+ KServiceGroup::List listElement = rootElement->entries(true, excludeNoDisplay_, true, KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName || KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly);
+
+ if ( !g->inlineAlias() && !inlineHeaderName.isEmpty() )
+ {
+ int mid = insertItem(new PopupMenuTitle(inlineHeaderName, font()), id + 1, id);
+ id++;
+ setItemEnabled( mid, false );
+ }
+
+ fillMenu( rootElement, listElement, g->relPath(), id );
+ continue;
+ }
+
+ // Ignore dotfiles.
+ if ((g->name().at(0) == '.'))
+ {
+ continue;
+ }
+
+ PanelServiceMenu * m =
+ newSubMenu(g->name(), g->relPath(), this, g->name().utf8(), inlineHeaderName);
+ m->setCaption(groupCaption);
+
+ QIconSet iconset = KickerLib::menuIconSet(g->icon());
+
+ if (separatorNeeded)
+ {
+ insertSeparator();
+ separatorNeeded = false;
+ }
+
+ int newId = insertItem(iconset, groupCaption, m, id++);
+ entryMap_.insert(newId, static_cast<KSycocaEntry*>(g));
+ // We have to delete the sub menu our selves! (See Qt docs.)
+ subMenus.append(m);
+ }
+ else if (e->isType(KST_KService))
+ {
+ if (separatorNeeded)
+ {
+ insertSeparator();
+ separatorNeeded = false;
+ }
+
+ KService::Ptr s(static_cast<KService *>(e));
+ insertMenuItem(s, id++, -1, &suppressGenericNames);
+ }
+ else if (e->isType(KST_KServiceSeparator))
+ {
+ separatorNeeded = true;
+ }
+ }
+#if 0
+ // WABA: tear off handles don't work together with dynamically updated
+ // menus. We can't update the menu while torn off, and we don't know
+ // when it is torn off.
+ if ( count() > 0 && !relPath_.isEmpty() )
+ if (KGlobalSettings::insertTearOffHandle())
+ insertTearOffHandle();
+#endif
+}
+
+void PanelServiceMenu::clearSubmenus()
+{
+ for (PopupMenuList::const_iterator it = subMenus.constBegin();
+ it != subMenus.constEnd();
+ ++it)
+ {
+ delete *it;
+ }
+ subMenus.clear();
+}
+
+void PanelServiceMenu::doInitialize()
+{
+
+ // Set the startposition outside the panel, so there is no drag initiated
+ // when we use drag and click to select items. A drag is only initiated when
+ // you click to open the menu, and then press and drag an item.
+ startPos_ = QPoint(-1,-1);
+
+ // We ask KSycoca to give us all services (sorted).
+ KServiceGroup::Ptr root = KServiceGroup::group(relPath_);
+
+ if (!root || !root->isValid())
+ return;
+
+ KServiceGroup::List list = root->entries(true, excludeNoDisplay_, true, KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName || KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly);
+
+ if (list.isEmpty()) {
+ setItemEnabled(insertItem(i18n("No Entries")), false);
+ return;
+ }
+
+ int id = serviceMenuStartId();
+
+ if (addmenumode_) {
+ int mid = insertItem(KickerLib::menuIconSet("ok"), i18n("Add This Menu"), id++);
+ entryMap_.insert(mid, static_cast<KSycocaEntry*>(root));
+
+ if (relPath_ == "")
+ {
+ insertItem(KickerLib::menuIconSet("exec"), i18n("Add Non-KDE Application"),
+ this, SLOT(addNonKDEApp()));
+ }
+
+ if (list.count() > 0) {
+ insertSeparator();
+ id++;
+ }
+ }
+ if ( !insertInlineHeader_.isEmpty() )
+ {
+ int mid = insertItem(new PopupMenuTitle(insertInlineHeader_, font()), -1, 0);
+ setItemEnabled( mid, false );
+ }
+ fillMenu( root, list, relPath_, id );
+}
+
+void PanelServiceMenu::configChanged()
+{
+ deinitialize();
+}
+
+void PanelServiceMenu::insertMenuItem(KService::Ptr & s, int nId,
+ int nIndex/*= -1*/,
+ const QStringList *suppressGenericNames /* = 0 */,
+ const QString & aliasname)
+{
+ QString serviceName = (aliasname.isEmpty() ? s->name() : aliasname).simplifyWhiteSpace();
+ QString comment = s->genericName().simplifyWhiteSpace();
+
+ if (!comment.isEmpty())
+ {
+ if (KickerSettings::menuEntryFormat() == KickerSettings::NameAndDescription)
+ {
+ if ((!suppressGenericNames ||
+ !suppressGenericNames->contains(s->untranslatedGenericName())) &&
+ serviceName.find(comment, 0, true) == -1)
+ {
+ if (comment.find(serviceName, 0, true) == -1)
+ {
+ serviceName = i18n("Entries in K-menu: %1 app name, %2 description", "%1 - %2").arg(serviceName, comment);
+ }
+ else
+ {
+ serviceName = comment;
+ }
+ }
+ }
+ else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName)
+ {
+ serviceName = i18n("Entries in K-menu: %1 description, %2 app name", "%1 (%2)").arg(comment, serviceName);
+ }
+ else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly)
+ {
+ serviceName = comment;
+ }
+ }
+
+ // restrict menu entries to a sane length
+ if ( serviceName.length() > 60 ) {
+ serviceName.truncate( 57 );
+ serviceName += "...";
+ }
+
+ // check for NoDisplay
+ if (s->noDisplay())
+ return;
+
+ // ignore dotfiles.
+ if ((serviceName.at(0) == '.'))
+ return;
+
+ // item names may contain ampersands. To avoid them being converted
+ // to accelerators, replace them with two ampersands.
+ serviceName.replace("&", "&&");
+
+ int newId = insertItem(KickerLib::menuIconSet(s->icon()), serviceName, nId, nIndex);
+ entryMap_.insert(newId, static_cast<KSycocaEntry*>(s));
+}
+
+void PanelServiceMenu::activateParent(const QString &child)
+{
+ PanelServiceMenu *parentMenu = dynamic_cast<PanelServiceMenu*>(parent());
+ if (parentMenu)
+ {
+ parentMenu->activateParent(relPath_);
+ }
+ else
+ {
+ PanelPopupButton *kButton = MenuManager::the()->findKButtonFor(this);
+ if (kButton)
+ {
+ adjustSize();
+ kButton->showMenu();
+ }
+ else
+ {
+ show();
+ }
+ }
+
+ if (!child.isEmpty())
+ {
+ EntryMap::Iterator mapIt;
+ for ( mapIt = entryMap_.begin(); mapIt != entryMap_.end(); ++mapIt )
+ {
+ KServiceGroup *g = dynamic_cast<KServiceGroup *>(static_cast<KSycocaEntry*>(mapIt.data()));
+
+ // if the dynamic_cast fails, we are looking at a KService entry
+ if (g && (g->relPath() == child))
+ {
+ activateItemAt(indexOf(mapIt.key()));
+ return;
+ }
+ }
+ }
+}
+
+bool PanelServiceMenu::highlightMenuItem( const QString &menuItemId )
+{
+ initialize();
+
+ // Check menu itself
+ EntryMap::Iterator mapIt;
+ for ( mapIt = entryMap_.begin(); mapIt != entryMap_.end(); ++mapIt )
+ {
+ // Skip recent files menu
+ if (mapIt.key() >= serviceMenuEndId())
+ {
+ continue;
+ }
+ KService *s = dynamic_cast<KService *>(
+ static_cast<KSycocaEntry*>(mapIt.data()));
+ if (s && (s->menuId() == menuItemId))
+ {
+ activateParent(QString::null);
+ int index = indexOf(mapIt.key());
+ setActiveItem(index);
+
+ // Warp mouse pointer to location of active item
+ QRect r = itemGeometry(index);
+ QCursor::setPos(mapToGlobal(QPoint(r.x()+ r.width() - 15,
+ r.y() + r.height() - 5)));
+ return true;
+ }
+ }
+
+ for(PopupMenuList::iterator it = subMenus.begin();
+ it != subMenus.end();
+ ++it)
+ {
+ PanelServiceMenu *serviceMenu = dynamic_cast<PanelServiceMenu*>(*it);
+ if (serviceMenu && serviceMenu->highlightMenuItem(menuItemId))
+ return true;
+ }
+ return false;
+}
+
+void PanelServiceMenu::slotExec(int id)
+{
+ if (!entryMap_.contains(id))
+ {
+ return;
+ }
+
+ KSycocaEntry * e = entryMap_[id];
+
+ kapp->propagateSessionManager();
+
+ KService::Ptr service = static_cast<KService *>(e);
+ KApplication::startServiceByDesktopPath(service->desktopEntryPath(),
+ QStringList(), 0, 0, 0, "", true);
+
+ updateRecentlyUsedApps(service);
+ startPos_ = QPoint(-1,-1);
+}
+
+void PanelServiceMenu::mousePressEvent(QMouseEvent * ev)
+{
+ startPos_ = ev->pos();
+ KPanelMenu::mousePressEvent(ev);
+}
+
+void PanelServiceMenu::mouseReleaseEvent(QMouseEvent * ev)
+{
+ if (ev->button() == RightButton && !Kicker::the()->isKioskImmutable())
+ {
+ int id = idAt( ev->pos() );
+
+ if (id < serviceMenuStartId())
+ {
+ return;
+ }
+
+ if (!entryMap_.contains(id))
+ {
+ kdDebug(1210) << "Cannot find service with menu id " << id << endl;
+ return;
+ }
+
+ contextKSycocaEntry_ = entryMap_[id];
+
+ delete popupMenu_;
+ popupMenu_ = new KPopupMenu(this);
+ connect(popupMenu_, SIGNAL(activated(int)), SLOT(slotContextMenu(int)));
+ bool hasEntries = false;
+
+ switch (contextKSycocaEntry_->sycocaType())
+ {
+ case KST_KService:
+ if (kapp->authorize("editable_desktop_icons"))
+ {
+ hasEntries = true;
+ popupMenu_->insertItem(SmallIconSet("desktop"),
+ i18n("Add Item to Desktop"), AddItemToDesktop);
+ }
+ if (kapp->authorizeKAction("kicker_rmb") && !Kicker::the()->isImmutable())
+ {
+ hasEntries = true;
+ popupMenu_->insertItem(SmallIconSet("kicker"),
+ i18n("Add Item to Main Panel"), AddItemToPanel);
+ }
+ if (kapp->authorizeKAction("menuedit"))
+ {
+ hasEntries = true;
+ popupMenu_->insertItem(SmallIconSet("kmenuedit"),
+ i18n("Edit Item"), EditItem);
+ }
+ if (kapp->authorize("run_command"))
+ {
+ hasEntries = true;
+ popupMenu_->insertItem(SmallIconSet("run"),
+ i18n("Put Into Run Dialog"), PutIntoRunDialog);
+ }
+ break;
+
+ case KST_KServiceGroup:
+ if (kapp->authorize("editable_desktop_icons"))
+ {
+ hasEntries = true;
+ popupMenu_->insertItem(SmallIconSet("desktop"),
+ i18n("Add Menu to Desktop"), AddMenuToDesktop);
+ }
+ if (kapp->authorizeKAction("kicker_rmb") && !Kicker::the()->isImmutable())
+ {
+ hasEntries = true;
+ popupMenu_->insertItem(SmallIconSet("kicker"),
+ i18n("Add Menu to Main Panel"), AddMenuToPanel);
+ }
+ if (kapp->authorizeKAction("menuedit"))
+ {
+ hasEntries = true;
+ popupMenu_->insertItem(SmallIconSet("kmenuedit"),
+ i18n("Edit Menu"), EditMenu);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (hasEntries)
+ {
+ popupMenu_->popup(this->mapToGlobal(ev->pos()));
+ return;
+ }
+ }
+
+ delete popupMenu_;
+ popupMenu_ = 0;
+
+ KPanelMenu::mouseReleaseEvent(ev);
+}
+
+extern int kicker_screen_number;
+
+void PanelServiceMenu::slotContextMenu(int selected)
+{
+ KProcess *proc;
+ KService::Ptr service;
+ KServiceGroup::Ptr g;
+ QByteArray ba;
+ QDataStream ds(ba, IO_WriteOnly);
+
+ KURL src,dest;
+ KIO::CopyJob *job;
+ KDesktopFile *df;
+
+ switch (selected) {
+ case AddItemToDesktop:
+ service = static_cast<KService *>(contextKSycocaEntry_);
+
+ src.setPath( KGlobal::dirs()->findResource( "apps", service->desktopEntryPath() ) );
+ dest.setPath( KGlobalSettings::desktopPath() );
+ dest.setFileName( src.fileName() );
+
+ job = KIO::copyAs( src, dest );
+ job->setDefaultPermissions( true );
+ break;
+
+ case AddItemToPanel: {
+ QCString appname = "kicker";
+ if ( kicker_screen_number )
+ appname.sprintf("kicker-screen-%d", kicker_screen_number);
+ service = static_cast<KService *>(contextKSycocaEntry_);
+ kapp->dcopClient()->send(appname, "Panel", "addServiceButton(QString)", service->desktopEntryPath());
+ break;
+ }
+
+ case EditItem:
+ proc = new KProcess(this);
+ *proc << KStandardDirs::findExe(QString::fromLatin1("kmenuedit"));
+ *proc << "/"+relPath_ << static_cast<KService *>(contextKSycocaEntry_)->menuId();
+ proc->start();
+ break;
+
+ case PutIntoRunDialog: {
+ close();
+ QCString appname = "kdesktop";
+ if ( kicker_screen_number )
+ appname.sprintf("kdesktop-screen-%d", kicker_screen_number);
+ service = static_cast<KService *>(contextKSycocaEntry_);
+ kapp->updateRemoteUserTimestamp( appname );
+ kapp->dcopClient()->send(appname, "default", "popupExecuteCommand(QString)", service->exec());
+ break;
+ }
+
+ case AddMenuToDesktop:
+ g = static_cast<KServiceGroup *>(contextKSycocaEntry_);
+ dest.setPath( KGlobalSettings::desktopPath() );
+ dest.setFileName( g->caption() );
+
+ df = new KDesktopFile( dest.path() );
+ df->writeEntry( "Icon", g->icon() );
+ df->writePathEntry( "URL", "programs:/"+g->name() );
+ df->writeEntry( "Name", g->caption() );
+ df->writeEntry( "Type", "Link" );
+ df->sync();
+ delete df;
+
+ break;
+
+ case AddMenuToPanel: {
+ QCString appname = "kicker";
+ if ( kicker_screen_number )
+ appname.sprintf("kicker-screen-%d", kicker_screen_number);
+
+ g = static_cast<KServiceGroup *>(contextKSycocaEntry_);
+ ds << "foo" << g->relPath();
+ kapp->dcopClient()->send("kicker", "Panel", "addServiceMenuButton(QString,QString)", ba);
+ break;
+ }
+
+ case EditMenu:
+ proc = new KProcess(this);
+ *proc << KStandardDirs::findExe(QString::fromLatin1("kmenuedit"));
+ *proc << "/"+static_cast<KServiceGroup *>(contextKSycocaEntry_)->relPath();
+ proc->start();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void PanelServiceMenu::mouseMoveEvent(QMouseEvent * ev)
+{
+ KPanelMenu::mouseMoveEvent(ev);
+
+ if (Kicker::the()->isKioskImmutable())
+ return;
+
+ if ( (ev->state() & LeftButton ) != LeftButton )
+ return;
+
+ QPoint p = ev->pos() - startPos_;
+ if (p.manhattanLength() <= QApplication::startDragDistance() )
+ return;
+
+ int id = idAt(startPos_);
+
+ // Don't drag items we didn't create.
+ if (id < serviceMenuStartId())
+ return;
+
+ if (!entryMap_.contains(id)) {
+ kdDebug(1210) << "Cannot find service with menu id " << id << endl;
+ return;
+ }
+
+ KSycocaEntry * e = entryMap_[id];
+
+ QPixmap icon;
+ KURL url;
+
+ switch (e->sycocaType()) {
+
+ case KST_KService:
+ {
+ icon = static_cast<KService *>(e)->pixmap(KIcon::Small);
+ QString filePath = static_cast<KService *>(e)->desktopEntryPath();
+ if (filePath[0] != '/')
+ {
+ filePath = locate("apps", filePath);
+ }
+ url.setPath(filePath);
+ break;
+ }
+
+ case KST_KServiceGroup:
+ {
+ icon = KGlobal::iconLoader()
+ ->loadIcon(static_cast<KServiceGroup *>(e)->icon(), KIcon::Small);
+ url = "programs:/" + static_cast<KServiceGroup *>(e)->relPath();
+ break;
+ }
+
+ default:
+ {
+ return;
+ break;
+ }
+ }
+
+ // If the path to the desktop file is relative, try to get the full
+ // path from KStdDirs.
+
+ KURLDrag *d = new KURLDrag(KURL::List(url), this);
+ connect(d, SIGNAL(destroyed()), this, SLOT(slotDragObjectDestroyed()));
+ d->setPixmap(icon);
+ d->dragCopy();
+
+ // Set the startposition outside the panel, so there is no drag initiated
+ // when we use drag and click to select items. A drag is only initiated when
+ // you click to open the menu, and then press and drag an item.
+ startPos_ = QPoint(-1,-1);
+}
+
+void PanelServiceMenu::dragEnterEvent(QDragEnterEvent *event)
+{
+ // Set the DragObject's target to this widget. This is needed because the
+ // widget doesn't accept drops, but we want to determine if the drag object
+ // is dropped on it. This avoids closing on accidental drags. If this
+ // widget accepts drops in the future, these lines can be removed.
+ if (event->source() == this)
+ {
+ KURLDrag::setTarget(this);
+ }
+ event->ignore();
+}
+
+void PanelServiceMenu::dragLeaveEvent(QDragLeaveEvent *)
+{
+ // see PanelServiceMenu::dragEnterEvent why this is nescessary
+ if (!frameGeometry().contains(QCursor::pos()))
+ {
+ KURLDrag::setTarget(0);
+ }
+}
+
+void PanelServiceMenu::slotDragObjectDestroyed()
+{
+ if (KURLDrag::target() != this)
+ {
+ // we need to re-enter the event loop before calling close() here
+ // this gets called _before_ the drag object is destroyed, so we are
+ // still in its event loop. closing the menu before that event loop is
+ // exited may result in getting hung up in it which in turn prevents
+ // the execution of any code after the original exec() statement
+ // though the panels themselves continue on otherwise normally
+ // (we just have some sort of nested event loop)
+ QTimer::singleShot(0, this, SLOT(close()));
+ }
+}
+
+PanelServiceMenu *PanelServiceMenu::newSubMenu(const QString & label, const QString & relPath,
+ QWidget * parent, const char * name, const QString& _inlineHeader)
+{
+ return new PanelServiceMenu(label, relPath, parent, name, false,_inlineHeader);
+}
+
+void PanelServiceMenu::slotClearOnClose()
+{
+ if (!initialized()) return;
+
+ if (!isVisible()){
+ clearOnClose_ = false;
+ slotClear();
+ } else {
+ clearOnClose_ = true;
+ }
+}
+
+void PanelServiceMenu::slotClose()
+{
+ if (clearOnClose_)
+ {
+ clearOnClose_ = false;
+ slotClear();
+ }
+
+ delete popupMenu_;
+ popupMenu_ = 0;
+}
+
+void PanelServiceMenu::slotClear()
+{
+ if (isVisible())
+ {
+ // QPopupMenu's aboutToHide() is emitted before the popup is really hidden,
+ // and also before a click in the menu is handled, so do the clearing
+ // only after that has been handled
+ QTimer::singleShot(100, this, SLOT(slotClear()));
+ return;
+ }
+
+ entryMap_.clear();
+ KPanelMenu::slotClear();
+
+ for (PopupMenuList::iterator it = subMenus.begin();
+ it != subMenus.end();
+ ++it)
+ {
+ delete *it;
+ }
+ subMenus.clear();
+}
+
+void PanelServiceMenu::selectFirstItem()
+{
+ setActiveItem(indexOf(serviceMenuStartId()));
+}
+
+// updates "recent" section of KMenu
+void PanelServiceMenu::updateRecentlyUsedApps(KService::Ptr &service)
+{
+ QString strItem(service->desktopEntryPath());
+
+ // don't add an item from root kmenu level
+ if (!strItem.contains('/'))
+ {
+ return;
+ }
+
+ // add it into recent apps list
+ RecentlyLaunchedApps::the().appLaunched(strItem);
+ RecentlyLaunchedApps::the().save();
+ RecentlyLaunchedApps::the().m_bNeedToUpdate = true;
+}
+
diff --git a/kicker/kicker/ui/service_mnu.h b/kicker/kicker/ui/service_mnu.h
new file mode 100644
index 000000000..9e28acd3f
--- /dev/null
+++ b/kicker/kicker/ui/service_mnu.h
@@ -0,0 +1,129 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef SERVICE_MENU_H
+#define SERVICE_MENU_H
+
+#include <qmap.h>
+#include <qvaluevector.h>
+
+#include <ksycocaentry.h>
+#include <kservice.h>
+#include <kpanelmenu.h>
+#include <kservicegroup.h>
+/**
+ * PanelServiceMenu is filled with KDE services and service groups. The sycoca
+ * database is queried and the hierarchical structure built by creating child
+ * menus of type PanelServiceMenu, so the creation is recursive.
+ *
+ * The entries are sorted alphabetically and groups come before services.
+ *
+ * @author Rik Hemsley <rik@kde.org>
+ */
+
+typedef QMap<int, KSycocaEntry::Ptr> EntryMap;
+typedef QValueVector<QPopupMenu*> PopupMenuList;
+
+class KDE_EXPORT PanelServiceMenu : public KPanelMenu
+{
+ Q_OBJECT
+
+public:
+ PanelServiceMenu(const QString & label, const QString & relPath,
+ QWidget* parent = 0, const char* name = 0,
+ bool addmenumode = false,
+ const QString &insertInlineHeader = QString::null);
+
+ virtual ~PanelServiceMenu();
+
+ QString relPath() { return relPath_; }
+
+ void setExcludeNoDisplay( bool flag );
+
+ virtual void showMenu();
+ bool highlightMenuItem( const QString &menuId );
+ void selectFirstItem();
+
+private:
+ void fillMenu( KServiceGroup::Ptr &_root, KServiceGroup::List &_list,
+ const QString &_relPath, int & id );
+
+protected slots:
+ virtual void initialize();
+ virtual void slotExec(int id);
+ virtual void slotClearOnClose();
+ virtual void slotClear();
+ virtual void configChanged();
+ virtual void slotClose();
+ void slotDragObjectDestroyed();
+
+ // for use in Add Applicaton To Panel
+ virtual void addNonKDEApp() {}
+
+protected:
+ void insertMenuItem(KService::Ptr & s, int nId, int nIndex = -1,
+ const QStringList *suppressGenericNames=0,
+ const QString &aliasname = QString::null);
+ virtual PanelServiceMenu * newSubMenu(const QString & label,
+ const QString & relPath,
+ QWidget * parent, const char * name,
+ const QString & _inlineHeader =
+ QString::null);
+
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ virtual void dragLeaveEvent(QDragLeaveEvent *);
+ virtual void updateRecentlyUsedApps(KService::Ptr &s);
+ void activateParent(const QString &child);
+ int serviceMenuStartId() { return 4242; }
+ int serviceMenuEndId() { return 5242; }
+ virtual void clearSubmenus();
+ void doInitialize();
+
+ QString relPath_;
+
+ EntryMap entryMap_;
+
+ bool loaded_;
+ bool excludeNoDisplay_;
+ QString insertInlineHeader_;
+ QPopupMenu * opPopup_;
+ bool clearOnClose_;
+ bool addmenumode_;
+ QPoint startPos_;
+ PopupMenuList subMenus;
+
+private slots:
+ void slotContextMenu(int);
+
+private:
+ enum ContextMenuEntry { AddItemToPanel, EditItem, AddMenuToPanel, EditMenu,
+ AddItemToDesktop, AddMenuToDesktop, PutIntoRunDialog };
+ KPopupMenu* popupMenu_;
+ KSycocaEntry* contextKSycocaEntry_;
+ void readConfig();
+ };
+
+#endif // SERVICE_MENU_H