summaryrefslogtreecommitdiffstats
path: root/kicker/applets
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/applets
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/applets')
-rw-r--r--kicker/applets/Makefile.am1
-rw-r--r--kicker/applets/clock/Makefile.am29
-rw-r--r--kicker/applets/clock/analog.ui344
-rw-r--r--kicker/applets/clock/clock.cpp1871
-rw-r--r--kicker/applets/clock/clock.h348
-rw-r--r--kicker/applets/clock/clockapplet.desktop151
-rw-r--r--kicker/applets/clock/clockapplet.kcfg191
-rw-r--r--kicker/applets/clock/datepicker.cpp87
-rw-r--r--kicker/applets/clock/datepicker.h49
-rw-r--r--kicker/applets/clock/digital.ui305
-rw-r--r--kicker/applets/clock/fuzzy.ui287
-rw-r--r--kicker/applets/clock/lcd.pngbin0 -> 237 bytes
-rw-r--r--kicker/applets/clock/prefs.kcfgc6
-rw-r--r--kicker/applets/clock/settings.ui515
-rw-r--r--kicker/applets/clock/zone.cpp180
-rw-r--r--kicker/applets/clock/zone.h62
-rw-r--r--kicker/applets/launcher/ChangeLog40
-rw-r--r--kicker/applets/launcher/Makefile.am27
-rw-r--r--kicker/applets/launcher/ToDo8
-rw-r--r--kicker/applets/launcher/configdlg.cpp101
-rw-r--r--kicker/applets/launcher/configdlg.h55
-rw-r--r--kicker/applets/launcher/configdlgbase.ui273
-rw-r--r--kicker/applets/launcher/easyvector.h147
-rw-r--r--kicker/applets/launcher/flowgridmanager.cpp316
-rw-r--r--kicker/applets/launcher/flowgridmanager.h99
-rw-r--r--kicker/applets/launcher/launcherapplet.kcfg77
-rw-r--r--kicker/applets/launcher/popularity.cpp424
-rw-r--r--kicker/applets/launcher/popularity.h127
-rw-r--r--kicker/applets/launcher/prefs.kcfgc6
-rw-r--r--kicker/applets/launcher/quickaddappsmenu.cpp67
-rw-r--r--kicker/applets/launcher/quickaddappsmenu.h51
-rw-r--r--kicker/applets/launcher/quickbutton.cpp322
-rw-r--r--kicker/applets/launcher/quickbutton.h124
-rw-r--r--kicker/applets/launcher/quickbuttongroup.h60
-rw-r--r--kicker/applets/launcher/quicklauncher.cpp1093
-rw-r--r--kicker/applets/launcher/quicklauncher.desktop140
-rw-r--r--kicker/applets/launcher/quicklauncher.h138
-rw-r--r--kicker/applets/lockout/Makefile.am18
-rw-r--r--kicker/applets/lockout/README4
-rw-r--r--kicker/applets/lockout/lockout.cpp278
-rw-r--r--kicker/applets/lockout/lockout.desktop125
-rw-r--r--kicker/applets/lockout/lockout.h52
-rw-r--r--kicker/applets/media/Makefile.am20
-rw-r--r--kicker/applets/media/mediaapplet.cpp444
-rw-r--r--kicker/applets/media/mediaapplet.desktop130
-rw-r--r--kicker/applets/media/mediaapplet.h79
-rw-r--r--kicker/applets/media/mediumbutton.cpp202
-rw-r--r--kicker/applets/media/mediumbutton.h66
-rw-r--r--kicker/applets/media/preferencesdialog.cpp167
-rw-r--r--kicker/applets/media/preferencesdialog.h53
-rw-r--r--kicker/applets/menu/Makefile.am20
-rw-r--r--kicker/applets/menu/menuapplet.cpp511
-rw-r--r--kicker/applets/menu/menuapplet.desktop128
-rw-r--r--kicker/applets/menu/menuapplet.h258
-rw-r--r--kicker/applets/minipager/Makefile.am25
-rw-r--r--kicker/applets/minipager/minipagerapplet.desktop122
-rw-r--r--kicker/applets/minipager/pagerapplet.cpp906
-rw-r--r--kicker/applets/minipager/pagerapplet.h138
-rw-r--r--kicker/applets/minipager/pagerbutton.cpp824
-rw-r--r--kicker/applets/minipager/pagerbutton.h111
-rw-r--r--kicker/applets/minipager/pagersettings.kcfg58
-rw-r--r--kicker/applets/minipager/pagersettings.kcfgc4
-rw-r--r--kicker/applets/naughty/Makefile.am30
-rw-r--r--kicker/applets/naughty/NaughtyApplet.cpp223
-rw-r--r--kicker/applets/naughty/NaughtyApplet.h76
-rw-r--r--kicker/applets/naughty/NaughtyConfigDialog.cpp98
-rw-r--r--kicker/applets/naughty/NaughtyConfigDialog.h58
-rw-r--r--kicker/applets/naughty/NaughtyProcessMonitor.cpp475
-rw-r--r--kicker/applets/naughty/NaughtyProcessMonitor.h76
-rw-r--r--kicker/applets/naughty/configure.in.in5
-rw-r--r--kicker/applets/naughty/naughty-happy.pngbin0 -> 457 bytes
-rw-r--r--kicker/applets/naughty/naughty-sad.pngbin0 -> 440 bytes
-rw-r--r--kicker/applets/naughty/naughtyapplet.desktop131
-rw-r--r--kicker/applets/run/Makefile.am19
-rw-r--r--kicker/applets/run/runapplet.cpp294
-rw-r--r--kicker/applets/run/runapplet.desktop130
-rw-r--r--kicker/applets/run/runapplet.h65
-rw-r--r--kicker/applets/swallow/Makefile.am18
-rw-r--r--kicker/applets/swallow/prefwidget.cpp39
-rw-r--r--kicker/applets/swallow/prefwidget.h34
-rw-r--r--kicker/applets/swallow/prefwidgetbase.ui134
-rw-r--r--kicker/applets/swallow/swallow.cpp348
-rw-r--r--kicker/applets/swallow/swallow.h114
-rw-r--r--kicker/applets/swallow/swallowapplet.desktop142
-rw-r--r--kicker/applets/systemtray/Makefile.am24
-rw-r--r--kicker/applets/systemtray/systemtrayapplet.cpp1013
-rw-r--r--kicker/applets/systemtray/systemtrayapplet.desktop158
-rw-r--r--kicker/applets/systemtray/systemtrayapplet.h126
-rw-r--r--kicker/applets/taskbar/Makefile.am22
-rw-r--r--kicker/applets/taskbar/taskbarapplet.cpp126
-rw-r--r--kicker/applets/taskbar/taskbarapplet.desktop138
-rw-r--r--kicker/applets/taskbar/taskbarapplet.h56
-rw-r--r--kicker/applets/trash/Makefile.am21
-rw-r--r--kicker/applets/trash/trashapplet.cpp165
-rw-r--r--kicker/applets/trash/trashapplet.desktop138
-rw-r--r--kicker/applets/trash/trashapplet.h62
-rw-r--r--kicker/applets/trash/trashbutton.cpp154
-rw-r--r--kicker/applets/trash/trashbutton.h60
98 files changed, 17636 insertions, 0 deletions
diff --git a/kicker/applets/Makefile.am b/kicker/applets/Makefile.am
new file mode 100644
index 000000000..6079814ce
--- /dev/null
+++ b/kicker/applets/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = clock systemtray minipager taskbar run launcher naughty lockout menu media trash
diff --git a/kicker/applets/clock/Makefile.am b/kicker/applets/clock/Makefile.am
new file mode 100644
index 000000000..b87e0d8e7
--- /dev/null
+++ b/kicker/applets/clock/Makefile.am
@@ -0,0 +1,29 @@
+pic_DATA = lcd.png
+picdir = $(kde_datadir)/clockapplet/pics
+
+INCLUDES = -I$(top_srcdir)/kicker/libkicker -I../../libkicker $(all_includes)
+
+kde_module_LTLIBRARIES = clock_panelapplet.la
+
+clock_panelapplet_la_SOURCES = clock.skel clock.cpp datepicker.cpp zone.cpp analog.ui digital.ui fuzzy.ui settings.ui prefs.kcfgc
+
+METASOURCES = AUTO
+noinst_HEADERS = clock.h datepicker.h zone.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = clockapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA) $(pic_DATA)
+
+clock_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+clock_panelapplet_la_LIBADD = ../../libkicker/libkickermain.la $(LIB_KDEUI)
+
+srcdoc:
+ kdoc -a -p -H -d $$HOME/web/src/clockapplet clockapplet *.h -lqt -lkdecore -lkdeui -lkfile
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/clockapplet.pot
+
+KDE_OPTIONS=nofinal
+
+clock_skel.lo: settings.h
diff --git a/kicker/applets/clock/analog.ui b/kicker/applets/clock/analog.ui
new file mode 100644
index 000000000..4a20312ec
--- /dev/null
+++ b/kicker/applets/clock/analog.ui
@@ -0,0 +1,344 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>AnalogWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>AnalogWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>524</width>
+ <height>307</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup2_3_2</cstring>
+ </property>
+ <property name="title">
+ <string>Display</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AnalogShowDate</cstring>
+ </property>
+ <property name="text">
+ <string>Dat&amp;e</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AnalogShowSeconds</cstring>
+ </property>
+ <property name="text">
+ <string>Seco&amp;nds</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AnalogShowDayOfWeek</cstring>
+ </property>
+ <property name="text">
+ <string>Da&amp;y of week</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AnalogShowFrame</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Frame</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer20</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Time</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton" row="2" column="1">
+ <property name="name">
+ <cstring>kcfg_AnalogBackgroundColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_AnalogShadowColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>foregroundAnalogLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Foreground color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_AnalogForegroundColor</cstring>
+ </property>
+ </widget>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>backgroundAnalogLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_AnalogBackgroundColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_AnalogForegroundColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>shadowAnalogLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Shadow color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_AnalogShadowColor</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Antialias:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_AnalogAntialias</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Low Quality</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>High Quality</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>kcfg_AnalogAntialias</cstring>
+ </property>
+ <property name="currentItem">
+ <number>0</number>
+ </property>
+ </widget>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>Spacer18_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>310</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>kcfg_AnalogLCDStyle</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;LCD look</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer row="3" column="2">
+ <property name="name">
+ <cstring>spacer54</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>50</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>kcfg_AnalogLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>foregroundAnalogLabel</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AnalogLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>backgroundAnalogLabel</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AnalogLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>shadowAnalogLabel</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AnalogLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_AnalogForegroundColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AnalogLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_AnalogShadowColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AnalogLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_AnalogBackgroundColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>kcfg_AnalogShowDate</tabstop>
+ <tabstop>kcfg_AnalogShowSeconds</tabstop>
+ <tabstop>kcfg_AnalogShowFrame</tabstop>
+ <tabstop>kcfg_AnalogAntialias</tabstop>
+ <tabstop>kcfg_AnalogLCDStyle</tabstop>
+ <tabstop>kcfg_AnalogForegroundColor</tabstop>
+ <tabstop>kcfg_AnalogShadowColor</tabstop>
+ <tabstop>kcfg_AnalogBackgroundColor</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">kfontrequester.h</include>
+</includes>
+<layoutdefaults spacing="3" margin="6"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kicker/applets/clock/clock.cpp b/kicker/applets/clock/clock.cpp
new file mode 100644
index 000000000..19e91be5c
--- /dev/null
+++ b/kicker/applets/clock/clock.cpp
@@ -0,0 +1,1871 @@
+/************************************************************
+
+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 <cstdlib>
+#include <ctime>
+#include <time.h>
+
+#include <qcheckbox.h>
+#include <qcursor.h>
+#include <qgroupbox.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <qclipboard.h>
+#include <qtabwidget.h>
+#include <qwidgetstack.h>
+#include <qcombobox.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kcolorbutton.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kstringhandler.h>
+#include <kfiledialog.h>
+#include <kfontrequester.h>
+#include <kglobalsettings.h>
+#include <kconfigdialogmanager.h>
+#include <kcalendarsystem.h>
+#include <kicontheme.h>
+#include <kiconloader.h>
+
+#include <global.h> // libkickermain
+
+#include "kickerSettings.h"
+#include "clock.h"
+#include "datepicker.h"
+#include "zone.h"
+#include "analog.h"
+#include "digital.h"
+#include "fuzzy.h"
+#include "prefs.h"
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("clockapplet");
+ KGlobal::locale()->insertCatalogue("timezones"); // For time zone translations
+ return new ClockApplet(configFile, KPanelApplet::Normal,
+ KPanelApplet::Preferences, parent, "clockapplet");
+ }
+}
+
+// Settings
+
+KConfigDialogSingle::KConfigDialogSingle(Zone *zone, QWidget *parent,
+ const char *name, Prefs * prefs,
+ KDialogBase::DialogType dialogType,
+ bool modal) :
+ KConfigDialog(parent, name, prefs, dialogType,
+ KDialogBase::Default | KDialogBase::Ok |
+ KDialogBase::Apply | KDialogBase::Cancel,
+ KDialogBase::Ok,
+ modal), _prefs(prefs)
+{
+ // As a temporary mesure until the kicker applet's app name is set to the
+ // applets name so KDialogBase gets the right info.
+ setPlainCaption(i18n("Configure - Clock"));
+ setIcon(SmallIcon("date"));
+
+ settings = new SettingsWidgetImp(prefs, zone, 0, "General");
+ connect(settings->kcfg_Type, SIGNAL(activated(int)), SLOT(selectPage(int)));
+
+ settings->kcfg_PlainBackgroundColor->setDefaultColor(KApplication::palette().active().background());
+ settings->kcfg_DateBackgroundColor->setDefaultColor(KApplication::palette().active().background());
+
+ // Digital
+ digitalPage = new DigitalWidget(0, "DigitalClock");
+ settings->widgetStack->addWidget(digitalPage, 1);
+ digitalPage->kcfg_DigitalBackgroundColor->setDefaultColor(KApplication::palette().active().background());
+
+ // Analog
+ analogPage = new AnalogWidget(0, "AnalogClock");
+ settings->widgetStack->addWidget(analogPage, 2);
+ analogPage->kcfg_AnalogBackgroundColor->setDefaultColor(KApplication::palette().active().background());
+
+ // Fuzzy
+ fuzzyPage = new FuzzyWidget(0, "FuzzyClock");
+ settings->widgetStack->addWidget(fuzzyPage, 3);
+ fuzzyPage->kcfg_FuzzyBackgroundColor->setDefaultColor(KApplication::palette().active().background());
+
+ connect(settings->kcfg_PlainShowDate, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(settings->kcfg_PlainShowDayOfWeek, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(digitalPage->kcfg_DigitalShowDate, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(digitalPage->kcfg_DigitalShowDayOfWeek, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(digitalPage->kcfg_DigitalShowDate, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(analogPage->kcfg_AnalogShowDate, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(analogPage->kcfg_AnalogShowDayOfWeek, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(fuzzyPage->kcfg_FuzzyShowDate, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+ connect(fuzzyPage->kcfg_FuzzyShowDayOfWeek, SIGNAL(toggled(bool)),
+ SLOT(dateToggled()));
+
+ addPage(settings, i18n("General"), QString::fromLatin1("package_settings"));
+}
+
+void KConfigDialogSingle::updateSettings()
+{
+ settings->OkApply();
+}
+
+void KConfigDialogSingle::updateWidgets()
+{
+ selectPage( _prefs->type() );
+}
+
+void KConfigDialogSingle::updateWidgetsDefault()
+{
+ KConfigSkeletonItem *item = _prefs->findItem("Type");
+ item->swapDefault();
+ selectPage( _prefs->type() );
+ item->swapDefault();
+ // This is ugly, but kcfg_Type does not have its correct setting
+ // at this point in time.
+ QTimer::singleShot(0, this, SLOT(dateToggled()));
+}
+
+void KConfigDialogSingle::selectPage(int p)
+{
+ settings->widgetStack->raiseWidget( p );
+ dateToggled();
+}
+
+void KConfigDialogSingle::dateToggled()
+{
+ bool showDate;
+ switch( settings->kcfg_Type->currentItem() )
+ {
+ case Prefs::EnumType::Plain:
+ showDate = settings->kcfg_PlainShowDate->isChecked() ||
+ settings->kcfg_PlainShowDayOfWeek->isChecked();
+ break;
+ case Prefs::EnumType::Digital:
+ showDate = digitalPage->kcfg_DigitalShowDate->isChecked() ||
+ digitalPage->kcfg_DigitalShowDayOfWeek->isChecked();
+ break;
+ case Prefs::EnumType::Analog:
+ showDate = analogPage->kcfg_AnalogShowDate->isChecked() ||
+ analogPage->kcfg_AnalogShowDayOfWeek->isChecked();
+ break;
+ case Prefs::EnumType::Fuzzy:
+ default:
+ showDate = fuzzyPage->kcfg_FuzzyShowDate->isChecked() ||
+ fuzzyPage->kcfg_FuzzyShowDayOfWeek->isChecked();
+ break;
+ }
+ settings->dateBox->setEnabled(showDate);
+}
+
+SettingsWidgetImp::SettingsWidgetImp(Prefs *p, Zone *z, QWidget* parent, const char* name, WFlags fl) :
+ SettingsWidget(parent, name, fl), prefs(p), zone(z)
+{
+ zone->readZoneList(tzListView);
+}
+
+void SettingsWidgetImp::OkApply()
+{
+ zone->getSelectedZonelist(tzListView);
+ zone->writeSettings();
+}
+
+//************************************************************
+
+
+ClockWidget::ClockWidget(ClockApplet *applet, Prefs* prefs)
+ : _applet(applet), _prefs(prefs), _force(false)
+{}
+
+
+ClockWidget::~ClockWidget()
+{}
+
+
+//************************************************************
+
+
+PlainClock::PlainClock(ClockApplet *applet, Prefs *prefs, QWidget *parent, const char *name)
+ : QLabel(parent, name), ClockWidget(applet, prefs)
+{
+ setWFlags(WNoAutoErase);
+ setBackgroundOrigin(AncestorOrigin);
+ loadSettings();
+ updateClock();
+}
+
+
+int PlainClock::preferedWidthForHeight(int ) const
+{
+ QString maxLengthTime = KGlobal::locale()->formatTime( QTime( 23, 59 ), _prefs->plainShowSeconds());
+ return fontMetrics().width( maxLengthTime ) + 8;
+}
+
+
+int PlainClock::preferedHeightForWidth(int /*w*/) const
+{
+ return fontMetrics().lineSpacing();
+}
+
+
+void PlainClock::updateClock()
+{
+ QString newStr = KGlobal::locale()->formatTime(_applet->clockGetTime(), _prefs->plainShowSeconds());
+
+ if (_force || newStr != _timeStr) {
+ _timeStr = newStr;
+ update();
+ }
+}
+
+void PlainClock::loadSettings()
+{
+ setFrameStyle(_prefs->plainShowFrame() ? Panel | Sunken : NoFrame);
+ setAlignment(AlignVCenter | AlignHCenter | SingleLine);
+
+ setFont(_prefs->plainFont());
+}
+
+bool PlainClock::showDate()
+{
+ return _prefs->plainShowDate();
+}
+
+bool PlainClock::showDayOfWeek()
+{
+ return _prefs->plainShowDayOfWeek();
+}
+
+void PlainClock::paintEvent(QPaintEvent *)
+{
+ QPainter p;
+ QPixmap buf(size());
+ buf.fill(this, 0, 0);
+ p.begin(&buf);
+ p.setFont(font());
+ p.setPen(paletteForegroundColor());
+ drawContents(&p);
+ drawFrame(&p);
+ p.end();
+ p.begin(this);
+ p.drawPixmap(0, 0, buf);
+ p.end();
+}
+
+void PlainClock::drawContents(QPainter *p)
+{
+ QRect tr(0, 0, width(), height());
+
+ if (!KickerSettings::transparent())
+ p->drawText(tr, AlignCenter, _timeStr);
+ else
+ _applet->shadowEngine()->drawText(*p, tr, AlignCenter, _timeStr, size());
+}
+
+//************************************************************
+
+
+DigitalClock::DigitalClock(ClockApplet *applet, Prefs *prefs, QWidget *parent, const char *name)
+ : QLCDNumber(parent, name), ClockWidget(applet, prefs)
+{
+ setWFlags(WNoAutoErase);
+ setBackgroundOrigin(AncestorOrigin);
+ loadSettings();
+ updateClock();
+}
+
+
+DigitalClock::~DigitalClock()
+{
+ delete _buffer;
+}
+
+
+int DigitalClock::preferedWidthForHeight(int h) const
+{
+ if (h > 29) h = 29;
+ if (h < 0) h = 0;
+ return (numDigits()*h*5/11)+2;
+}
+
+
+int DigitalClock::preferedHeightForWidth(int w) const
+{
+ if (w < 0) w = 0;
+ return((w / numDigits() * 2) + 6);
+}
+
+
+void DigitalClock::updateClock()
+{
+ static bool colon = true;
+ QString newStr;
+ QTime t(_applet->clockGetTime());
+
+ int h = t.hour();
+ int m = t.minute();
+ int s = t.second();
+
+ QString format("%02d");
+
+ QString sep(!colon && _prefs->digitalBlink() ? " " : ":");
+
+ if (_prefs->digitalShowSeconds())
+ format += sep + "%02d";
+
+ if (KGlobal::locale()->use12Clock()) {
+ if (h > 12)
+ h -= 12;
+ else if( h == 0)
+ h = 12;
+
+ format.prepend("%2d" + sep);
+ } else
+ format.prepend("%02d" + sep);
+
+
+ if (_prefs->digitalShowSeconds())
+ newStr.sprintf(format.latin1(), h, m, s);
+ else
+ newStr.sprintf(format.latin1(), h, m);
+
+ if (_force || newStr != _timeStr)
+ {
+ _timeStr = newStr;
+ setUpdatesEnabled( FALSE );
+ display(_timeStr);
+ setUpdatesEnabled( TRUE );
+ update();
+ }
+
+ if (_prefs->digitalBlink())
+ colon = !colon;
+}
+
+void DigitalClock::loadSettings()
+{
+ setFrameStyle(_prefs->digitalShowFrame() ? Panel | Sunken : NoFrame);
+ setMargin( 4 );
+ setSegmentStyle(QLCDNumber::Flat);
+
+ if (_prefs->digitalLCDStyle())
+ lcdPattern = KIconLoader("clockapplet").loadIcon("lcd", KIcon::User);
+
+ setNumDigits(_prefs->digitalShowSeconds() ? 8:5);
+
+ _buffer = new QPixmap(width(), height());
+}
+
+void DigitalClock::paintEvent(QPaintEvent*)
+{
+ QPainter p(_buffer);
+
+ if (_prefs->digitalLCDStyle())
+ {
+ p.drawTiledPixmap(0, 0, width(), height(), lcdPattern);
+ }
+ else if (_prefs->digitalBackgroundColor() !=
+ KApplication::palette().active().background())
+ {
+ p.fillRect(0, 0, width(), height(), _prefs->digitalBackgroundColor());
+ }
+ else if (paletteBackgroundPixmap())
+ {
+ QPoint offset = backgroundOffset();
+ p.drawTiledPixmap(0, 0, width(), height(), *paletteBackgroundPixmap(), offset.x(), offset.y());
+ }
+ else
+ {
+ p.fillRect(0, 0, width(), height(), _prefs->digitalBackgroundColor());
+ }
+
+ drawContents(&p);
+ if (_prefs->digitalShowFrame())
+ {
+ drawFrame(&p);
+ }
+
+ p.end();
+ bitBlt(this, 0, 0, _buffer, 0, 0);
+}
+
+
+// yes, the colors for the lcd-lock are hardcoded,
+// but other colors would break the lcd-lock anyway
+void DigitalClock::drawContents( QPainter * p)
+{
+ setUpdatesEnabled( FALSE );
+ QPalette pal = palette();
+ if (_prefs->digitalLCDStyle())
+ pal.setColor( QColorGroup::Foreground, QColor(128,128,128));
+ else
+ pal.setColor( QColorGroup::Foreground, _prefs->digitalShadowColor());
+ setPalette( pal );
+ p->translate( +1, +1 );
+ QLCDNumber::drawContents( p );
+ if (_prefs->digitalLCDStyle())
+ pal.setColor( QColorGroup::Foreground, Qt::black);
+ else
+ pal.setColor( QColorGroup::Foreground, _prefs->digitalForegroundColor());
+ setPalette( pal );
+ p->translate( -2, -2 );
+ setUpdatesEnabled( TRUE );
+ QLCDNumber::drawContents( p );
+ p->translate( +1, +1 );
+}
+
+
+// reallocate buffer pixmap
+void DigitalClock::resizeEvent ( QResizeEvent *)
+{
+ delete _buffer;
+ _buffer = new QPixmap( width(), height() );
+}
+
+
+bool DigitalClock::showDate()
+{
+ return _prefs->digitalShowDate();
+}
+
+bool DigitalClock::showDayOfWeek()
+{
+ return _prefs->digitalShowDayOfWeek();
+}
+
+
+//************************************************************
+
+
+AnalogClock::AnalogClock(ClockApplet *applet, Prefs *prefs, QWidget *parent, const char *name)
+ : QFrame(parent, name), ClockWidget(applet, prefs), _spPx(NULL)
+{
+ setWFlags(WNoAutoErase);
+ setBackgroundOrigin(AncestorOrigin);
+ loadSettings();
+}
+
+
+AnalogClock::~AnalogClock()
+{
+ delete _spPx;
+}
+
+void AnalogClock::initBackgroundPixmap()
+{
+ //if no antialiasing, use pixmap as-is
+ if (_prefs->analogAntialias() == 0)
+ {
+ lcdPattern = KIconLoader("clockapplet").loadIcon("lcd",KIcon::User);
+ _bgScale = 1;
+ }
+ else
+ {
+ //make a scaled pixmap -- so when image is reduced it'll look "OK".
+ _bgScale = _prefs->analogAntialias()+1;
+ QImage bgImage = KIconLoader("clockapplet").loadIcon("lcd", KIcon::User).convertToImage();
+ lcdPattern = QPixmap(bgImage.scale(bgImage.width() * _bgScale,
+ bgImage.height() * _bgScale));
+
+ }
+}
+
+void AnalogClock::updateClock()
+{
+ if (!_force)
+ {
+ if (!_prefs->analogShowSeconds() && (_time.minute() == _applet->clockGetTime().minute()))
+ return;
+ }
+
+ _time = _applet->clockGetTime();
+ update();
+}
+
+void AnalogClock::loadSettings()
+{
+ if (_prefs->analogLCDStyle())
+ {
+ initBackgroundPixmap();
+ }
+/* this may prevent flicker, but it also prevents transparency
+ else
+ {
+ setBackgroundMode(NoBackground);
+ }*/
+
+ setFrameStyle(_prefs->analogShowFrame() ? Panel | Sunken : NoFrame);
+ _time = _applet->clockGetTime();
+ _spPx = new QPixmap(size().width() * _prefs->analogAntialias()+1,
+ size().height() * _prefs->analogAntialias()+1);
+
+ update();
+}
+
+void AnalogClock::paintEvent( QPaintEvent * )
+{
+ if ( !isVisible() )
+ return;
+
+ int aaFactor = _prefs->analogAntialias()+1;
+ int spWidth = size().width() * aaFactor;
+ int spHeight = size().height() * aaFactor;
+
+ if ((spWidth != _spPx->size().width()) ||
+ (spHeight != _spPx->size().height()))
+ {
+ delete _spPx;
+ _spPx = new QPixmap(spWidth, spHeight);
+ }
+
+ QPainter paint;
+ paint.begin(_spPx);
+
+ if (_prefs->analogLCDStyle())
+ {
+ if (_bgScale != aaFactor)
+ {
+ //check to see if antialiasing has changed -- bg pixmap will need
+ //to be re-created
+ initBackgroundPixmap();
+ }
+
+ paint.drawTiledPixmap(0, 0, spWidth, spHeight, lcdPattern);
+ }
+ else if (_prefs->analogBackgroundColor() != KApplication::palette().active().background())
+ {
+ _spPx->fill(_prefs->analogBackgroundColor());
+ }
+ else if (paletteBackgroundPixmap())
+ {
+ QPixmap bg(width(), height());
+ QPainter p(&bg);
+ QPoint offset = backgroundOffset();
+ p.drawTiledPixmap(0, 0, width(), height(), *paletteBackgroundPixmap(), offset.x(), offset.y());
+ p.end();
+ QImage bgImage = bg.convertToImage().scale(spWidth, spHeight);
+ paint.drawImage(0, 0, bgImage);
+ }
+ else
+ {
+ _spPx->fill(_prefs->analogBackgroundColor());
+ }
+
+ QPointArray pts;
+ QPoint cp(spWidth / 2, spHeight / 2);
+
+ int d = KMIN(spWidth,spHeight) - (10 * aaFactor);
+
+ if (_prefs->analogLCDStyle())
+ {
+ paint.setPen( QPen(QColor(100,100,100), aaFactor) );
+ paint.setBrush( QColor(100,100,100) );
+ }
+ else
+ {
+ paint.setPen( QPen(_prefs->analogShadowColor(), aaFactor) );
+ paint.setBrush( _prefs->analogShadowColor() );
+ }
+
+ paint.setViewport(2,2,spWidth,spHeight);
+
+ for ( int c=0 ; c < 2 ; c++ ) {
+ QWMatrix matrix;
+ matrix.translate( cp.x(), cp.y());
+ matrix.scale( d/1000.0F, d/1000.0F );
+
+ // hour
+ float h_angle = 30*(_time.hour()%12-3) + _time.minute()/2;
+ matrix.rotate( h_angle );
+ paint.setWorldMatrix( matrix );
+ pts.setPoints( 4, -20,0, 0,-20, 300,0, 0,20 );
+ paint.drawPolygon( pts );
+ matrix.rotate( -h_angle );
+
+ // minute
+ float m_angle = (_time.minute()-15)*6;
+ matrix.rotate( m_angle );
+ paint.setWorldMatrix( matrix );
+ pts.setPoints( 4, -10,0, 0,-10, 400,0, 0,10 );
+ paint.drawPolygon( pts );
+ matrix.rotate( -m_angle );
+
+ if (_prefs->analogShowSeconds()) { // second
+ float s_angle = (_time.second()-15)*6;
+ matrix.rotate( s_angle );
+ paint.setWorldMatrix( matrix );
+ pts.setPoints(4,0,0,0,0,400,0,0,0);
+ paint.drawPolygon( pts );
+ matrix.rotate( -s_angle );
+ }
+
+ QWMatrix matrix2;
+ matrix2.translate( cp.x(), cp.y());
+ matrix2.scale( d/1000.0F, d/1000.0F );
+
+ // quadrante
+ for ( int i=0 ; i < 12 ; i++ ) {
+ paint.setWorldMatrix( matrix2 );
+ paint.drawLine( 460,0, 500,0 ); // draw hour lines
+ // paint.drawEllipse( 450, -15, 30, 30 );
+ matrix2.rotate( 30 );
+ }
+
+ if (_prefs->analogLCDStyle()) {
+ paint.setPen( QPen(Qt::black, aaFactor) );
+ paint.setBrush( Qt::black );
+ } else {
+ paint.setPen( QPen(_prefs->analogForegroundColor(), aaFactor) );
+ paint.setBrush( _prefs->analogForegroundColor() );
+ }
+
+ paint.setViewport(0,0,spWidth,spHeight);
+ }
+ paint.end();
+
+ QPainter paintFinal;
+ paintFinal.begin(this);
+
+ if (aaFactor != 1)
+ {
+ QImage spImage = _spPx->convertToImage();
+ QImage displayImage = spImage.smoothScale(size());
+
+ paintFinal.drawImage(0, 0, displayImage);
+ }
+ else
+ {
+ paintFinal.drawPixmap(0, 0, *_spPx);
+ }
+
+ if (_prefs->analogShowFrame())
+ {
+ drawFrame(&paintFinal);
+ }
+}
+
+
+// the background pixmap disappears during a style change
+void AnalogClock::styleChange(QStyle &)
+{
+ if (_prefs->analogLCDStyle())
+ {
+ initBackgroundPixmap();
+ }
+}
+
+bool AnalogClock::showDate()
+{
+ return _prefs->analogShowDate();
+}
+
+bool AnalogClock::showDayOfWeek()
+{
+ return _prefs->analogShowDayOfWeek();
+}
+
+
+//************************************************************
+
+
+FuzzyClock::FuzzyClock(ClockApplet *applet, Prefs *prefs, QWidget *parent, const char *name)
+ : QFrame(parent, name), ClockWidget(applet, prefs)
+{
+ setBackgroundOrigin(AncestorOrigin);
+ loadSettings();
+ hourNames << i18n("hour","one") << i18n("hour","two")
+ << i18n("hour","three") << i18n("hour","four") << i18n("hour","five")
+ << i18n("hour","six") << i18n("hour","seven") << i18n("hour","eight")
+ << i18n("hour","nine") << i18n("hour","ten") << i18n("hour","eleven")
+ << i18n("hour","twelve");
+
+ // xgettext:no-c-format
+ normalFuzzy << i18n("%0 o'clock") // xgettext:no-c-format
+ << i18n("five past %0") // xgettext:no-c-format
+ << i18n("ten past %0") // xgettext:no-c-format
+ << i18n("quarter past %0") // xgettext:no-c-format
+ << i18n("twenty past %0") // xgettext:no-c-format
+ << i18n("twenty five past %0") // xgettext:no-c-format
+ << i18n("half past %0") // xgettext:no-c-format
+ << i18n("twenty five to %1") // xgettext:no-c-format
+ << i18n("twenty to %1") // xgettext:no-c-format
+ << i18n("quarter to %1") // xgettext:no-c-format
+ << i18n("ten to %1") // xgettext:no-c-format
+ << i18n("five to %1") // xgettext:no-c-format
+ << i18n("%1 o'clock");
+
+ // xgettext:no-c-format
+ normalFuzzyOne << i18n("one","%0 o'clock") // xgettext:no-c-format
+ << i18n("one","five past %0") // xgettext:no-c-format
+ << i18n("one","ten past %0") // xgettext:no-c-format
+ << i18n("one","quarter past %0") // xgettext:no-c-format
+ << i18n("one","twenty past %0") // xgettext:no-c-format
+ << i18n("one","twenty five past %0") // xgettext:no-c-format
+ << i18n("one","half past %0") // xgettext:no-c-format
+ << i18n("one","twenty five to %1") // xgettext:no-c-format
+ << i18n("one","twenty to %1") // xgettext:no-c-format
+ << i18n("one","quarter to %1") // xgettext:no-c-format
+ << i18n("one","ten to %1") // xgettext:no-c-format
+ << i18n("one","five to %1") // xgettext:no-c-format
+ << i18n("one","%1 o'clock");
+
+ dayTime << i18n("Night")
+ << i18n("Early morning") << i18n("Morning") << i18n("Almost noon")
+ << i18n("Noon") << i18n("Afternoon") << i18n("Evening")
+ << i18n("Late evening");
+
+ _time = _applet->clockGetTime();
+ alreadyDrawing=false;
+ update();
+}
+
+void FuzzyClock::deleteMyself()
+{
+ if(alreadyDrawing) // try again later
+ QTimer::singleShot(1000, this, SLOT(deleteMyself()));
+ else
+ delete this;
+}
+
+
+int FuzzyClock::preferedWidthForHeight(int ) const
+{
+ QFontMetrics fm(_prefs->fuzzyFont());
+ return fm.width(_timeStr) + 8;
+}
+
+
+int FuzzyClock::preferedHeightForWidth(int ) const
+{
+ QFontMetrics fm(_prefs->fuzzyFont());
+ return fm.width(_timeStr) + 8;
+}
+
+
+void FuzzyClock::updateClock()
+{
+ if (!_force)
+ {
+ if (_time.hour() == _applet->clockGetTime().hour() &&
+ _time.minute() == _applet->clockGetTime().minute())
+ return;
+ }
+
+ _time = _applet->clockGetTime();
+ update();
+}
+
+void FuzzyClock::loadSettings()
+{
+ setFrameStyle(_prefs->fuzzyShowFrame() ? Panel | Sunken : 0);
+}
+
+void FuzzyClock::drawContents(QPainter *p)
+{
+ if (!isVisible())
+ return;
+
+ if(!_applet)
+ return;
+
+ alreadyDrawing = true;
+ QString newTimeStr;
+
+ if (_prefs->fuzzyness() == 1 || _prefs->fuzzyness() == 2) {
+ int minute = _time.minute();
+ int sector = 0;
+ int realHour = 0;
+
+ if (_prefs->fuzzyness() == 1) {
+ if (minute > 2)
+ sector = (minute - 3) / 5 + 1;
+ } else {
+ if (minute > 6)
+ sector = ((minute - 7) / 15 + 1) * 3;
+ }
+
+ newTimeStr = normalFuzzy[sector];
+ int phStart = newTimeStr.find("%");
+ if (phStart >= 0) { // protect yourself from translations
+ int phLength = newTimeStr.find(" ", phStart) - phStart;
+
+ // larrosa: we want the exact length, in case the translation needs it,
+ // in other case, we would cut off the end of the translation.
+ if (phLength < 0) phLength = newTimeStr.length() - phStart;
+ int deltaHour = newTimeStr.mid(phStart + 1, phLength - 1).toInt();
+
+ if ((_time.hour() + deltaHour) % 12 > 0)
+ realHour = (_time.hour() + deltaHour) % 12 - 1;
+ else
+ realHour = 12 - ((_time.hour() + deltaHour) % 12 + 1);
+ if (realHour==0) {
+ newTimeStr = normalFuzzyOne[sector];
+ phStart = newTimeStr.find("%");
+ // larrosa: Note that length is the same,
+ // so we only have to update phStart
+ }
+ if (phStart >= 0)
+ newTimeStr.replace(phStart, phLength, hourNames[realHour]);
+ newTimeStr.replace(0, 1, QString(newTimeStr.at(0).upper()));
+ }
+ } else if (_prefs->fuzzyness() == 3) {
+ newTimeStr = dayTime[_time.hour() / 3];
+ } else {
+ int dow = _applet->clockGetDate().dayOfWeek();
+
+ if (dow == 1)
+ newTimeStr = i18n("Start of week");
+ else if (dow >= 2 && dow <= 4)
+ newTimeStr = i18n("Middle of week");
+ else if (dow == 5)
+ newTimeStr = i18n("End of week");
+ else
+ newTimeStr = i18n("Weekend!");
+ }
+
+ if (_timeStr != newTimeStr) {
+ _timeStr = newTimeStr;
+ _applet->resizeRequest();
+ }
+
+ p->setFont(_prefs->fuzzyFont());
+ p->setPen(_prefs->fuzzyForegroundColor());
+
+ QRect tr;
+
+ if (_applet->getOrientation() == Vertical)
+ {
+ p->rotate(90);
+ tr = QRect(4, -2, height() - 8, -(width()) + 2);
+ }
+ else
+ tr = QRect(4, 2, width() - 8, height() - 4);
+
+ if (!KickerSettings::transparent())
+ p->drawText(tr, AlignCenter, _timeStr);
+ else
+ _applet->shadowEngine()->drawText(*p, tr, AlignCenter, _timeStr, size());
+
+ alreadyDrawing = false;
+}
+
+bool FuzzyClock::showDate()
+{
+ return _prefs->fuzzyShowDate();
+}
+
+bool FuzzyClock::showDayOfWeek()
+{
+ return _prefs->fuzzyShowDayOfWeek();
+}
+
+
+//************************************************************
+
+
+ClockApplet::ClockApplet(const QString& configFile, Type t, int actions,
+ QWidget *parent, const char *name)
+ : KPanelApplet(configFile, t, actions, parent, name),
+ _calendar(0),
+ _disableCalendar(false),
+ _clock(0),
+ _timer(new QTimer(this)),
+ m_layoutTimer(new QTimer(this)),
+ m_layoutDelay(0),
+ m_followBackgroundSetting(true),
+ m_dateFollowBackgroundSetting(true),
+ TZoffset(0),
+ _prefs(new Prefs(sharedConfig())),
+ zone(new Zone(config())),
+ menu(0),
+ m_tooltip(this),
+ m_shadowEngine(0)
+{
+ DCOPObject::setObjId("ClockApplet");
+ _prefs->readConfig();
+ configFileName = configFile.latin1();
+ setBackgroundOrigin(AncestorOrigin);
+
+ _dayOfWeek = new QLabel(this);
+ _dayOfWeek->setAlignment(AlignVCenter | AlignHCenter | WordBreak);
+ _dayOfWeek->setBackgroundOrigin(AncestorOrigin);
+ _dayOfWeek->installEventFilter(this); // catch mouse clicks
+
+ _date = new QLabel(this);
+ _date->setAlignment(AlignVCenter | AlignHCenter | WordBreak);
+ _date->setBackgroundOrigin(AncestorOrigin);
+ _date->installEventFilter(this); // catch mouse clicks
+
+ connect(m_layoutTimer, SIGNAL(timeout()), this, SLOT(fixupLayout()));
+ connect(_timer, SIGNAL(timeout()), SLOT(slotUpdate()));
+ connect(kapp, SIGNAL(kdisplayPaletteChanged()), SLOT(globalPaletteChange()));
+
+ reconfigure(); // initialize clock widget
+ slotUpdate();
+
+ if (kapp->authorizeKAction("kicker_rmb"))
+ {
+ menu = new KPopupMenu();
+ connect(menu, SIGNAL(aboutToShow()), SLOT(aboutToShowContextMenu()));
+ connect(menu, SIGNAL(activated(int)), SLOT(contextMenuActivated(int)));
+ setCustomMenu(menu);
+ }
+
+ installEventFilter(KickerTip::the());
+}
+
+
+ClockApplet::~ClockApplet()
+{
+ delete m_shadowEngine;
+ //reverse for the moment
+ KGlobal::locale()->removeCatalogue("clockapplet");
+ KGlobal::locale()->removeCatalogue("timezones"); // For time zone translations
+
+ if (_calendar)
+ {
+ // we have to take care of the calendar closing first before deleting
+ // the prefs
+ _calendar->close();
+ }
+
+ zone->writeSettings();
+
+ delete _prefs; _prefs = 0;
+ delete zone; zone = 0;
+ delete menu; menu = 0;
+ config()->sync();
+}
+
+
+KTextShadowEngine *ClockApplet::shadowEngine()
+{
+ if (!m_shadowEngine)
+ m_shadowEngine = new KTextShadowEngine();
+
+ return m_shadowEngine;
+}
+
+
+int ClockApplet::widthForHeight(int h) const
+{
+ if (orientation() == Qt::Vertical)
+ {
+ return width();
+ }
+
+ int shareDateHeight = 0, shareDayOfWeekHeight = 0;
+ bool dateToSide = (h < 32);
+ bool mustShowDate = showDate || (zone->zoneIndex() != 0);
+ if (mustShowDate)
+ {
+ _date->setAlignment(AlignVCenter | AlignHCenter);
+ if (!dateToSide)
+ {
+ shareDateHeight = _date->sizeHint().height();
+ }
+ }
+ if (showDayOfWeek)
+ {
+ _dayOfWeek->setAlignment(AlignVCenter | AlignHCenter);
+ if (!dateToSide)
+ {
+ shareDayOfWeekHeight = _dayOfWeek->sizeHint().height();
+ }
+ }
+
+ int clockWidth = _clock->preferedWidthForHeight(KMAX(0, h - shareDateHeight - shareDayOfWeekHeight));
+ int w = clockWidth;
+ if (!mustShowDate && !showDayOfWeek)
+ {
+ // resize the date widgets in case the are to the left of the clock
+ _clock->widget()->setFixedSize(w, h);
+ _clock->widget()->move(0,0);
+ _dayOfWeek->move(clockWidth + 4, 0);
+ _date->move(clockWidth + 4, 0);
+ }
+ else
+ {
+ int dateWidth = mustShowDate ? _date->sizeHint().width() + 4 : 0;
+ int dayOfWeekWidth = showDayOfWeek ? _dayOfWeek->sizeHint().width() + 4 : 0;
+
+ if (dateToSide)
+ {
+ w += dateWidth + dayOfWeekWidth;
+ bool dateFirst = false;
+
+ if (mustShowDate)
+ {
+ // if the date format STARTS with a year, assume it's in descending
+ // order and should therefore PRECEED the date.
+ QString dateFormat = KGlobal::locale()->dateFormatShort();
+ dateFirst = dateFormat.at(1) == 'y' || dateFormat.at(1) == 'Y';
+ }
+
+ if (dateFirst)
+ {
+ _date->setFixedSize(dateWidth, h);
+ _date->move(0, 0);
+
+ if (showDayOfWeek)
+ {
+ _dayOfWeek->setFixedSize(dayOfWeekWidth, h);
+ _dayOfWeek->move(dateWidth, 0);
+ }
+
+ _clock->widget()->setFixedSize(clockWidth, h);
+ _clock->widget()->move(dateWidth + dayOfWeekWidth, 0);
+ }
+ else
+ {
+ _clock->widget()->setFixedSize(clockWidth, h);
+ _clock->widget()->move(0,0);
+
+ if (showDayOfWeek)
+ {
+ _dayOfWeek->setFixedSize(dayOfWeekWidth, h);
+ _dayOfWeek->move(clockWidth, 0);
+ }
+
+ if (mustShowDate)
+ {
+ _date->setFixedSize(dateWidth, h);
+ _date->move(clockWidth + dayOfWeekWidth, 0);
+ }
+ }
+ }
+ else
+ {
+ w = KMAX(KMAX(w, dateWidth), dayOfWeekWidth);
+
+ _clock->widget()->setFixedSize(w, h - shareDateHeight - shareDayOfWeekHeight);
+ _clock->widget()->setMinimumSize(w, h - shareDateHeight - shareDayOfWeekHeight);
+ _clock->widget()->move(0, 0);
+ if (showDayOfWeek)
+ {
+ _dayOfWeek->setFixedSize(w, _dayOfWeek->sizeHint().height());
+ _dayOfWeek->move(0, _clock->widget()->height());
+ }
+
+ if (mustShowDate)
+ {
+ _date->setFixedSize(w, _date->sizeHint().height());
+ _date->move(0, _clock->widget()->height() + shareDayOfWeekHeight);
+ }
+ }
+ }
+
+ return w;
+}
+
+int ClockApplet::heightForWidth(int w) const
+{
+ if (orientation() == Qt::Horizontal)
+ {
+ return height();
+ }
+
+ int clockHeight = _clock->preferedHeightForWidth(w);
+ bool mustShowDate = showDate || (zone->zoneIndex() != 0);
+
+ _clock->widget()->setFixedSize(w, clockHeight);
+
+ // add 4 pixels in height for each of date+dayOfWeek, if visible
+ if (showDayOfWeek)
+ {
+ if (_dayOfWeek->minimumSizeHint().width() > w)
+ {
+ _dayOfWeek->setAlignment(AlignVCenter | WordBreak);
+ }
+ else
+ {
+ _dayOfWeek->setAlignment(AlignVCenter | AlignHCenter | WordBreak);
+ }
+
+ _dayOfWeek->setFixedSize(w, _dayOfWeek->minimumSizeHint().height());
+ _dayOfWeek->move(0, clockHeight);
+
+ clockHeight += _dayOfWeek->height();
+ }
+
+ if (mustShowDate)
+ {
+ // yes, the const_cast is ugly, but this is to ensure that we
+ // get a proper date label in the case that we munged it for
+ // display on panel that is too narrow and then they made it wider
+ const_cast<ClockApplet*>(this)->updateDateLabel(false);
+
+ if (_date->minimumSizeHint().width() > w)
+ {
+ QString dateStr = _date->text();
+ // if we're too wide to fit, replace the first non-digit from the end with a space
+ int p = dateStr.findRev(QRegExp("[^0-9]"));
+ if (p > 0)
+ {
+ _date->setText(dateStr.insert(p, '\n'));
+ }
+ }
+
+ if (_date->minimumSizeHint().width() > w)
+ {
+ _date->setAlignment(AlignVCenter | WordBreak);
+ }
+ else
+ {
+ _date->setAlignment(AlignVCenter | AlignHCenter | WordBreak);
+ }
+ _date->setFixedSize(w, _date->heightForWidth(w));
+ _date->move(0, clockHeight);
+
+ clockHeight += _date->height();
+ }
+
+ return clockHeight;
+}
+
+void ClockApplet::preferences()
+{
+ preferences(false);
+}
+
+void ClockApplet::preferences(bool timezone)
+{
+ KConfigDialogSingle *dialog = dynamic_cast<KConfigDialogSingle*>(KConfigDialog::exists(configFileName));
+
+ if (!dialog)
+ {
+ dialog = new KConfigDialogSingle(zone, this, configFileName, _prefs, KDialogBase::Swallow);
+ connect(dialog, SIGNAL(settingsChanged()), this, SLOT(slotReconfigure()));
+ }
+
+ if (timezone)
+ {
+ dialog->settings->tabs->setCurrentPage(1);
+ }
+
+ dialog->show();
+}
+
+void ClockApplet::updateFollowBackground()
+{
+ QColor globalBgroundColor = KApplication::palette().active().background();
+ QColor bgColor;
+
+ switch (_prefs->type())
+ {
+ case Prefs::EnumType::Plain:
+ bgColor = _prefs->plainBackgroundColor();
+ break;
+ case Prefs::EnumType::Analog:
+ bgColor = _prefs->analogBackgroundColor();
+ break;
+ case Prefs::EnumType::Fuzzy:
+ bgColor = _prefs->fuzzyBackgroundColor();
+ break;
+ case Prefs::EnumType::Digital:
+ default:
+ bgColor = _prefs->digitalBackgroundColor();
+ break;
+ }
+
+ m_followBackgroundSetting = (bgColor == globalBgroundColor);
+
+ bgColor = _prefs->dateBackgroundColor();
+ m_dateFollowBackgroundSetting = (bgColor == globalBgroundColor);
+}
+
+// DCOP interface
+void ClockApplet::reconfigure()
+{
+ _timer->stop();
+
+ // ugly workaround for FuzzyClock: sometimes FuzzyClock
+ // hasn't finished drawing when getting deleted, so we
+ // ask FuzzyClock to delete itself appropriately
+ if (_clock && _clock->widget()->inherits("FuzzyClock"))
+ {
+ FuzzyClock* f = static_cast<FuzzyClock*>(_clock);
+ f->deleteMyself();
+ }
+ else
+ {
+ delete _clock;
+ }
+
+ int shortInterval = 500;
+ int updateInterval = 0;
+
+ switch (_prefs->type())
+ {
+ case Prefs::EnumType::Plain:
+ _clock = new PlainClock(this, _prefs, this);
+ if (_prefs->plainShowSeconds())
+ updateInterval = shortInterval;
+ break;
+ case Prefs::EnumType::Analog:
+ _clock = new AnalogClock(this, _prefs, this);
+ if (_prefs->analogShowSeconds())
+ updateInterval = shortInterval;
+ break;
+ case Prefs::EnumType::Fuzzy:
+ _clock = new FuzzyClock(this, _prefs, this);
+ break;
+ case Prefs::EnumType::Digital:
+ default:
+ _clock = new DigitalClock(this, _prefs, this);
+ if (_prefs->digitalShowSeconds() || _prefs->digitalBlink())
+ updateInterval = shortInterval;
+ break;
+ }
+
+ m_updateOnTheMinute = updateInterval != shortInterval;
+ if (m_updateOnTheMinute)
+ {
+ connect(_timer, SIGNAL(timeout()), this, SLOT(setTimerTo60()));
+ updateInterval = ((60 - clockGetTime().second()) * 1000) + 500;
+ }
+ else
+ {
+ // in case we reconfigure to show seconds but setTimerTo60 is going to be called
+ // we need to make sure to disconnect this so we don't end up updating only once
+ // a minute ;)
+ disconnect(_timer, SIGNAL(timeout()), this, SLOT(setTimerTo60()));
+ }
+
+ _timer->start(updateInterval);
+
+ // See if the clock wants to show the date.
+ showDate = _clock->showDate();
+ if (showDate)
+ {
+ TZoffset = zone->calc_TZ_offset(zone->zone(), true);
+ updateDateLabel();
+ }
+
+ updateFollowBackground();
+ setBackground();
+
+ // FIXME: this means you can't have a transparent clock but a non-transparent
+ // date or day =/
+
+ _clock->widget()->installEventFilter(this); // catch mouse clicks
+ _clock->widget()->show();
+
+ _clock->forceUpdate(); /* force repaint */
+
+ if (showDayOfWeek)
+ {
+ _dayOfWeek->show();
+ }
+ else
+ {
+ _dayOfWeek->hide();
+ }
+
+ if (showDate || (zone->zoneIndex() != 0))
+ {
+ _date->show();
+ }
+ else
+ {
+ _date->hide();
+ }
+
+ emit(updateLayout());
+
+ showZone(zone->zoneIndex());
+}
+
+void ClockApplet::setTimerTo60()
+{
+// kdDebug() << "setTimerTo60" << endl;
+ disconnect(_timer, SIGNAL(timeout()), this, SLOT(setTimerTo60()));
+ _timer->changeInterval(60000);
+}
+
+void ClockApplet::setBackground()
+{
+ QColor globalBgroundColor = KApplication::palette().active().background();
+ QColor fgColor, bgColor;
+
+ if (!_clock)
+ return;
+
+ switch (_prefs->type())
+ {
+ case Prefs::EnumType::Plain:
+ bgColor = _prefs->plainBackgroundColor();
+ fgColor = _prefs->plainForegroundColor();
+ break;
+ case Prefs::EnumType::Analog:
+ bgColor = _prefs->analogBackgroundColor();
+ fgColor = _prefs->analogForegroundColor();
+ break;
+ case Prefs::EnumType::Fuzzy:
+ bgColor = _prefs->fuzzyBackgroundColor();
+ fgColor = _prefs->fuzzyForegroundColor();
+ break;
+ case Prefs::EnumType::Digital:
+ default:
+ bgColor = _prefs->digitalBackgroundColor();
+ fgColor = _prefs->digitalForegroundColor();
+ break;
+ }
+
+ if (!m_followBackgroundSetting)
+ _clock->widget()->setPaletteBackgroundColor(bgColor);
+ else
+ _clock->widget()->unsetPalette();
+ _clock->widget()->setPaletteForegroundColor(fgColor);
+
+ bgColor = _prefs->dateBackgroundColor();
+
+ // See if the clock wants to show the day of week.
+ // use same font/color as for date
+ showDayOfWeek = _clock->showDayOfWeek();
+ if (showDayOfWeek)
+ {
+ _dayOfWeek->setFont(_prefs->dateFont());
+
+ if (!m_dateFollowBackgroundSetting)
+ _dayOfWeek->setBackgroundColor(bgColor);
+ else
+ _dayOfWeek->unsetPalette();
+ _dayOfWeek->setPaletteForegroundColor(_prefs->dateForegroundColor());
+ }
+
+ // See if the clock wants to show the date.
+ showDate = _clock->showDate();
+ _date->setFont(_prefs->dateFont());
+
+ if (!m_dateFollowBackgroundSetting)
+ _date->setPaletteBackgroundColor(bgColor);
+ else
+ _date->unsetPalette();
+ _date->setPaletteForegroundColor(_prefs->dateForegroundColor());
+}
+
+void ClockApplet::globalPaletteChange()
+{
+ if (!m_dateFollowBackgroundSetting && !m_followBackgroundSetting)
+ return;
+
+ QColor globalBgroundColor = KApplication::palette().active().background();
+
+ if (m_dateFollowBackgroundSetting)
+ _prefs->setDateBackgroundColor(globalBgroundColor);
+
+ if (m_followBackgroundSetting)
+ {
+ // we need to makes sure we have the background color synced!
+ // otherwise when we switch color schemes again or restart kicker
+ // it might come back non-transparent
+ switch (_prefs->type())
+ {
+ case Prefs::EnumType::Plain:
+ _prefs->setPlainBackgroundColor(globalBgroundColor);
+ break;
+ case Prefs::EnumType::Analog:
+ _prefs->setAnalogBackgroundColor(globalBgroundColor);
+ break;
+ case Prefs::EnumType::Fuzzy:
+ _prefs->setFuzzyBackgroundColor(globalBgroundColor);
+ break;
+ case Prefs::EnumType::Digital:
+ default:
+ _prefs->setDigitalBackgroundColor(globalBgroundColor);
+ break;
+ }
+ }
+
+ _prefs->writeConfig();
+}
+
+void ClockApplet::slotUpdate()
+{
+ if (_lastDate != clockGetDate())
+ {
+ updateDateLabel();
+ }
+
+ if (m_updateOnTheMinute)
+ {
+ // catch drift so we're never more than a few s out
+ int seconds = clockGetTime().second();
+// kdDebug() << "checking for drift: " << seconds << endl;
+
+ if (seconds > 2)
+ {
+ connect(_timer, SIGNAL(timeout()), this, SLOT(setTimerTo60()));
+ _timer->changeInterval(((60 - seconds) * 1000) + 500);
+ }
+ }
+ _clock->updateClock();
+ KickerTip::Client::updateKickerTip();
+}
+
+void ClockApplet::slotCalendarDeleted()
+{
+ _calendar = 0L;
+ // don't reopen the calendar immediately ...
+ _disableCalendar = true;
+ QTimer::singleShot(100, this, SLOT(slotEnableCalendar()));
+
+ // we are free to show a tip know :)
+ installEventFilter(KickerTip::the());
+}
+
+
+void ClockApplet::slotEnableCalendar()
+{
+ _disableCalendar = false;
+}
+
+void ClockApplet::toggleCalendar()
+{
+ if (_calendar && !_disableCalendar)
+ {
+ // calls slotCalendarDeleted which does the cleanup for us
+ _calendar->close();
+ return;
+ }
+
+ if (_calendar || _disableCalendar)
+ {
+ return;
+ }
+
+ KickerTip::the()->untipFor(this);
+ removeEventFilter(KickerTip::the());
+
+ _calendar = new DatePicker(this, _lastDate, _prefs);
+ connect(_calendar, SIGNAL(destroyed()), SLOT(slotCalendarDeleted()));
+
+ QSize size = _prefs->calendarSize();
+
+ if (size != QSize())
+ {
+ _calendar->resize(size);
+ }
+ else
+ {
+ _calendar->adjustSize();
+ }
+
+ // make calendar fully visible
+ QPoint popupAt = KickerLib::popupPosition(popupDirection(),
+ _calendar,
+ this);
+ _calendar->move(popupAt);
+ _calendar->show();
+ _calendar->setFocus();
+}
+
+
+void ClockApplet::openContextMenu()
+{
+ if (!menu || !kapp->authorizeKAction("kicker_rmb"))
+ return;
+
+ menu->exec( QCursor::pos() );
+}
+
+void ClockApplet::contextMenuActivated(int result)
+{
+ if ((result >= 0) && (result < 100))
+ {
+ _prefs->setType(result);
+ _prefs->writeConfig();
+ reconfigure();
+ return;
+ };
+
+ if ((result >= 500) && (result < 600))
+ {
+ showZone(result-500);
+ zone->writeSettings();
+ return;
+ };
+
+ KProcess proc;
+ switch (result)
+ {
+ case 102:
+ preferences();
+ break;
+ case 103:
+ proc << locate("exe", "kdesu");
+ proc << "--nonewdcop";
+ proc << QString("%1 kde-clock.desktop --lang %2")
+ .arg(locate("exe", "kcmshell"))
+ .arg(KGlobal::locale()->language());
+ proc.start(KProcess::DontCare);
+ break;
+ case 104:
+ proc << locate("exe", "kcmshell");
+ proc << "kde-language.desktop";
+ proc.start(KProcess::DontCare);
+ break;
+ case 110:
+ preferences(true);
+ break;
+ } /* switch() */
+}
+
+void ClockApplet::aboutToShowContextMenu()
+{
+ bool bImmutable = config()->isImmutable();
+
+ menu->clear();
+ menu->insertTitle( SmallIcon( "clock" ), i18n( "Clock" ) );
+
+ KLocale *loc = KGlobal::locale();
+ QDateTime dt = QDateTime::currentDateTime();
+ dt = dt.addSecs(TZoffset);
+
+ KPopupMenu *copyMenu = new KPopupMenu( menu );
+ copyMenu->insertItem(loc->formatDateTime(dt), 201);
+ copyMenu->insertItem(loc->formatDate(dt.date()), 202);
+ copyMenu->insertItem(loc->formatDate(dt.date(), true), 203);
+ copyMenu->insertItem(loc->formatTime(dt.time()), 204);
+ copyMenu->insertItem(loc->formatTime(dt.time(), true), 205);
+ copyMenu->insertItem(dt.date().toString(), 206);
+ copyMenu->insertItem(dt.time().toString(), 207);
+ copyMenu->insertItem(dt.toString(), 208);
+ copyMenu->insertItem(dt.toString("yyyy-MM-dd hh:mm:ss"), 209);
+ connect( copyMenu, SIGNAL( activated(int) ), this, SLOT( slotCopyMenuActivated(int) ) );
+
+ if (!bImmutable)
+ {
+ KPopupMenu *zoneMenu = new KPopupMenu( menu );
+ connect(zoneMenu, SIGNAL(activated(int)), SLOT(contextMenuActivated(int)));
+ for (int i = 0; i <= zone->remoteZoneCount(); i++)
+ {
+ if (i == 0)
+ {
+ zoneMenu->insertItem(i18n("Local Timezone"), 500 + i);
+ }
+ else
+ {
+ zoneMenu->insertItem(i18n(zone->zone(i).utf8()).replace("_", " "), 500 + i);
+ }
+ }
+ zoneMenu->setItemChecked(500 + zone->zoneIndex(),true);
+ zoneMenu->insertSeparator();
+ zoneMenu->insertItem(SmallIcon("configure"), i18n("&Configure Timezones..."), 110);
+
+ KPopupMenu *type_menu = new KPopupMenu(menu);
+ connect(type_menu, SIGNAL(activated(int)), SLOT(contextMenuActivated(int)));
+ type_menu->insertItem(i18n("&Plain"), Prefs::EnumType::Plain, 1);
+ type_menu->insertItem(i18n("&Digital"), Prefs::EnumType::Digital, 2);
+ type_menu->insertItem(i18n("&Analog"), Prefs::EnumType::Analog, 3);
+ type_menu->insertItem(i18n("&Fuzzy"), Prefs::EnumType::Fuzzy, 4);
+ type_menu->setItemChecked(_prefs->type(),true);
+
+ menu->insertItem(i18n("&Type"), type_menu, 101, 1);
+ menu->insertItem(i18n("Show Time&zone"), zoneMenu, 110, 2);
+ if (kapp->authorize("user/root"))
+ {
+ menu->insertItem(SmallIcon("date"), i18n("&Adjust Date && Time..."), 103, 4);
+ }
+ menu->insertItem(SmallIcon("kcontrol"), i18n("Date && Time &Format..."), 104, 5);
+ }
+
+ menu->insertItem(SmallIcon("editcopy"), i18n("C&opy to Clipboard"), copyMenu, 105, 6);
+ if (!bImmutable)
+ {
+ menu->insertSeparator(7);
+ menu->insertItem(SmallIcon("configure"), i18n("&Configure Clock..."), 102, 8);
+ }
+}
+
+
+void ClockApplet::slotCopyMenuActivated( int id )
+{
+ QPopupMenu *m = (QPopupMenu *) sender();
+ QString s = m->text(id);
+ QApplication::clipboard()->setText(s);
+}
+
+QTime ClockApplet::clockGetTime()
+{
+ return QTime::currentTime().addSecs(TZoffset);
+}
+
+QDate ClockApplet::clockGetDate()
+{
+ return QDateTime::currentDateTime().addSecs(TZoffset).date();
+}
+
+void ClockApplet::showZone(int z)
+{
+ zone->setZone(z);
+ TZoffset = zone->calc_TZ_offset( zone->zone() );
+ updateDateLabel();
+ _clock->forceUpdate(); /* force repaint */
+}
+
+void ClockApplet::nextZone()
+{
+ zone->nextZone();
+ showZone(zone->zoneIndex());
+}
+
+void ClockApplet::prevZone()
+{
+ zone->prevZone();
+ showZone(zone->zoneIndex());
+}
+
+void ClockApplet::mousePressEvent(QMouseEvent *ev)
+{
+ switch (ev->button())
+ {
+ case QMouseEvent::LeftButton:
+ toggleCalendar();
+ break;
+ case QMouseEvent::RightButton:
+ openContextMenu();
+ break;
+ case QMouseEvent::MidButton:
+ nextZone();
+ QToolTip::remove(_clock->widget());
+ break;
+ default:
+ break;
+ }
+}
+
+void ClockApplet::wheelEvent(QWheelEvent* e)
+{
+ if (e->delta() < 0)
+ {
+ prevZone();
+ }
+ else
+ {
+ nextZone();
+ }
+
+ QToolTip::remove(_clock->widget());
+ KickerTip::Client::updateKickerTip();
+}
+
+// catch the mouse clicks of our child widgets
+bool ClockApplet::eventFilter( QObject *o, QEvent *e )
+{
+ if (( o == _clock->widget() || o == _date || o == _dayOfWeek) &&
+ e->type() == QEvent::MouseButtonPress )
+ {
+ mousePressEvent(static_cast<QMouseEvent*>(e) );
+ return true;
+ }
+
+ return KPanelApplet::eventFilter(o, e);
+}
+
+void ClockApplet::positionChange(Position p)
+{
+ KPanelApplet::positionChange(p);
+ reconfigure();
+}
+
+void ClockApplet::updateDateLabel(bool reLayout)
+{
+ _lastDate = clockGetDate();
+ _dayOfWeek->setText(KGlobal::locale()->calendar()->weekDayName(_lastDate));
+
+ if (zone->zoneIndex() != 0)
+ {
+ QString zone_s = i18n(zone->zone().utf8());
+ _date->setText(zone_s.mid(zone_s.find('/') + 1).replace("_", " "));
+ _date->setShown(true);
+ }
+ else
+ {
+ QString dateStr = KGlobal::locale()->formatDate(_lastDate, true);
+ _date->setText(dateStr);
+ _date->setShown(showDate);
+ }
+
+ if (reLayout)
+ {
+ if (_calendar && _lastDate != _calendar->date())
+ {
+ _calendar->setDate(_lastDate);
+ }
+
+ m_layoutTimer->stop();
+ m_layoutTimer->start(m_layoutDelay, true);
+ }
+}
+
+void ClockApplet::updateKickerTip(KickerTip::Data& data)
+{
+ int zoneCount = zone->remoteZoneCount();
+
+ QString activeZone = zone->zone();
+ if (zoneCount == 0)
+ {
+ QString _time = KGlobal::locale()->formatTime(clockGetTime(),
+ _prefs->plainShowSeconds());
+ QString _date = KGlobal::locale()->formatDate(clockGetDate(), false);
+ data.message = _time;
+ data.subtext = _date;
+
+ if (!activeZone.isEmpty())
+ {
+ activeZone = i18n(activeZone.utf8());
+ data.subtext.append("<br>").append(activeZone.mid(activeZone.find('/') + 1).replace("_", " "));
+ }
+ }
+ else
+ {
+ int activeIndex = zone->zoneIndex();
+
+ for (int i = 0; i <= zone->remoteZoneCount(); i++)
+ {
+ QString m_zone = zone->zone(i);
+ TZoffset = zone->calc_TZ_offset(m_zone);
+
+ if (!m_zone.isEmpty())
+ {
+ m_zone = i18n(m_zone.utf8()); // ensure it gets translated
+ }
+
+ QString _time = KGlobal::locale()->formatTime(clockGetTime(),
+ _prefs->plainShowSeconds());
+ QString _date = KGlobal::locale()->formatDate(clockGetDate(), false);
+
+ if (activeIndex == i)
+ {
+ data.message = m_zone.mid(m_zone.find('/') + 1).replace("_", " ");
+ data.message += " " + _time + "<br>" + _date;
+ }
+ else
+ {
+ if (i == 0)
+ {
+ data.subtext += "<b>" + i18n("Local Timezone") + "</b>";
+ }
+ else
+ {
+ data.subtext += "<b>" + m_zone.mid(m_zone.find('/') + 1).replace("_", " ") + "</b>";
+ }
+ data.subtext += " " + _time + ", " + _date + "<br>";
+ }
+ }
+
+ TZoffset = zone->calc_TZ_offset(activeZone);
+ }
+
+ data.icon = DesktopIcon("date", KIcon::SizeMedium);
+ data.direction = popupDirection();
+ data.duration = 4000;
+}
+
+void ClockApplet::fixupLayout()
+{
+ m_layoutDelay = 0;
+
+ // ensure we have the right widget line up in horizontal mode
+ // when we are showing date beside the clock
+ // this fixes problems triggered by having the date first
+ // because of the date format (e.g. YY/MM/DD) and then hiding
+ // the date
+ if (orientation() == Qt::Horizontal && height() < 32)
+ {
+ bool mustShowDate = showDate || (zone->zoneIndex() != 0);
+
+ if (!mustShowDate && !showDayOfWeek)
+ {
+ _clock->widget()->move(0,0);
+ }
+
+ int dayWidth = 0;
+ if (!showDayOfWeek)
+ {
+ _dayOfWeek->move(_clock->widget()->width() + 4, 0);
+ }
+ else
+ {
+ dayWidth = _dayOfWeek->width();
+ }
+
+ if (!showDate)
+ {
+ _date->move(_clock->widget()->width() + dayWidth + 4, 0);
+ }
+ }
+
+ emit updateLayout();
+}
+
+int ClockApplet::type()
+{
+ return _prefs->type();
+}
+
+ClockAppletToolTip::ClockAppletToolTip( ClockApplet* clock )
+ : QToolTip( clock ),
+ m_clock( clock )
+{
+}
+
+void ClockAppletToolTip::maybeTip( const QPoint & /*point*/ )
+{
+ QString tipText;
+ if ( (m_clock->type() == Prefs::EnumType::Fuzzy) ||
+ (m_clock->type() == Prefs::EnumType::Analog) )
+ {
+ // show full time (incl. hour) as tooltip for Fuzzy clock
+ tipText = KGlobal::locale()->formatDateTime(QDateTime::currentDateTime().addSecs(m_clock->TZoffset));
+ }
+ else
+ {
+ tipText = KGlobal::locale()->formatDate(m_clock->clockGetDate());
+ }
+
+ if (m_clock->timezones() && m_clock->timezones()->zoneIndex() > 0)
+ {
+ tipText += "\n" + i18n("Showing time for %1").arg(i18n(m_clock->timezones()->zone().utf8()), false);
+ }
+
+ tip(m_clock->geometry(), tipText);
+}
+
+//************************************************************
+
+#include "clock.moc"
diff --git a/kicker/applets/clock/clock.h b/kicker/applets/clock/clock.h
new file mode 100644
index 000000000..efa67be46
--- /dev/null
+++ b/kicker/applets/clock/clock.h
@@ -0,0 +1,348 @@
+/*****************************************************************
+
+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 __CLOCK_H
+#define __CLOCK_H
+
+#include <qlcdnumber.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <qguardedptr.h>
+#include <qdatetime.h>
+#include <qvbox.h>
+#include <qstringlist.h>
+#include <qtooltip.h>
+#include <qevent.h>
+
+#include <dcopobject.h>
+#include <kpanelapplet.h>
+#include <kdirwatch.h>
+#include <kconfigdialog.h>
+
+#include <kickertip.h>
+#include "settings.h"
+#include "kshadowengine.h"
+
+class QTimer;
+class QBoxLayout;
+class DatePicker;
+class QPixmap;
+class Zone;
+class KPopupMenu;
+class Prefs;
+class ClockApplet;
+
+namespace KIO
+{
+ class Job;
+}
+
+class DigitalWidget;
+class AnalogWidget;
+class FuzzyWidget;
+class ClockApplet;
+class KConfigDialogManager;
+class SettingsWidgetImp;
+
+class SettingsWidgetImp : public SettingsWidget
+{
+ Q_OBJECT
+
+ public:
+ SettingsWidgetImp(Prefs *p=0,
+ Zone *z=0,
+ QWidget* parent=0,
+ const char* name=0,
+ WFlags fl=0);
+ public slots:
+ void OkApply();
+
+ private:
+ Prefs *prefs;
+ Zone *zone;
+};
+
+class KConfigDialogSingle : public KConfigDialog
+{
+ Q_OBJECT
+
+ public:
+ KConfigDialogSingle(Zone *zone,
+ QWidget *parent=0,
+ const char *name=0,
+ Prefs *prefs=0,
+ KDialogBase::DialogType dialogType = KDialogBase::IconList,
+ bool modal=false);
+
+ SettingsWidgetImp* settings;
+
+ void updateSettings();
+ void updateWidgets();
+ void updateWidgetsDefault();
+
+ protected slots:
+ void selectPage(int p);
+ void dateToggled();
+
+ private:
+ DigitalWidget *digitalPage;
+ AnalogWidget *analogPage;
+ FuzzyWidget *fuzzyPage;
+ Prefs *_prefs;
+};
+
+/**
+ * Base class for all clock types
+ */
+class ClockWidget
+{
+ public:
+ ClockWidget(ClockApplet *applet, Prefs *prefs);
+ virtual ~ClockWidget();
+
+ virtual QWidget* widget()=0;
+ virtual int preferedWidthForHeight(int h) const =0;
+ virtual int preferedHeightForWidth(int w) const =0;
+ virtual void updateClock()=0;
+ virtual void forceUpdate() { _force = true; updateClock(); }
+ virtual void loadSettings()=0;
+ virtual bool showDate()=0;
+ virtual bool showDayOfWeek()=0;
+
+ protected:
+ ClockApplet *_applet;
+ Prefs *_prefs;
+ QTime _time;
+ bool _force;
+};
+
+
+class PlainClock : public QLabel, public ClockWidget
+{
+ Q_OBJECT
+
+ public:
+ PlainClock(ClockApplet *applet, Prefs *prefs, QWidget *parent=0, const char *name=0);
+
+ QWidget* widget() { return this; }
+ int preferedWidthForHeight(int h) const;
+ int preferedHeightForWidth(int w) const;
+ void updateClock();
+ void loadSettings();
+ bool showDate();
+ bool showDayOfWeek();
+
+ protected:
+ void paintEvent(QPaintEvent *e);
+ void drawContents(QPainter *p);
+
+ QString _timeStr;
+};
+
+
+class DigitalClock : public QLCDNumber, public ClockWidget
+{
+ Q_OBJECT
+
+ public:
+ DigitalClock(ClockApplet *applet, Prefs *prefs, QWidget *parent=0, const char *name=0);
+ ~DigitalClock();
+
+ QWidget* widget() { return this; }
+ int preferedWidthForHeight(int h) const;
+ int preferedHeightForWidth(int w) const;
+ void updateClock();
+ void loadSettings();
+ bool showDate();
+ bool showDayOfWeek();
+
+ protected:
+ void paintEvent( QPaintEvent*);
+ void drawContents( QPainter * p);
+ void resizeEvent ( QResizeEvent *ev);
+
+ QPixmap *_buffer;
+ QString _timeStr;
+ QPixmap lcdPattern;
+};
+
+
+class AnalogClock : public QFrame, public ClockWidget
+{
+ Q_OBJECT
+
+ public:
+ AnalogClock(ClockApplet *applet, Prefs *prefs, QWidget *parent=0, const char *name=0);
+ ~AnalogClock();
+
+ QWidget* widget() { return this; }
+ int preferedWidthForHeight(int h) const { return h; }
+ int preferedHeightForWidth(int w) const { return w; }
+ void updateClock();
+ void loadSettings();
+ bool showDate();
+ bool showDayOfWeek();
+
+ protected:
+ virtual void paintEvent(QPaintEvent *);
+ void styleChange(QStyle&);
+ void initBackgroundPixmap();
+
+ QPixmap *_spPx;
+ QPixmap lcdPattern;
+ int _bgScale;
+};
+
+
+class FuzzyClock : public QFrame, public ClockWidget
+{
+ Q_OBJECT
+
+ public:
+ FuzzyClock(ClockApplet *applet, Prefs* prefs, QWidget *parent=0, const char *name=0);
+
+ QWidget* widget() { return this; }
+ int preferedWidthForHeight(int h) const;
+ int preferedHeightForWidth(int w) const;
+ void updateClock();
+ void loadSettings();
+ bool showDate();
+ bool showDayOfWeek();
+
+ public slots:
+ void deleteMyself();
+
+ protected:
+ virtual void drawContents(QPainter *p);
+
+ QStringList hourNames;
+ QStringList normalFuzzy;
+ QStringList normalFuzzyOne;
+ QStringList dayTime;
+
+ QString _timeStr;
+
+ private:
+ bool alreadyDrawing;
+};
+
+class ClockAppletToolTip : public QToolTip
+{
+ public:
+ ClockAppletToolTip( ClockApplet* clock );
+
+ protected:
+ virtual void maybeTip( const QPoint & );
+
+ private:
+ ClockApplet *m_clock;
+};
+
+class ClockApplet : public KPanelApplet, public KickerTip::Client, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+ friend class ClockAppletToolTip;
+
+ public:
+ ClockApplet(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ ~ClockApplet();
+
+ int widthForHeight(int h) const;
+ int heightForWidth(int w) const;
+ void preferences();
+ void preferences(bool timezone);
+ int type();
+ Orientation getOrientation() { return orientation(); }
+ void resizeRequest() { emit(updateLayout()); }
+ const Zone* timezones() { return zone; }
+
+ QTime clockGetTime();
+ QDate clockGetDate();
+
+ virtual void updateKickerTip(KickerTip::Data&);
+
+ KTextShadowEngine *shadowEngine();
+
+ k_dcop:
+ void reconfigure();
+
+ protected slots:
+ void slotReconfigure() { reconfigure(); }
+ void slotUpdate();
+ void slotCalendarDeleted();
+ void slotEnableCalendar();
+ void slotCopyMenuActivated( int id );
+ void contextMenuActivated(int result);
+ void aboutToShowContextMenu();
+ void fixupLayout();
+ void globalPaletteChange();
+ void setTimerTo60();
+
+ protected:
+ void toggleCalendar();
+ void openContextMenu();
+ void updateDateLabel(bool reLayout = true);
+ void showZone(int z);
+ void nextZone();
+ void prevZone();
+ void updateFollowBackground();
+
+ void paletteChange(const QPalette &) { setBackground(); }
+ void setBackground();
+ void mousePressEvent(QMouseEvent *ev);
+ void wheelEvent(QWheelEvent* e);
+ bool eventFilter(QObject *, QEvent *);
+
+ virtual void positionChange(Position p);
+
+ QCString configFileName;
+ DatePicker *_calendar;
+ bool _disableCalendar;
+ ClockWidget *_clock;
+ QLabel *_date;
+ QLabel *_dayOfWeek;
+ QDate _lastDate;
+ QTimer *_timer;
+ QTimer *m_layoutTimer;
+ int m_layoutDelay;
+ bool m_followBackgroundSetting;
+ bool m_dateFollowBackgroundSetting;
+ int TZoffset;
+
+ // settings
+ Prefs *_prefs;
+ Zone *zone;
+ bool showDate;
+ bool showDayOfWeek;
+ bool m_updateOnTheMinute;
+ QStringList _remotezonelist;
+ KPopupMenu* menu;
+ ClockAppletToolTip m_tooltip;
+ KTextShadowEngine *m_shadowEngine;
+};
+
+
+#endif
diff --git a/kicker/applets/clock/clockapplet.desktop b/kicker/applets/clock/clockapplet.desktop
new file mode 100644
index 000000000..6dda8818a
--- /dev/null
+++ b/kicker/applets/clock/clockapplet.desktop
@@ -0,0 +1,151 @@
+[Desktop Entry]
+Type=Plugin
+Icon=clock
+Name=Clock
+Name[af]=Horlosie
+Name[ar]=الساعة
+Name[az]=Saat
+Name[be]=Гадзіннік
+Name[bg]=Часовник
+Name[bn]=ঘড়ি
+Name[br]=Eurier
+Name[bs]=Sat
+Name[ca]=Rellotge
+Name[cs]=Hodiny
+Name[csb]=Zédżer
+Name[cy]=Cloc
+Name[da]=Ur
+Name[de]=Uhr
+Name[el]=Ρολόι
+Name[eo]=Horloĝo
+Name[es]=Reloj
+Name[et]=Kell
+Name[eu]=Erlojua
+Name[fa]=ساعت
+Name[fi]=Kello
+Name[fr]=Horloge
+Name[fy]=Klok
+Name[ga]=Clog
+Name[gl]=Reloxo
+Name[he]=שעון
+Name[hi]=घड़ी
+Name[hr]=Sat
+Name[hu]=Óra
+Name[id]=Jam
+Name[is]=Klukka
+Name[it]=Orologio
+Name[ja]=時計
+Name[ka]=საათი
+Name[kk]=Сағат
+Name[km]=នាឡិកា
+Name[ko]=시계
+Name[lo]=ໂມງ
+Name[lt]=Laikrodis
+Name[lv]=Pulkstenis
+Name[mk]=Часовник
+Name[mn]=Цаг
+Name[ms]=Jam
+Name[mt]=Arloġġ
+Name[nb]=Klokke
+Name[nds]=Klock
+Name[ne]=घडी
+Name[nl]=Klok
+Name[nn]=Klokke
+Name[nso]=Sesupanako
+Name[oc]=Rellotge
+Name[pa]=ਘੜੀ
+Name[pl]=Zegar
+Name[pt]=Relógio
+Name[pt_BR]=Relógio
+Name[ro]=Ceas
+Name[ru]=Часы
+Name[rw]=Isaha
+Name[se]=Diibmu
+Name[sk]=Hodiny
+Name[sl]=Ura
+Name[sr]=Часовник
+Name[sr@Latn]=Časovnik
+Name[ss]=Liwashi
+Name[sv]=Klocka
+Name[ta]=கடிகாரம்
+Name[te]=గడియారం
+Name[tg]=Соат
+Name[th]=นาฬิกา
+Name[tr]=Saat
+Name[tt]=Säğät
+Name[uk]=Годинник
+Name[uz]=Soat
+Name[uz@cyrillic]=Соат
+Name[ven]=Tshifhinga
+Name[vi]=Đồng hồ
+Name[wa]=Ôrlodje
+Name[xh]=Ikloko
+Name[zh_CN]=时钟
+Name[zh_TW]=時鐘
+Name[zu]=Iwashi
+
+Comment=An analog and digital clock
+Comment[af]='n Analoog en digitale horlosie
+Comment[ar]= ساعة رقمية و عادية
+Comment[be]=Аналагавы і лічбавы гадзіннік
+Comment[bg]=Системен аплет за показване на датата и часа
+Comment[bn]=একটি অ্যানালগ এবং ডিজিটাল ঘড়ি
+Comment[bs]=Analogni i digitalni sat
+Comment[ca]=Un rellotge digital i analògic
+Comment[cs]=Applet s analogovými a digitálními hodinami
+Comment[csb]=Analogòwi ë cyfrowi zédżer
+Comment[da]=Et analogt og digitalt ur
+Comment[de]=Eine analoge und digitale Uhr
+Comment[el]=Ένα αναλογικό και ψηφιακό ρολόι
+Comment[en_GB]=An analogue and digital clock
+Comment[eo]=Analoga kaj cifereca horloĝo
+Comment[es]=Reloj analógico/digital
+Comment[et]=Analoog- ja digitaalkell
+Comment[eu]=Erloju analogiko eta digitala
+Comment[fa]=ساعت قیاسی و رقمی
+Comment[fi]=Analoginen ja digitaalinen kello
+Comment[fr]=Une horloge numérique et analogique
+Comment[fy]=In analoge en digitale klok
+Comment[ga]=Clog analógach agus digiteach
+Comment[gl]=Unha applet cun reloxo analóxico e dixital.
+Comment[he]=שעון אנלוגי ודיגיטלי
+Comment[hr]=Analogni i digitalni sat
+Comment[hu]=Egy analóg/digitális óra kisalkalmazásként
+Comment[is]=Forrit sem birtir stafræna klukku eða skífuklukku
+Comment[it]=Un orologio digitale o analogico
+Comment[ja]=アナログ時計とデジタル時計
+Comment[ka]=ანალოგური და ციფრული საათი
+Comment[kk]=Тілді немесе цифрлық сағат
+Comment[km]=នាឡិកា​អាណាឡូក និង​ឌីជីថល
+Comment[lt]=Analoginis ir skaitmeninis laikrodis
+Comment[mk]=Аналоген и дигитален часовник
+Comment[nb]=En analog og digital klokke for panelet.
+Comment[nds]=En analoog oder digitaal Klock
+Comment[ne]=एनालग र डिजिटल घडी
+Comment[nl]=Een analoge en digitale klok
+Comment[nn]=Ei analog og digital klokke
+Comment[pa]=ਇੱਕ ਐਨਾਲਾਗ ਤੇ ਡਿਜ਼ੀਟਲ ਘੜੀ ਹੈ।
+Comment[pl]=Zegar analogowy i cyfrowy
+Comment[pt]=Um relógio analógico e digital
+Comment[pt_BR]=Um relógio analógico e digital
+Comment[ro]=Un ceas analogic și digital
+Comment[ru]=Аплет аналоговых и цифровых часов
+Comment[se]=Analogálaš ja digitalálaš diibmo
+Comment[sk]=Analógové a digitálne hodiny.
+Comment[sl]=Analogna in digitalna ura
+Comment[sr]=Аналогни и дигитални часовник
+Comment[sr@Latn]=Analogni i digitalni časovnik
+Comment[sv]=En analog och digital klocka
+Comment[te]=ఎనాలాగ్ మరయూ డిజిటల్ గడియారం
+Comment[th]=นาฬิกาแบบเข็มและแบบตัวเลข
+Comment[tr]=Bir sayısal ve analog saat programcığı
+Comment[uk]=Аналоговий або цифровий годинник
+Comment[uz]=Analog va raqamli soat
+Comment[uz@cyrillic]=Аналог ва рақамли соат
+Comment[vi]=Đồng hồ thường và đồng hồ điện tử
+Comment[wa]=Ene analodjike ou didjitåle ôrlodje.
+Comment[zh_CN]=模拟和数字时钟面板小程序
+Comment[zh_TW]=一個小的類比或數字時鐘
+
+X-KDE-Library=clock_panelapplet
+X-KDE-UniqueApplet=false
diff --git a/kicker/applets/clock/clockapplet.kcfg b/kicker/applets/clock/clockapplet.kcfg
new file mode 100644
index 000000000..9b1ab3031
--- /dev/null
+++ b/kicker/applets/clock/clockapplet.kcfg
@@ -0,0 +1,191 @@
+<?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>
+ <kcfgfile arg="true"/>
+ <group name="General">
+ <entry name="Type" type="Enum">
+ <label>Clock type</label>
+ <choices>
+ <choice name="Plain"/>
+ <choice name="Digital"/>
+ <choice name="Analog"/>
+ <choice name="Fuzzy"/>
+ </choices>
+ <default>Digital</default>
+ </entry>
+ </group>
+ <group name="Date">
+ <entry name="DateForegroundColor" type="Color" key="Foreground_Color">
+ <label>Foreground color.</label>
+ <default code="true">KApplication::palette().active().text()</default>
+ </entry>
+ <entry name="DateBackgroundColor" type="Color" key="Background_Color">
+ <label>Foreground color.</label>
+ <default code="true">KApplication::palette().active().background()</default>
+ </entry>
+ <entry name="DateFont" type="Font" key="Font">
+ <label>Font for the clock.</label>
+ <code>
+QFont defFont=KGlobalSettings::generalFont();
+defFont.setPointSize(8);
+ </code>
+ <default code="true">defFont</default>
+ </entry>
+ </group>
+ <group name="Plain">
+ <entry name="PlainShowSeconds" type="Bool" key="Show_Seconds">
+ <label>Show seconds.</label>
+ <default>false</default>
+ </entry>
+ <entry name="PlainShowDate" type="Bool" key="Show_Date">
+ <label>Show date.</label>
+ <default>true</default>
+ </entry>
+ <entry name="PlainShowDayOfWeek" type="Bool" key="Show_DayOfWeek">
+ <label>Show day of week.</label>
+ <default>false</default>
+ </entry>
+ <entry name="PlainShowFrame" type="Bool" key="Show_Frame">
+ <label>Show frame.</label>
+ <default>false</default>
+ </entry>
+ <entry name="PlainFont" type="Font" key="Font">
+ <label>Font for the clock.</label>
+ <code>
+defFont=KGlobalSettings::generalFont();
+defFont.setPointSize(8);
+defFont.setBold(true);
+ </code>
+ <default code="true">defFont</default>
+ </entry>
+ <entry name="PlainForegroundColor" type="Color" key="Foreground_Color">
+ <label>Foreground color.</label>
+ <default code="true">KApplication::palette().active().text()</default>
+ </entry>
+ <entry name="PlainBackgroundColor" type="Color" key="Background_Color">
+ <label>Background color.</label>
+ <default code="true">KApplication::palette().active().background()</default>
+ </entry>
+ </group>
+ <group name="Digital">
+ <entry name="DigitalShowSeconds" type="Bool" key="Show_Seconds">
+ <label>Show seconds.</label>
+ <default>false</default>
+ </entry>
+ <entry name="DigitalShowDate" type="Bool" key="Show_Date">
+ <label>Show date.</label>
+ <default>false</default>
+ </entry>
+ <entry name="DigitalShowDayOfWeek" type="Bool" key="Show_DayOfWeek">
+ <label>Show day of week.</label>
+ <default>false</default>
+ </entry>
+ <entry name="DigitalShowFrame" type="Bool" key="Show_Frame">
+ <label>Show frame.</label>
+ <default>false</default>
+ </entry>
+ <entry name="DigitalForegroundColor" type="Color" key="Foreground_Color">
+ <label>Foreground color.</label>
+ <default code="true">KApplication::palette().active().text()</default>
+ </entry>
+ <entry name="DigitalBackgroundColor" type="Color" key="Background_Color">
+ <label>Background color.</label>
+ <default code="true">KApplication::palette().active().background()</default>
+ </entry>
+ <entry name="DigitalShadowColor" type="Color" key="Shadow_Color">
+ <label>Shadow color.</label>
+ <default code="true">KApplication::palette().active().mid()</default>
+ </entry>
+ <entry name="DigitalBlink" type="Bool" key="Blink">
+ <label>Blink</label>
+ <default>false</default>
+ </entry>
+ <entry name="DigitalLCDStyle" type="Bool" key="LCD_Style">
+ <label>LCD Style</label>
+ <default>false</default>
+ </entry>
+ </group>
+ <group name="Analog">
+ <entry name="AnalogShowSeconds" type="Bool" key="Show_Seconds">
+ <label>Show seconds.</label>
+ <default>true</default>
+ </entry>
+ <entry name="AnalogShowDate" type="Bool" key="Show_Date">
+ <label>Show date.</label>
+ <default>false</default>
+ </entry>
+ <entry name="AnalogShowDayOfWeek" type="Bool" key="Show_DayOfWeek">
+ <label>Show day of week.</label>
+ <default>false</default>
+ </entry>
+ <entry name="AnalogShowFrame" type="Bool" key="Show_Frame">
+ <label>Show frame.</label>
+ <default>false</default>
+ </entry>
+ <entry name="AnalogForegroundColor" type="Color" key="Foreground_Color">
+ <label>Foreground color.</label>
+ <default code="true">KApplication::palette().active().text()</default>
+ </entry>
+ <entry name="AnalogBackgroundColor" type="Color" key="Background_Color">
+ <label>Background color.</label>
+ <default code="true">KApplication::palette().active().background()</default>
+ </entry>
+ <entry name="AnalogShadowColor" type="Color" key="Shadow_Color">
+ <label>Shadow color.</label>
+ <default code="true">KApplication::palette().active().mid()</default>
+ </entry>
+ <entry name="AnalogLCDStyle" type="Bool" key="LCD_Style">
+ <label>LCD Style</label>
+ <default>true</default>
+ </entry>
+ <entry name="AnalogAntialias" type="Int" key="Antialias">
+ <label>Anti-Alias factor</label>
+ <default>0</default>
+ </entry>
+ </group>
+ <group name="Fuzzy">
+ <entry name="FuzzyShowDate" type="Bool" key="Show_Date">
+ <label>Show date.</label>
+ <default>true</default>
+ </entry>
+ <entry name="FuzzyShowDayOfWeek" type="Bool" key="Show_DayOfWeek">
+ <label>Show day of week.</label>
+ <default>false</default>
+ </entry>
+ <entry name="FuzzyShowFrame" type="Bool" key="Show_Frame">
+ <label>Show frame.</label>
+ <default>false</default>
+ </entry>
+ <entry name="FuzzyFont" type="Font" key="Font">
+ <label>Font for the clock.</label>
+ <code>
+defFont=KGlobalSettings::generalFont();
+ </code>
+ <default code="true">defFont</default>
+ </entry>
+ <entry name="FuzzyForegroundColor" type="Color" key="Foreground_Color">
+ <label>Foreground color.</label>
+ <default code="true">KApplication::palette().active().text()</default>
+ </entry>
+ <entry name="FuzzyBackgroundColor" type="Color" key="Background_Color">
+ <label>Background color.</label>
+ <default code="true">KApplication::palette().active().background()</default>
+ </entry>
+ <entry name="Fuzzyness" type="Int">
+ <label>Fuzzyness</label>
+ <default>1</default>
+ </entry>
+ </group>
+ <group name="Calendar">
+ <entry name="CalendarFullWindow" type="Bool" key="FullWindow">
+ <label>Show window frame</label>
+ <default>true</default>
+ </entry>
+ <entry name="CalendarSize" type="Size" key="Size">
+ <label>Default size of the calendar</label>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kicker/applets/clock/datepicker.cpp b/kicker/applets/clock/datepicker.cpp
new file mode 100644
index 000000000..0ea677e8a
--- /dev/null
+++ b/kicker/applets/clock/datepicker.cpp
@@ -0,0 +1,87 @@
+/************************************************************
+
+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 "datepicker.h"
+#include "prefs.h"
+
+#include <kdatepicker.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kwin.h>
+#include <netwm.h>
+
+DatePicker::DatePicker(QWidget *parent, const QDate& date, Prefs* _prefs)
+ : QVBox( parent, 0,
+ _prefs->calendarFullWindow()
+ ? (WType_TopLevel | WDestructiveClose |
+ WStyle_StaysOnTop)
+ : (WStyle_Customize | WStyle_NoBorder |
+ WType_TopLevel | WDestructiveClose |
+ WStyle_StaysOnTop) ),
+ prefs(_prefs)
+{
+ if (prefs->calendarFullWindow())
+ {
+ KWin::setType(winId(), NET::Utility);
+ setFrameStyle(QFrame::NoFrame);
+ }
+ else
+ {
+ setFrameStyle(QFrame::PopupPanel | QFrame::Raised);
+ }
+
+ KWin::setOnAllDesktops(handle(), true);
+ picker = new KDatePicker(this, date);
+ picker->setCloseButton(!_prefs->calendarFullWindow());
+
+ /* name and icon for kicker's taskbar */
+ setCaption(i18n("Calendar"));
+ setIcon(SmallIcon("date"));
+}
+
+void DatePicker::closeEvent(QCloseEvent* e)
+{
+ prefs->setCalendarSize(size());
+ QVBox::closeEvent(e);
+}
+
+void DatePicker::keyPressEvent(QKeyEvent *e)
+{
+ QVBox::keyPressEvent(e);
+
+ if (e->key() == Qt::Key_Escape)
+ {
+ close();
+ }
+}
+
+bool DatePicker::setDate(const QDate& date)
+{
+ return picker->setDate(date);
+}
+
+QDate DatePicker::date()
+{
+ return picker->date();
+}
+
diff --git a/kicker/applets/clock/datepicker.h b/kicker/applets/clock/datepicker.h
new file mode 100644
index 000000000..ee39261e0
--- /dev/null
+++ b/kicker/applets/clock/datepicker.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 __DATEPICKER_H
+#define __DATEPICKER_H
+
+#include <qvbox.h>
+#include <qdatetime.h>
+
+class KDatePicker;
+class Prefs;
+
+class DatePicker : public QVBox
+{
+ public:
+ DatePicker(QWidget*, const QDate&, Prefs* _prefs);
+ bool setDate(const QDate& date);
+ QDate date();
+
+ protected:
+ void closeEvent(QCloseEvent* e);
+ void keyPressEvent(QKeyEvent *e);
+
+ private:
+ KDatePicker *picker;
+ Prefs *prefs;
+};
+
+#endif
diff --git a/kicker/applets/clock/digital.ui b/kicker/applets/clock/digital.ui
new file mode 100644
index 000000000..256bca99b
--- /dev/null
+++ b/kicker/applets/clock/digital.ui
@@ -0,0 +1,305 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>DigitalWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>DigitalWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>553</width>
+ <height>251</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup2_3</cstring>
+ </property>
+ <property name="title">
+ <string>Display</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_DigitalShowDate</cstring>
+ </property>
+ <property name="text">
+ <string>Dat&amp;e</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_DigitalShowSeconds</cstring>
+ </property>
+ <property name="text">
+ <string>Seco&amp;nds</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_DigitalShowDayOfWeek</cstring>
+ </property>
+ <property name="text">
+ <string>Da&amp;y of week</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_DigitalBlink</cstring>
+ </property>
+ <property name="text">
+ <string>Blin&amp;king dots</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_DigitalShowFrame</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Frame</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer21</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Time</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_DigitalLCDStyle</cstring>
+ </property>
+ <property name="text">
+ <string>LCD look</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>Foreground_ColorL</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Foreground color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DigitalForegroundColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="2" column="1">
+ <property name="name">
+ <cstring>kcfg_DigitalBackgroundColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>backgroundDigitalLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DigitalBackgroundColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_DigitalForegroundColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_DigitalShadowColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>110</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>Shadow_ColorL</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Shadow color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DigitalShadowColor</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer75</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>kcfg_DigitalLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_DigitalBackgroundColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_DigitalLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>backgroundDigitalLabel</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_DigitalLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_DigitalForegroundColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_DigitalLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>Foreground_ColorL</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_DigitalLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_DigitalShadowColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_DigitalLCDStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>Shadow_ColorL</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>kcfg_DigitalShowDate</tabstop>
+ <tabstop>kcfg_DigitalShowSeconds</tabstop>
+ <tabstop>kcfg_DigitalBlink</tabstop>
+ <tabstop>kcfg_DigitalShowFrame</tabstop>
+ <tabstop>kcfg_DigitalLCDStyle</tabstop>
+ <tabstop>kcfg_DigitalForegroundColor</tabstop>
+ <tabstop>kcfg_DigitalShadowColor</tabstop>
+ <tabstop>kcfg_DigitalBackgroundColor</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">kfontrequester.h</include>
+ <include location="local" impldecl="in implementation">digital.ui.h</include>
+</includes>
+<slots>
+ <slot>kcfg_DigitalLCDStyle_stateChanged( int )</slot>
+</slots>
+<layoutdefaults spacing="3" margin="6"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kicker/applets/clock/fuzzy.ui b/kicker/applets/clock/fuzzy.ui
new file mode 100644
index 000000000..04e910340
--- /dev/null
+++ b/kicker/applets/clock/fuzzy.ui
@@ -0,0 +1,287 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>FuzzyWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>FuzzyWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>306</width>
+ <height>299</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Display</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_FuzzyShowDate</cstring>
+ </property>
+ <property name="text">
+ <string>Dat&amp;e</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_FuzzyShowDayOfWeek</cstring>
+ </property>
+ <property name="text">
+ <string>Da&amp;y of week</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_FuzzyShowFrame</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Frame</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Time</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="3" column="2">
+ <property name="name">
+ <cstring>spacer46</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Font:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2_3_4_3</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_FuzzyBackgroundColor</cstring>
+ </property>
+ </widget>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>51</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_4_3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Foreground color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_FuzzyForegroundColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_FuzzyBackgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_FuzzyForegroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="2">
+ <property name="name">
+ <cstring>Layout7_3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel4_3</cstring>
+ </property>
+ <property name="text">
+ <string>Low</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>kcfg_Fuzzyness</cstring>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>4</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>Both</enum>
+ </property>
+ <property name="tickInterval">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel5_3</cstring>
+ </property>
+ <property name="text">
+ <string>High</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel3_3</cstring>
+ </property>
+ <property name="text">
+ <string>Fuzziness:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_Fuzzyness</cstring>
+ </property>
+ </widget>
+ <widget class="KFontRequester" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>kcfg_FuzzyFont</cstring>
+ </property>
+ <property name="title">
+ <string>Date Font</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>kcfg_FuzzyShowDate</tabstop>
+ <tabstop>kcfg_FuzzyShowFrame</tabstop>
+ <tabstop>kcfg_Fuzzyness</tabstop>
+ <tabstop>kcfg_FuzzyForegroundColor</tabstop>
+ <tabstop>kcfg_FuzzyBackgroundColor</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">kfontrequester.h</include>
+</includes>
+<layoutdefaults spacing="3" margin="6"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kfontrequester.h</includehint>
+</includehints>
+</UI>
diff --git a/kicker/applets/clock/lcd.png b/kicker/applets/clock/lcd.png
new file mode 100644
index 000000000..32e5e90d8
--- /dev/null
+++ b/kicker/applets/clock/lcd.png
Binary files differ
diff --git a/kicker/applets/clock/prefs.kcfgc b/kicker/applets/clock/prefs.kcfgc
new file mode 100644
index 000000000..890209526
--- /dev/null
+++ b/kicker/applets/clock/prefs.kcfgc
@@ -0,0 +1,6 @@
+# Code generation options for kconfig_compiler
+File=clockapplet.kcfg
+ClassName=Prefs
+Singleton=false
+Mutators=Type,CalendarSize,CalendarFullWindow,DateBackgroundColor,PlainBackgroundColor,AnalogBackgroundColor,FuzzyBackgroundColor,DigitalBackgroundColor
+# MemberVariables=public
diff --git a/kicker/applets/clock/settings.ui b/kicker/applets/clock/settings.ui
new file mode 100644
index 000000000..215aa5433
--- /dev/null
+++ b/kicker/applets/clock/settings.ui
@@ -0,0 +1,515 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>SettingsWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>605</width>
+ <height>639</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabs</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Appearance</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="text">
+ <string>Clock type:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>clockCombo</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>Plain Clock</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Digital Clock</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Analog Clock</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Fuzzy Clock</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>kcfg_Type</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QWidgetStack">
+ <property name="name">
+ <cstring>widgetStack</cstring>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>page</cstring>
+ </property>
+ <attribute name="id">
+ <number>0</number>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup2_3_2_2</cstring>
+ </property>
+ <property name="title">
+ <string>Display</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_PlainShowDate</cstring>
+ </property>
+ <property name="text">
+ <string>Dat&amp;e</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_PlainShowSeconds</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Seconds</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_PlainShowDayOfWeek</cstring>
+ </property>
+ <property name="text">
+ <string>Da&amp;y of week</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_PlainShowFrame</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Frame</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Time</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel1_3_3_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Font:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel1_2_3_4_3_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_PlainBackgroundColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="1" column="2">
+ <property name="name">
+ <cstring>kcfg_PlainBackgroundColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="2">
+ <property name="name">
+ <cstring>kcfg_PlainForegroundColor</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel1_4_3_2_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Foreground color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_PlainForegroundColor</cstring>
+ </property>
+ </widget>
+ <spacer row="0" column="3">
+ <property name="name">
+ <cstring>spacer17</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>230</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KFontRequester" row="2" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>kcfg_PlainFont</cstring>
+ </property>
+ </widget>
+ <spacer row="3" column="3">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>dateBox</cstring>
+ </property>
+ <property name="title">
+ <string>Date</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_DateBackgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Foreground color:</string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_DateForegroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer15</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>343</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Font:</string>
+ </property>
+ </widget>
+ <widget class="KFontRequester">
+ <property name="name">
+ <cstring>kcfg_DateFont</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>100</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Timezones</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>City</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Comment</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>tzListView</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>A list of timezones known to your system. Press the middle mouse button on the clock in the taskbar and it shows you the time in the selected cities.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>tabs</tabstop>
+ <tabstop>kcfg_Type</tabstop>
+ <tabstop>kcfg_PlainShowDate</tabstop>
+ <tabstop>kcfg_PlainShowSeconds</tabstop>
+ <tabstop>kcfg_PlainShowFrame</tabstop>
+ <tabstop>kcfg_PlainForegroundColor</tabstop>
+ <tabstop>kcfg_PlainBackgroundColor</tabstop>
+ <tabstop>kcfg_DateBackgroundColor</tabstop>
+ <tabstop>kcfg_DateForegroundColor</tabstop>
+ <tabstop>kcfg_DateFont</tabstop>
+ <tabstop>tzListView</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">kfontrequester.h</include>
+</includes>
+<slots>
+ <slot>configureType()</slot>
+</slots>
+<layoutdefaults spacing="3" margin="6"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kfontrequester.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kfontrequester.h</includehint>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/kicker/applets/clock/zone.cpp b/kicker/applets/clock/zone.cpp
new file mode 100644
index 000000000..1d952a765
--- /dev/null
+++ b/kicker/applets/clock/zone.cpp
@@ -0,0 +1,180 @@
+/************************************************************
+
+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.
+
+******************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "zone.h"
+
+#include <kcolorbutton.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+#include <klocale.h>
+
+#include <qfile.h>
+#include <qtooltip.h>
+#include <klistview.h>
+
+#include <time.h>
+#include <stdlib.h> // for getenv()
+
+Zone::Zone(KConfig* conf):
+ config(conf),
+ _zoneIndex(0)
+{
+ _defaultTZ = ::getenv("TZ");
+ tzset();
+
+ config->setGroup("General");
+
+ /* default displayable timezones */
+ QString tzList = config->readEntry("RemoteZones");
+ _remotezonelist = QStringList::split(",", tzList);
+ setZone(config->readNumEntry("Initial_TZ", 0));
+}
+
+Zone::~Zone()
+{
+ writeSettings();
+}
+
+void Zone::setZone(int z)
+{
+ if (_zoneIndex > _remotezonelist.count())
+ z = 0;
+
+ _zoneIndex = z;
+}
+
+QString Zone::zone(int z) const
+{
+ return (z == 0 ? _defaultTZ : _remotezonelist[z-1]);
+}
+
+int Zone::calc_TZ_offset(const QString& zone, bool /* reset */)
+{
+ const KTimezone *z = zone.isEmpty() ? m_zoneDb.local() : m_zoneDb.zone(zone);
+
+ if (!z)
+ {
+ z = m_zoneDb.local();
+ }
+
+ if (z)
+ {
+ return -z->offset(Qt::LocalTime);
+ }
+
+ return 0;
+}
+
+void Zone::readZoneList(KListView *listView )
+{
+ const KTimezones::ZoneMap zones = m_zoneDb.allZones();
+ QMap<QString, QListViewItem*> KontinentMap;
+
+ listView->setRootIsDecorated(true);
+ for (KTimezones::ZoneMap::ConstIterator it = zones.begin(); it != zones.end(); ++it)
+ {
+ const KTimezone *zone = it.data();
+ QString tzName = zone->name();
+ QString comment = zone->comment();
+ if (!comment.isEmpty())
+ comment = i18n(comment.utf8());
+
+ const QStringList KontCity = QStringList::split("/", i18n(tzName.utf8()).replace("_", " "));
+ QListViewItem* Kontinent = KontinentMap[KontCity[0]];
+ if (!Kontinent) {
+ KontinentMap[KontCity[0]] = new QListViewItem(listView, KontCity[0]);
+ Kontinent = KontinentMap[KontCity[0]];
+ Kontinent->setExpandable(true);
+ }
+
+ QCheckListItem *li = new QCheckListItem(Kontinent, KontCity[1], QCheckListItem::CheckBox);
+ li->setText(1, comment);
+ li->setText(2, tzName); /* store complete path in ListView */
+
+ if (_remotezonelist.findIndex(tzName) != -1)
+ li->setOn(true);
+
+ // locate the flag from /l10n/%1/flag.png
+ // if not available select default "C" flag
+ QString flag = locate( "locale", QString("l10n/%1/flag.png").arg(zone->countryCode().lower()) );
+ if (!QFile::exists(flag))
+ flag = locate( "locale", "l10n/C/flag.png" );
+ if (QFile::exists(flag))
+ li->setPixmap(0, QPixmap(flag));
+ }
+}
+
+void Zone::getSelectedZonelist(KListView *listView)
+{
+ _remotezonelist.clear();
+
+ /* loop through all entries */
+ QListViewItem *root = listView->firstChild();
+ while (root) {
+ if (root->firstChild()) {
+ root = root->firstChild();
+ continue;
+ }
+
+ QCheckListItem *cl = (QCheckListItem*) root;
+ if (cl->isOn()) {
+ _remotezonelist.append(cl->text(2));
+ }
+
+ if (root->nextSibling()) {
+ root = root->nextSibling();
+ continue;
+ }
+ root = root->parent();
+ if (root)
+ root = root->nextSibling();
+ }
+}
+
+void Zone::nextZone()
+{
+ if (++_zoneIndex > _remotezonelist.count())
+ _zoneIndex = 0;
+}
+
+void Zone::prevZone()
+{
+ if (_zoneIndex == 0)
+ _zoneIndex = _remotezonelist.count();
+ else
+ --_zoneIndex;
+}
+
+void Zone::writeSettings()
+{
+ config->setGroup("General");
+ config->writeEntry("RemoteZones", _remotezonelist.join(","));
+ config->writeEntry("Initial_TZ",_zoneIndex);
+ config->sync();
+}
diff --git a/kicker/applets/clock/zone.h b/kicker/applets/clock/zone.h
new file mode 100644
index 000000000..34371c6ae
--- /dev/null
+++ b/kicker/applets/clock/zone.h
@@ -0,0 +1,62 @@
+/*****************************************************************
+
+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 __ZONE_H
+#define __ZONE_H
+
+#include <ktimezones.h>
+#include <qstringlist.h>
+
+class KConfig;
+class KListView;
+
+class Zone {
+
+public:
+ Zone(KConfig* conf);
+ ~Zone();
+
+ void writeSettings();
+
+ QString zone() const { return zone(_zoneIndex); };
+ QString zone(int z) const;
+ QStringList remoteZoneList() const { return _remotezonelist; };
+ int remoteZoneCount() { return _remotezonelist.count(); };
+ unsigned int zoneIndex() const { return _zoneIndex; }
+ void setZone(int z = 0);
+
+ void nextZone();
+ void prevZone();
+ int calc_TZ_offset(const QString& zone, bool reset=false);
+ void readZoneList(KListView *listView);
+ void getSelectedZonelist(KListView *listView);
+
+protected:
+ KTimezones m_zoneDb;
+ QStringList _remotezonelist;
+ KConfig *config;
+ QString _defaultTZ;
+ unsigned int _zoneIndex;
+};
+
+#endif
diff --git a/kicker/applets/launcher/ChangeLog b/kicker/applets/launcher/ChangeLog
new file mode 100644
index 000000000..b86dbd7aa
--- /dev/null
+++ b/kicker/applets/launcher/ChangeLog
@@ -0,0 +1,40 @@
+2004-06-15 Dan Bullok <[email protected]>
+ * Fixed flicker on drop/arrange.
+ * Can now drop more than one item at a time
+ * Empty panel now has size>0, so user can still drop icons on it.
+ * Fixed gcc 3.4 incompatibilities in EasyVector
+ * Fixed Drag and Drop Bugs :
+ * Crash when non-url dropped on quicklauncher
+ * Crash panel button dropped on quicklauncher
+ * Able to drop objects when quicklauncher is locked
+ * Add application context menu now inserts new app at current location
+
+2004-06-14 Dan Bullok <[email protected]>
+ * Fixed License statements (added email & pointer to COPYING)
+ * GUI changes made in previous commit.
+ * continued separating QuickURL and QuickButton.
+ * Rearranged menu items to make more sense
+
+2004-06-13 Dan Bullok <[email protected]>
+ * Fixes Bugs #42278, #55625, #63506, #67891, #76868, #79848, #80530 - also makes bacon & eggs for breakfast (toast & jam available for vegetarians)
+ * v2.0alpha
+ * Replaced most of the innards of QuickLauncher class.
+ * Icons are positions evenly across available space.
+ * Drag and drop works for all kicker widths.
+ * Visual Feedback of drop location
+ * Icon Size is user-definable. Sensible(?) values are used by default (Icons grow slightly as panel size increases. #icons per row for given panel size is Tiny,Small: 1, Normal: 2, Large:3, 110pix: 4).
+ * User can lock icon drag and drop (prevents accidentally screwing things up).
+ * Icons can either take up exactly the defined amount of space (ConserveSpace=true - this is the default), or grow slightly to take advantage of unused space.
+ * Spouts tons of debugging info to kdDebug (for now).
+
+2004-06-12 Dan Bullok <[email protected]>
+ * Fixed bug #75351: Tooltips change to filenames after rearranging applications in quicklauncher.
+ * Moved the URL->(menuID,service,kurl) functionality from the QuickButton constructor to its own class: QuickURL. Very similar code is used elsewhere in kicker, and should eventually be merged.
+ * Renamed some methods in QuickButton (getId -> menuId, getURL -> url) This matches the predominant KDE naming style.
+ * Groundwork laid for variable-sized buttons.
+
+2004-06-12 Dan Bullok <[email protected]>
+ * Changed member variable names: myVar -> _myVar.
+
+2004-06-12 Dan Bullok <[email protected]>
+ * Fixed formatting only - no code changes. There were a few conflicting indenting styles. I picked the one that looked like it was the oldest, and applied it to all the files.
diff --git a/kicker/applets/launcher/Makefile.am b/kicker/applets/launcher/Makefile.am
new file mode 100644
index 000000000..a101c6ccf
--- /dev/null
+++ b/kicker/applets/launcher/Makefile.am
@@ -0,0 +1,27 @@
+
+INCLUDES = -I$(top_srcdir)/kicker/libkicker -I$(top_srcdir)/kicker/kicker/ui $(all_includes)
+
+kde_module_LTLIBRARIES = launcher_panelapplet.la
+
+launcher_panelapplet_la_SOURCES = quicklauncher.skel quicklauncher.cpp quickbutton.cpp quickaddappsmenu.cpp flowgridmanager.cpp popularity.cpp configdlgbase.ui prefs.kcfgc configdlg.cpp
+
+METASOURCES = AUTO
+noinst_HEADERS = quicklauncher.h quickbutton.h quickaddappsmenu.h easyvector.h quickbuttongroup.h flowgridmanager.h popularity.h configdlg.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = quicklauncher.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+launcher_panelapplet_la_LDFLAGS = -module $(KDE_RPATH) $(all_libraries) -avoid-version -no-undefined
+launcher_panelapplet_la_LIBADD = ../../kicker/core/libkicker_core.la ../../kicker/buttons/libkicker_buttons.la \
+ ../../kicker/ui/libkicker_ui.la ../../libkicker/libkickermain.la $(LIB_KIO) \
+ $(LIB_KSYCOCA) $(LIB_KDEUI) $(LIB_KUTILS)
+
+kde_kcfg_DATA = launcherapplet.kcfg
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/quicklauncher.pot
+
+srcdoc:
+ kdoc -a -p -H -d $$HOME/web/src/quicklauncher quicklauncher *.h -lqt -lkdecore -lkdeui
diff --git a/kicker/applets/launcher/ToDo b/kicker/applets/launcher/ToDo
new file mode 100644
index 000000000..c7c852a36
--- /dev/null
+++ b/kicker/applets/launcher/ToDo
@@ -0,0 +1,8 @@
+TODO:
+ X * Geometry isn't always updated when panel size changes.
+ x * Remove debugging code (makes everything slow).
+ * Tooltip or other popup to alert user that buttons are locked (with a "don't show this again" checkbox).
+ * Docs.
+ * Use old quicklauncher config file if found. #77959
+ X * "Add application" context menu should add the new application at the index of the button that summoned the context menu.
+ X * Make sure to always have a little space to drop things on, even when there are no buttons.
diff --git a/kicker/applets/launcher/configdlg.cpp b/kicker/applets/launcher/configdlg.cpp
new file mode 100644
index 000000000..9950dd2a9
--- /dev/null
+++ b/kicker/applets/launcher/configdlg.cpp
@@ -0,0 +1,101 @@
+/*****************************************************************
+
+Copyright (c) 2005 Fred Schaettgen <[email protected]>
+
+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 <qcombobox.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "prefs.h"
+#include "configdlg.h"
+#include "configdlgbase.h"
+
+ConfigDlg::ConfigDlg(QWidget *parent, const char *name, Prefs *config,
+ int autoSize, KConfigDialog::DialogType dialogType,
+ int dialogButtons) :
+ KConfigDialog(parent, name, config, dialogType, dialogButtons),
+ m_settings(config),
+ m_autoSize(autoSize)
+{
+ m_ui = new ConfigDlgBase(this->plainPage());
+ addPage(m_ui, i18n("Configure"), "config");
+
+ m_ui->iconDim->clear();
+ m_ui->iconDim->insertItem(i18n("Automatic"));
+ for (int n=0; n<int(m_settings->iconDimChoices().size()); ++n)
+ {
+ m_ui->iconDim->insertItem(QString::number(
+ m_settings->iconDimChoices()[n]));
+ }
+ connect(m_ui->iconDim, SIGNAL(textChanged(const QString&)),
+ this, SLOT(updateButtons()));
+ updateWidgets();
+ m_oldIconDimText = m_ui->iconDim->currentText();
+ updateButtons();
+}
+
+void ConfigDlg::updateSettings()
+{
+ kdDebug() << "updateSettings" << endl;
+ KConfigDialog::updateSettings();
+ if (!hasChanged())
+ {
+ return;
+ }
+ m_oldIconDimText = m_ui->iconDim->currentText();
+ if (m_ui->iconDim->currentText() == i18n("Automatic"))
+ {
+ m_settings->setIconDim(m_autoSize);
+ }
+ else
+ {
+ m_settings->setIconDim(m_ui->iconDim->currentText().toInt());
+ }
+ settingsChangedSlot();
+}
+
+void ConfigDlg::updateWidgets()
+{
+ KConfigDialog::updateWidgets();
+ if (m_settings->iconDim() == m_autoSize)
+ {
+ m_ui->iconDim->setEditText(i18n("Automatic"));
+ }
+ else
+ {
+ m_ui->iconDim->setEditText(QString::number(m_settings->iconDim()));
+ }
+}
+
+void ConfigDlg::updateWidgetsDefault()
+{
+ KConfigDialog::updateWidgetsDefault();
+}
+
+bool ConfigDlg::hasChanged()
+{
+ return m_oldIconDimText != m_ui->iconDim->currentText() ||
+ KConfigDialog::hasChanged();
+}
+
+#include "configdlg.moc"
diff --git a/kicker/applets/launcher/configdlg.h b/kicker/applets/launcher/configdlg.h
new file mode 100644
index 000000000..1d03a9381
--- /dev/null
+++ b/kicker/applets/launcher/configdlg.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+
+Copyright (c) 2005 Fred Schaettgen <[email protected]>
+
+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 CONFIG_DLG_H
+#define CONFIG_DLG_H
+
+#include <kconfigdialog.h>
+
+class ConfigDlgBase;
+class Prefs;
+
+class ConfigDlg : public KConfigDialog
+{
+ Q_OBJECT
+
+public:
+ ConfigDlg(QWidget *parent, const char *name, Prefs *config, int autoSize,
+ KConfigDialog::DialogType dialogType, int dialogButtons);
+
+protected:
+ virtual bool hasChanged();
+
+protected slots:
+ virtual void updateSettings();
+ virtual void updateWidgets();
+ virtual void updateWidgetsDefault();
+
+private:
+ ConfigDlgBase *m_ui;
+ Prefs* m_settings;
+ int m_autoSize;
+ QString m_oldIconDimText;
+};
+
+#endif
diff --git a/kicker/applets/launcher/configdlgbase.ui b/kicker/applets/launcher/configdlgbase.ui
new file mode 100644
index 000000000..bfb1bc4e6
--- /dev/null
+++ b/kicker/applets/launcher/configdlgbase.ui
@@ -0,0 +1,273 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ConfigDlgBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ConfigDlgBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>371</width>
+ <height>338</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_DragEnabled</cstring>
+ </property>
+ <property name="text">
+ <string>Allow drag and drop</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Layout</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>kcfg_ConserveSpace</cstring>
+ </property>
+ <property name="text">
+ <string>Conserve space</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Do not expand icons to the size of the panel</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Icon size:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>iconDim</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer4_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>332</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>autoAdjustGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Most Popular Applications</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSlider" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>kcfg_HistoryHorizon</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="lineStep">
+ <number>0</number>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>140</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Short Term</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Long Term</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Maximum number of applications:</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_AutoAdjustMinItems</cstring>
+ </property>
+ </widget>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>50</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KIntSpinBox" row="2" column="1">
+ <property name="name">
+ <cstring>kcfg_AutoAdjustMaxItems</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Minimum number of applications:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>kcfg_AutoAdjustEnabled</cstring>
+ </property>
+ <property name="text">
+ <string>Add/remove applications based on their popularity</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>kcfg_AutoAdjustEnabled</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_AutoAdjustMinItems</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AutoAdjustEnabled</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_AutoAdjustMaxItems</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AutoAdjustEnabled</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_HistoryHorizon</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AutoAdjustEnabled</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textLabel1</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AutoAdjustEnabled</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textLabel2</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AutoAdjustEnabled</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textLabel3</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_AutoAdjustEnabled</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textLabel3_2</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/kicker/applets/launcher/easyvector.h b/kicker/applets/launcher/easyvector.h
new file mode 100644
index 000000000..cad9a2c86
--- /dev/null
+++ b/kicker/applets/launcher/easyvector.h
@@ -0,0 +1,147 @@
+/* Copyright 2004, Daniel Woods Bullok <[email protected]>
+ distributed under the terms of the
+ GNU GENERAL PUBLIC LICENSE Version 2 -
+ See the file kdebase/COPYING for details
+*/
+
+#ifndef __easyvector_h__
+#define __easyvector_h__
+#include <vector>
+#include <algorithm>
+#include <assert.h>
+
+template < class VALUE >
+class __Valtype {
+public:
+ typedef const VALUE& CVALUE;
+};
+
+
+template < class VALUE >
+class __Valtype< VALUE* > {
+public:
+ typedef const VALUE* CVALUE;
+};
+
+
+template <class VALUE, bool CHECKINDEX=true>
+class EasyVector: public std::vector< VALUE > {
+public:
+ typedef int Index;
+ typedef std::vector< Index > Indices;
+ typedef typename __Valtype< VALUE >::CVALUE CVALUE;
+
+ static const Index NotFound=-2;
+ static const Index Append=-1;
+
+ template < class PTYPE, class PROP_FUNC >
+ Index findProperty(const PTYPE &property,
+ PROP_FUNC prop_func) const;
+ Index findValue(CVALUE value) const;
+
+ Index lastIndex() const {return this->size()-1;}
+
+ void eraseAt(Index index);
+
+ VALUE takeFrom(Index index);
+
+ void insertAt(Index index,const VALUE &value);
+ void insertAt(Index index,const EasyVector &values);
+
+ bool isValidIndex(Index index) const;
+ bool isValidInsertIndex(Index index) const;
+ virtual ~EasyVector(){};
+
+
+protected:
+ void _checkInsertIndex(Index index) const;
+ void _checkIndex(Index index) const;
+ Index _convertInsertIndex(Index index) const;
+};
+
+
+template < class VALUE, bool CHECKINDEX >
+template < class PTYPE, class PROP_FUNC >
+typename EasyVector< VALUE, CHECKINDEX >::Index
+ EasyVector< VALUE, CHECKINDEX >::findProperty(const PTYPE &property,
+ PROP_FUNC prop_func) const
+{ typename EasyVector< VALUE, CHECKINDEX >::const_iterator i;
+ for (i=this->begin();i!=this->end();++i) {
+ if (prop_func(*i)==property)
+ return i-this->begin();
+ }
+ return NotFound;
+}
+
+
+template < class VALUE, bool CHECKINDEX >
+typename EasyVector< VALUE, CHECKINDEX >::Index
+ EasyVector< VALUE, CHECKINDEX >::findValue(CVALUE value) const
+{ typename EasyVector< VALUE, CHECKINDEX >::const_iterator i;
+ i=std::find(this->begin(),this->end(),value);
+ if (i==this->end()) return NotFound;
+ return i-this->begin();
+}
+
+
+template < class VALUE, bool CHECKINDEX >
+void EasyVector< VALUE, CHECKINDEX >::eraseAt(Index index)
+{ _checkIndex(index);
+ erase(this->begin()+index);
+}
+
+
+template < class VALUE, bool CHECKINDEX >
+VALUE EasyVector< VALUE, CHECKINDEX >::takeFrom(Index index)
+{ _checkIndex(index);
+ VALUE result=(*this)[index];
+ eraseAt(index);
+ return result;
+}
+
+
+template < class VALUE, bool CHECKINDEX >
+void EasyVector< VALUE, CHECKINDEX >::insertAt(EasyVector< VALUE, CHECKINDEX >::Index index,const VALUE &value)
+{ index=_convertInsertIndex(index);
+ _checkInsertIndex(index);
+ if (index==int(this->size())) {
+ this->push_back(value);
+ return;
+ }
+ insert(this->begin()+index,value);
+}
+
+
+template < class VALUE, bool CHECKINDEX >
+void EasyVector< VALUE, CHECKINDEX >::insertAt(EasyVector< VALUE, CHECKINDEX >::Index index,const EasyVector< VALUE, CHECKINDEX > &v)
+{ index=_convertInsertIndex(index);
+ _checkInsertIndex(index);
+ insert(this->begin()+index,v.begin(),v.end());
+}
+
+
+template < class VALUE, bool CHECKINDEX >
+bool EasyVector< VALUE, CHECKINDEX >::isValidIndex(EasyVector< VALUE, CHECKINDEX >::Index index) const
+{ return(0<=index && index<int(this->size()));}
+
+template < class VALUE, bool CHECKINDEX >
+bool EasyVector< VALUE, CHECKINDEX >::isValidInsertIndex(EasyVector< VALUE, CHECKINDEX >::Index index) const
+{ return(index==Append)||(0<=index && index<=int(this->size()));}
+
+template < class VALUE, bool CHECKINDEX >
+inline typename EasyVector< VALUE, CHECKINDEX >::Index EasyVector< VALUE, CHECKINDEX >::_convertInsertIndex(Index index) const
+{ if (index==Append) return this->size();
+ return index;
+}
+
+template < class VALUE, bool CHECKINDEX >
+void EasyVector< VALUE, CHECKINDEX >::_checkInsertIndex(Index index) const
+{ if (CHECKINDEX) assert (isValidInsertIndex(index));}
+
+template < class VALUE, bool CHECKINDEX >
+void EasyVector< VALUE, CHECKINDEX >::_checkIndex(Index index) const
+{ if (CHECKINDEX) assert (isValidIndex(index));}
+
+
+#endif
+
diff --git a/kicker/applets/launcher/flowgridmanager.cpp b/kicker/applets/launcher/flowgridmanager.cpp
new file mode 100644
index 000000000..b5715097b
--- /dev/null
+++ b/kicker/applets/launcher/flowgridmanager.cpp
@@ -0,0 +1,316 @@
+/* Copyright 2004, Daniel Woods Bullok <[email protected]>
+ distributed under the terms of the
+ GNU GENERAL PUBLIC LICENSE Version 2 -
+ See the file kdebase/COPYING for details
+*/
+
+#include "flowgridmanager.h"
+#include <kdebug.h>
+#ifdef DEBUG
+ #define DEBUGSTR kdDebug()
+#else
+ #define DEBUGSTR kndDebug()
+#endif
+
+
+FlowGridManager::FlowGridManager(QSize p_item_size,
+ QSize p_space_size,
+ QSize p_border_size,
+ QSize p_frame_size,
+ Qt::Orientation orient,
+ int num_items,
+ Slack slack_x,Slack slack_y)
+{
+ _pItemSize=p_item_size;
+ _pSpaceSize=p_space_size;
+ _pBorderSize=p_border_size;
+ _pFrameSize=p_frame_size;
+ _orientation=orient;
+ _numItems=num_items;
+ _slackX=slack_x;
+ _slackY=slack_y;
+ _conserveSpace=false;
+
+ _dirty=true;
+ _valid=false;
+}
+
+// set members.
+// These all set the _dirty flag if the new value is different.
+void FlowGridManager::setNumItems(int num_items)
+{ if (_numItems==num_items)
+ return;
+ _numItems=num_items; _dirty=true;
+}
+void FlowGridManager::setItemSize(QSize p_item_size)
+{ if (_pItemSize==p_item_size)
+ return;
+ _pItemSize=p_item_size; _dirty=true;
+}
+
+void FlowGridManager::setSpaceSize(QSize p_space_size)
+{ if (_pSpaceSize==p_space_size)
+ return;
+ _pSpaceSize=p_space_size; _dirty=true;
+}
+
+void FlowGridManager::setBorderSize(QSize p_border_size)
+{ if (_pBorderSize==p_border_size)
+ return;
+ _pBorderSize=p_border_size; _dirty=true;
+}
+
+void FlowGridManager::setFrameSize(QSize p_frame_size)
+{ if (_pFrameSize==p_frame_size)
+ return;
+ _pFrameSize=p_frame_size;
+ if (_pFrameSize.width()<=0) {
+ _orientation=Qt::Vertical;
+ }
+ if (_pFrameSize.height()<=0) {
+ _orientation=Qt::Horizontal;
+ }
+ _dirty=true;
+}
+
+void FlowGridManager::setOrientation(Qt::Orientation orient)
+{ if (orient==_orientation)
+ return;
+ _orientation=orient; _dirty=true;
+}
+
+void FlowGridManager::setSlack(Slack slack_x, Slack slack_y)
+{ if (slack_x==_slackX && slack_y==_slackY) return;
+ _slackX=slack_x; _slackY=slack_y; _dirty=true;}
+
+
+void FlowGridManager::setConserveSpace(bool conserve)
+{ if (_conserveSpace==conserve)
+ return;
+ _conserveSpace=conserve; _dirty=true;
+}
+
+
+
+// get members
+QSize FlowGridManager::itemSize() const
+{ _checkReconfigure(); return _itemSize;}
+
+QSize FlowGridManager::spaceSize() const
+{ _checkReconfigure(); return _spaceSize;}
+
+QSize FlowGridManager::borderSize() const
+{ _checkReconfigure(); return _borderSize;}
+
+QSize FlowGridManager::gridDim() const
+{ _checkReconfigure(); return _gridDim;}
+
+QSize FlowGridManager::gridSpacing() const
+{ _checkReconfigure(); return _gridSpacing;}
+
+QSize FlowGridManager::frameSize() const
+{ _checkReconfigure(); return _frameSize;}
+
+QPoint FlowGridManager::origin() const
+{ _checkReconfigure(); return _origin;}
+
+Qt::Orientation FlowGridManager::orientation() const
+{ _checkReconfigure(); return _orientation;}
+
+/*Slack FlowGridManager::slackX() const
+{ return _slackY;}
+
+Slack FlowGridManager::slackY() const
+{ return _slackY;}
+*/
+
+bool FlowGridManager::conserveSpace() const
+{ return _conserveSpace; }
+
+
+bool FlowGridManager::isValid() const
+{ _checkReconfigure(); return _valid;}
+
+QPoint FlowGridManager::posAtCell(int x,int y) const
+{ _checkReconfigure();
+ return _origin+QPoint(_gridSpacing.width()*x,_gridSpacing.height()*y);
+}
+
+QPoint FlowGridManager::pos(int i) const
+{ return posAtCell(cell(i).x(),cell(i).y());
+}
+
+QPoint FlowGridManager::cell(int index) const
+{ _checkReconfigure();
+ //assert((index>=0) && (index<_gridDim.width()*_gridDim.height()));
+ int x=index % _gridDim.width(),
+ y=index / _gridDim.width();
+ return QPoint(x,y);
+}
+
+
+
+
+// return height if orientation is Horizontal
+// return width if orientation is Vertical
+int FlowGridManager::_getHH(QSize size) const
+{ if (_orientation==Qt::Horizontal)
+ return size.height();
+ return size.width();
+}
+
+// return height if orientation is Vertical
+// return width if orientation is Horizontal
+int FlowGridManager::_getWH(QSize size) const
+{ if (_orientation==Qt::Horizontal)
+ return size.width();
+ return size.height();
+}
+
+// swap horizontal and vertical if orientation is Vertical, otherwise return arg
+QSize FlowGridManager::_swapHV(QSize hv) const
+{ if (_orientation==Qt::Horizontal)
+ return hv;
+ QSize temp=hv;
+ temp.transpose();
+ return temp;
+}
+
+
+// return the amount of slack when:
+// nitems = # of items
+// length = total length of space where items will be placed
+// item, space, border = length of respective entities
+int FlowGridManager::_slack(int nitems,int length,int item,int space,int border) const
+{ return length-(2*border)-(nitems-1)*space-nitems*item;}
+
+
+void FlowGridManager::_clear() const
+{
+ _borderSize=QSize(0,0);
+ _spaceSize=QSize(0,0);
+ _itemSize=QSize(0,0);
+ _gridDim=QSize(0,0);
+ _gridSpacing=QSize(0,0);
+ _origin=QPoint(0,0);
+ _frameSize=QSize(0,0);
+
+ _dirty=false;
+ _valid=false;
+}
+
+
+int FlowGridManager::indexNearest(QPoint p) const
+{ if (!isValid()) return -1;
+ QPoint c=(p-_origin)-QPoint(_spaceSize.width(),_spaceSize.height())/2;
+ int x=c.x()/_gridSpacing.width(),
+ y=c.y()/_gridSpacing.height();
+ int i= x+y*_gridDim.width();
+ if (i>_numItems) return -1;
+ return i;
+}
+
+
+
+// Redistribute the boxes
+void FlowGridManager::_reconfigure() const
+{ if ((!_pFrameSize.isValid()) ||
+ (!_pItemSize.isValid()) ||
+ _numItems==0 ) {
+ _clear();
+ return;
+ }
+ int height=_getHH(_pFrameSize),
+ pItemHeight=_getHH(_pItemSize),
+ pSpaceHeight=_getHH(_pSpaceSize),
+ pBorderHeight=_getHH(_pBorderSize),
+ spanlen=(height-2*pBorderHeight+pSpaceHeight)/(pItemHeight+pSpaceHeight);
+ int slack,iSlack;
+
+ if (spanlen==0) {
+ _dirty=false;
+ _valid=false;
+ return;
+ }
+ // figure out the number of spans required for all items
+ int numspans=_numItems/spanlen;
+ if (numspans*spanlen<_numItems) {
+ numspans++;
+ }
+
+ slack=_slack(spanlen,height,pItemHeight,pSpaceHeight,pBorderHeight); // total slack
+ iSlack=slack/spanlen; // slack per item
+ // Items pick up extra slack
+ if (_slackX==ItemSlack) pItemHeight+=iSlack;
+ slack=_slack(spanlen,height,pItemHeight,pSpaceHeight,pBorderHeight);
+
+ // space picks up extra slack
+ if (spanlen>1) {
+ iSlack=slack/(spanlen+1);
+ pSpaceHeight+=iSlack;
+ }
+
+ slack=_slack(spanlen,height,pItemHeight,pSpaceHeight,pBorderHeight);
+ iSlack=slack/2;
+ pBorderHeight+=iSlack;
+ if (_conserveSpace) {
+ _itemSize=_swapHV(QSize(_getWH(_pItemSize),pItemHeight));
+ _spaceSize=_swapHV(QSize(_getWH(_pSpaceSize),pSpaceHeight));
+ _borderSize=_swapHV(QSize(_getWH(_pBorderSize),pBorderHeight));
+ }
+ else {
+ _itemSize=_swapHV(QSize(pItemHeight,pItemHeight));
+ _spaceSize=_swapHV(QSize(pSpaceHeight,pSpaceHeight));
+ _borderSize=_swapHV(QSize(pBorderHeight,pBorderHeight));
+ }
+ _gridDim=_swapHV(QSize(numspans,spanlen));
+
+ _gridSpacing=_itemSize+_spaceSize;
+ _origin=QPoint(_borderSize.width(),_borderSize.height());
+ _frameSize=2*_borderSize+QSize(_gridDim.width()*_gridSpacing.width()-_spaceSize.width(),
+ _gridDim.height()*_gridSpacing.height()-_spaceSize.height());
+
+ _dirty=false;
+ _valid=true;
+}
+
+
+void FlowGridManager::dump()
+{
+ DEBUGSTR<<endl<<flush;
+
+ DEBUGSTR<<"_pItemSize=("<<_pItemSize.width()<<","<<_pItemSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_pSpaceSize=("<<_pSpaceSize.width()<<","<<_pSpaceSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_pBorderSize=("<<_pBorderSize.width()<<","<<_pBorderSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_pFrameSize=("<<_pFrameSize.width()<<","<<_pFrameSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_borderSize=("<<_borderSize.width()<<","<<_borderSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_spaceSize=("<<_spaceSize.width()<<","<<_spaceSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_itemSize=("<<_itemSize.width()<<","<<_itemSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_gridDim=("<<_gridDim.width()<<","<<_gridDim.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_gridSpacing=("<<_gridSpacing.width()<<","<<_gridSpacing.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_origin=("<<_origin.x()<<","<<_origin.y()<<")"<<endl<<flush;
+ DEBUGSTR<<"_frameSize=("<<_frameSize.width()<<","<<_frameSize.height()<<")"<<endl<<flush;
+ DEBUGSTR<<"_conserveSpace="<<_conserveSpace<<endl<<flush;
+
+ DEBUGSTR<<"_orientation="<<_orientation<<endl<<flush;
+ DEBUGSTR<<"_numItems="<<_numItems<<endl<<flush;
+ DEBUGSTR<<"_slackX="<<_slackX<<endl<<flush;
+ DEBUGSTR<<"_slackY="<<_slackY<<endl<<flush;
+ DEBUGSTR<<"_dirty="<<_dirty<<endl<<flush;
+ DEBUGSTR<<"_valid="<<_valid<<endl<<flush;
+ DEBUGSTR<<endl<<flush;
+}
+
+
+
+bool operator== ( const FlowGridManager & csg1, const FlowGridManager & csg2 )
+{
+ return csg1.gridDim()==csg2.gridDim() &&
+ csg1.origin()==csg2.origin() &&
+ csg1.gridSpacing()==csg2.gridSpacing() &&
+ csg1.frameSize()==csg2.frameSize();
+}
+
+
+
+
diff --git a/kicker/applets/launcher/flowgridmanager.h b/kicker/applets/launcher/flowgridmanager.h
new file mode 100644
index 000000000..9d100c74f
--- /dev/null
+++ b/kicker/applets/launcher/flowgridmanager.h
@@ -0,0 +1,99 @@
+/* Copyright 2004, Daniel Woods Bullok <[email protected]>
+ distributed under the terms of the
+ GNU GENERAL PUBLIC LICENSE Version 2 -
+ See the file kdebase/COPYING for details
+*/
+
+#ifndef __const_space_grid_h__
+#define __const_space_grid_h__
+
+#include <qnamespace.h>
+#include <qpoint.h>
+#include <qsize.h>
+
+
+class FlowGridManager {
+// Determine if two FlowGridManager objs have the same layout. They may or
+// may not have the same input parameters, but the resulting layout is identical.
+ friend bool operator== ( const FlowGridManager & gp1, const FlowGridManager & gp2 );
+
+public:
+ typedef enum {
+ ItemSlack,SpaceSlack,BorderSlack,NoSlack
+ } Slack;
+
+ FlowGridManager(QSize p_item_size=QSize(0,0),
+ QSize p_space_size=QSize(0,0),
+ QSize p_border_size=QSize(0,0),
+ QSize frame_size=QSize(0,0),
+ Qt::Orientation orient=Qt::Horizontal,
+ int num_items=0,
+ Slack slack_x=ItemSlack,
+ Slack slack_y=ItemSlack);
+
+
+ void setNumItems(int num_items);
+ void setItemSize(QSize item_size);
+ void setSpaceSize(QSize space_size);
+ void setBorderSize(QSize border_size);
+ void setOrientation(Qt::Orientation orient);
+ void setFrameSize(QSize frame_size);
+ void setSlack(Slack slack_x, Slack slack_y);
+ void setConserveSpace(bool conserve);
+
+
+ QSize itemSize() const;
+ QSize spaceSize() const;
+ QSize borderSize() const;
+ QSize gridDim() const;
+ QSize gridSpacing() const;
+ QSize frameSize() const;
+ QPoint origin() const;
+ Qt::Orientation orientation() const;
+ bool conserveSpace() const;
+
+// Slack slackX() const;
+// Slack slackY() const;
+
+ QPoint posAtCell(int x,int y) const;
+ QPoint pos(int i) const;
+ QPoint cell(int index) const;
+ bool isValid() const;
+ int indexNearest(QPoint p) const;
+
+ void dump();
+protected:
+ int _getHH(QSize size) const;
+ int _getWH(QSize size) const;
+ QSize _swapHV(QSize hv) const;
+ inline void _checkReconfigure() const;
+ int _slack(int nitems,int length,int item,int space,int border) const;
+ void _reconfigure() const;
+ void _clear() const;
+
+protected:
+ // user-definable data
+ QSize _pItemSize,_pSpaceSize,_pBorderSize,_pFrameSize;
+ Slack _slackX, _slackY;
+ bool _conserveSpace;
+ Qt::Orientation _orientation;
+ int _numItems;
+
+ // results
+ mutable QSize _itemSize, _spaceSize, _borderSize, _gridDim, _gridSpacing, _frameSize;
+ mutable QPoint _origin;
+
+ // status
+ mutable bool _dirty, _valid;
+
+};
+
+
+// reconfigure the grid if necessary.
+inline void FlowGridManager::_checkReconfigure() const
+{ if (!_dirty) return;
+ _reconfigure();
+}
+
+#endif
+
diff --git a/kicker/applets/launcher/launcherapplet.kcfg b/kicker/applets/launcher/launcherapplet.kcfg
new file mode 100644
index 000000000..3433bf437
--- /dev/null
+++ b/kicker/applets/launcher/launcherapplet.kcfg
@@ -0,0 +1,77 @@
+<?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" >
+ <kcfgfile arg="true"/>
+ <group name="General">
+ <entry name="ConserveSpace" type="Bool">
+ <label>Conserve Space</label>
+ <default>true</default>
+ </entry>
+ <entry name="DragEnabled" type="Bool">
+ <label>Drag Enabled</label>
+ <default>true</default>
+ </entry>
+ <entry name="IconDim" type="Int">
+ <label>Icon Size</label>
+ <default>0</default>
+ </entry>
+ <entry name="IconDimChoices" type="IntList">
+ <label>Offered Icon Sizes</label>
+ <default>16,20,24,28,32,48,64</default>
+ </entry>
+ <entry name="Buttons" type="StringList">
+ <label>Buttons</label>
+ <default>kde-Home.desktop,kde-konsole.desktop,kde-KControl.desktop,kde-Help.desktop,kde-kwrite.desktop</default>
+ </entry>
+ <entry name="VolatileButtons" type="StringList">
+ <label>Volatile Buttons</label>
+ <whatsthis>Buttons that can be removed dynamically if they become unpopular</whatsthis>
+ <default></default>
+ </entry>
+ <entry name="ShowVolatileButtonIndicator" type="Bool">
+ <label>Show frame for volatile buttons</label>
+ <default>true</default>
+ </entry>
+ <entry name="AutoAdjustEnabled" type="Bool">
+ <label>Auto Adjust Enabled</label>
+ <default>false</default>
+ </entry>
+ <entry name="AutoAdjustMinItems" type="Int">
+ <label>Minimum Number of Items</label>
+ <min>0</min>
+ <default>3</default>
+ </entry>
+ <entry name="AutoAdjustMaxItems" type="Int">
+ <label>Maximum Number of Items</label>
+ <min>0</min>
+ <default>6</default>
+ </entry>
+ <entry name="HistoryHorizon" type="Int">
+ <label>History Weight</label>
+ <min>0</min>
+ <max>100</max>
+ <default>70</default>
+ </entry>
+ </group>
+ <group name="PopularityData">
+ <entry name="ServiceCacheSize" key="ServiceCacheSize" type="Int">
+ <label>Service Cache Size</label>
+ <whatsthis>Number of services to remember</whatsthis>
+ <default>500</default>
+ </entry>
+ <entry name="ServiceNames" key="ServiceNames" type="StringList">
+ <label>Service Names</label>
+ <whatsthis>Name of known services</whatsthis>
+ </entry>
+ <entry name="ServiceInspos" key="ServiceInspos" type="IntList">
+ <label>Service Insertion Positions</label>
+ <whatsthis>Position where services are inserted when they regain popularity</whatsthis>
+ </entry>
+ <entry name="ServiceHistories" key="ServiceHistories" type="StringList">
+ <label>Service History Data</label>
+ <whatsthis>History Data used to determine the popularity of a service</whatsthis>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kicker/applets/launcher/popularity.cpp b/kicker/applets/launcher/popularity.cpp
new file mode 100644
index 000000000..3bfcdd872
--- /dev/null
+++ b/kicker/applets/launcher/popularity.cpp
@@ -0,0 +1,424 @@
+/*****************************************************************
+
+Copyright (c) 2005 Fred Schaettgen <[email protected]>
+
+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 "popularity.h"
+#include "prefs.h"
+#include <assert.h>
+#include <algorithm>
+#include <iterator>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <list>
+#include <set>
+#include <map>
+#include <cmath>
+#include <vector>
+
+using namespace std;
+
+class PopularityStatisticsImpl
+{
+public:
+ struct SingleFalloffHistory
+ {
+ public:
+ // fallof is a number between 0 and 1. The popularity of
+ // each service is multiplied with the falloff value
+ // every time a service is used. Only the used service
+ // gets also 1-falloff added to its popularity.
+ double falloff;
+ // popularity values for each service
+ map<QString, double> vals;
+ // accumulated popularity of the unknown programs
+ // started before the statistic started
+ double iniVal;
+ };
+
+ struct Popularity
+ {
+ QString service;
+ double popularity;
+ bool operator<(const Popularity& p) const
+ {
+ return popularity > p.popularity;
+ }
+ };
+
+ PopularityStatisticsImpl();
+ void normalizeHistory(SingleFalloffHistory& h);
+ void updateServiceRanks();
+
+ vector<SingleFalloffHistory> m_stats;
+ vector<Popularity> m_servicesByPopularity;
+ map<QString, int> m_serviceRanks;
+ double m_historyHorizon;
+};
+
+// ---- Public methods ----
+
+PopularityStatistics::PopularityStatistics() :
+ d(new PopularityStatisticsImpl())
+{
+}
+
+PopularityStatistics::~PopularityStatistics()
+{
+ delete d;
+}
+
+void PopularityStatistics::useService(const QString& service)
+{
+ vector<PopularityStatisticsImpl::SingleFalloffHistory>::iterator
+ it(d->m_stats.begin()), end(d->m_stats.end());
+ for (; it != end; ++it)
+ {
+ map<QString, double>::iterator valIt;
+ bool found(false);
+ for (valIt = it->vals.begin(); valIt != it->vals.end(); ++valIt)
+ {
+ valIt->second = valIt->second * it->falloff;
+ if (valIt->first == service)
+ {
+ found = true;
+ valIt->second += 1-it->falloff;
+ }
+ }
+ it->iniVal = it->iniVal * it->falloff;
+ if (found == false)
+ {
+ it->vals[service] = 1-it->falloff;
+ }
+ d->normalizeHistory(*it);
+ }
+ d->updateServiceRanks();
+}
+
+void PopularityStatistics::moveToTop(const QStringList& newTopServiceList)
+{
+ vector<PopularityStatisticsImpl::SingleFalloffHistory>::iterator
+ histIt(d->m_stats.begin()), histEnd(d->m_stats.end());
+ for (; histIt != histEnd; ++histIt)
+ {
+ set<QString> newTopServices;
+ for (uint n=0; n<newTopServiceList.size(); ++n)
+ newTopServices.insert(newTopServiceList[n]);
+
+ // Sort by popularity
+ vector<PopularityStatisticsImpl::Popularity> ranking;
+ map<QString, double>::iterator valIt;
+ for (valIt = histIt->vals.begin(); valIt != histIt->vals.end(); ++valIt)
+ {
+ PopularityStatisticsImpl::Popularity pop;
+ pop.service = valIt->first;
+ pop.popularity = valIt->second;
+ ranking.push_back(pop);
+ }
+ stable_sort(ranking.begin(), ranking.end());
+
+ // Get the new positions of each service in the ranking.
+ // We don't touch the popularity values in the ranking.
+ list<QString> topServiceList, bottomServiceList;
+ vector<PopularityStatisticsImpl::Popularity>:: iterator rankIt;
+ for (rankIt = ranking.begin(); rankIt != ranking.end(); ++rankIt)
+ {
+ if (newTopServices.find(rankIt->service) != newTopServices.end())
+ {
+ topServiceList.push_back(rankIt->service);
+ //kdDebug() << "top service: " << valIt->first << endl;
+ newTopServices.erase(rankIt->service);
+ }
+ else
+ {
+ //kdDebug() << "bottom service: " << valIt->first << endl;
+ bottomServiceList.push_back(rankIt->service);
+ }
+ }
+ // Append remaining new services to the topServices list
+ while (newTopServices.size() > 0)
+ {
+ topServiceList.push_back(*newTopServices.begin());
+ newTopServices.erase(newTopServices.begin());
+ }
+
+ list<QString> newServiceList;
+ copy(topServiceList.begin(), topServiceList.end(),
+ back_insert_iterator<list<QString> >(newServiceList));
+ copy(bottomServiceList.begin(), bottomServiceList.end(),
+ back_insert_iterator<list<QString> >(newServiceList));
+
+ // Merge the old list of service popularities
+ // with the new ordering of the services
+ histIt->vals.clear();
+ list<QString>::iterator servIt;
+ uint serviceIndex = 0;
+ //kdDebug() << endl;
+
+ for (servIt = newServiceList.begin(); servIt != newServiceList.end();
+ ++servIt)
+ {
+ if (serviceIndex < ranking.size())
+ {
+ histIt->vals[*servIt] = ranking[serviceIndex].popularity;
+ //kdDebug() << "->Re-Added service " <<
+ //ranking[serviceIndex].popularity
+ // << " " << *servIt << endl;
+ //kdDebug() << "...was replaced by " << *servIt << endl;
+ }
+ else
+ {
+ //kdDebug() << "Service " << *servIt << endl;
+ //kdDebug() << "...was set to popularity=0" << endl;
+ histIt->vals[*servIt] = 0.00001;
+ }
+ // Make sure that the topServices are actually bigger than
+ // the bottomServices and not just bigger or equal
+ // and also that no services have popularity==0
+ if (serviceIndex >= topServiceList.size())
+ {
+ histIt->vals[*servIt] *= histIt->falloff;
+ }
+ ++serviceIndex;
+ }
+ d->normalizeHistory(*histIt);
+ }
+ d->updateServiceRanks();
+}
+
+/*v
+Old version - moves everything else one position up
+and 'service' to the bottom
+void PopularityStatistics::moveToBottom(const QString& service)
+{
+ // Moves a service to the bottom of the ranking
+ // by moving everything else to the top
+ d->updateServiceRanks();
+ QStringList allButOneServices;
+ vector<PopularityStatisticsImpl::Popularity>::iterator
+ it(d->m_servicesByPopularity.begin()),
+ end(d->m_servicesByPopularity.end());
+ for (; it != end; ++it)
+ {
+ if (it->service != service)
+ allButOneServices << it->service;
+ }
+ moveToTop(allButOneServices);
+}*/
+
+void PopularityStatistics::moveToBottom(const QString& service)
+{
+ vector<PopularityStatisticsImpl::SingleFalloffHistory>::iterator
+ it(d->m_stats.begin()), end(d->m_stats.end());
+ for (; it != end; ++it)
+ {
+ it->iniVal += it->vals[service];
+ it->vals[service] = 0;
+ d->normalizeHistory(*it);
+ }
+ d->updateServiceRanks();
+}
+
+QString PopularityStatistics::serviceByRank(int n) const
+{
+ if (n >= 0 && n < int(d->m_servicesByPopularity.size()))
+ return d->m_servicesByPopularity[n].service;
+ else
+ return QString();
+}
+
+double PopularityStatistics::popularityByRank(int n) const
+{
+ if (n >= 0 && n < int(d->m_servicesByPopularity.size()))
+ return d->m_servicesByPopularity[n].popularity;
+ else
+ return 0.0;
+}
+
+int PopularityStatistics::rankByService(const QString service)
+{
+ if (d->m_serviceRanks.find(service) != d->m_serviceRanks.end())
+ {
+ return d->m_serviceRanks[service];
+ }
+ return -1;
+}
+
+void PopularityStatistics::writeConfig(Prefs* prefs) const
+{
+ QStringList serviceNames, serviceHistories;
+ int limit = prefs->serviceCacheSize();
+ //kdDebug() << "popularityData: writeConfig" << endl;
+ for (int n=0; n<int(d->m_servicesByPopularity.size()) && n<limit; ++n)
+ {
+ PopularityStatisticsImpl::Popularity pop = d->m_servicesByPopularity[n];
+ QStringList historyData;
+ for (int i=0; i<int(d->m_stats.size()); ++i)
+ {
+ historyData << QString::number(d->m_stats[i].vals[pop.service]);
+ }
+ serviceNames << pop.service;
+ serviceHistories << historyData.join("/");
+ //kdDebug() << "popularityData: writeConfig -- " << pop.service << endl;
+ }
+ prefs->setServiceNames(serviceNames);
+ prefs->setServiceHistories(serviceHistories);
+}
+
+void PopularityStatistics::readConfig(Prefs* prefs)
+{
+ int n = 0;
+ QStringList serviceNames = prefs->serviceNames();
+ QStringList histories = prefs->serviceHistories();
+ for (n = std::min(serviceNames.size(), histories.size())-1; n>=0; --n)
+ {
+ QString serviceName = serviceNames[n];
+ QStringList serviceHistory =
+ QStringList::split("/", histories[n]);
+ for (int i=min(serviceHistory.size(), d->m_stats.size())-1; i>=0; --i)
+ {
+ d->m_stats[i].vals[serviceName] = serviceHistory[i].toDouble();
+ }
+ }
+
+ for (int i=0; i<int(d->m_stats.size()); ++i)
+ {
+ map<QString, double>::iterator valIt;
+ double valSum = 0;
+ for (valIt = d->m_stats[i].vals.begin();
+ valIt != d->m_stats[i].vals.end(); ++valIt)
+ {
+ if (valIt->second < 0) valIt->second = 0;
+ valSum += valIt->second;
+ }
+ // Scale down values if their sum is bigger than 1
+ // because of rounding errors or a corrupted config file
+ if (valSum > 1)
+ {
+ for (valIt = d->m_stats[i].vals.begin();
+ valIt != d->m_stats[i].vals.end(); ++valIt)
+ {
+ valIt->second = valIt->second / valSum;
+ }
+ }
+ d->m_stats[i].iniVal = 1-valSum;
+ }
+ d->updateServiceRanks();
+}
+
+void PopularityStatistics::setHistoryHorizon(double h)
+{
+ d->m_historyHorizon = std::max(std::min(h, 1.0), 0.0);
+ d->updateServiceRanks();
+}
+
+double PopularityStatistics::historyHorizon()
+{
+ return d->m_historyHorizon;
+}
+
+
+// ---- Implementation methods ----
+
+PopularityStatisticsImpl::PopularityStatisticsImpl()
+{
+ const int rateBaseCount(8);
+
+ m_historyHorizon = 0.0;
+
+ for (int n=0; n<rateBaseCount; ++n)
+ {
+ SingleFalloffHistory h;
+ h.falloff = 1.0 - (0.5 / std::exp(double(n)*1.5));
+ m_stats.push_back(h);
+ }
+}
+
+void PopularityStatisticsImpl::normalizeHistory(SingleFalloffHistory& h)
+{
+ //kdDebug() << "Normalize history" << endl;
+ double sum = h.iniVal;
+ map<QString, double>::iterator it;
+ for (it = h.vals.begin(); it != h.vals.end(); ++it)
+ {
+ sum += it->second;
+ }
+ for (it = h.vals.begin(); it != h.vals.end(); ++it)
+ {
+ it->second = it->second / sum;
+ }
+ h.iniVal = h.iniVal / sum;
+}
+
+void PopularityStatisticsImpl::updateServiceRanks()
+{
+ // For each service calculate the average over the popularity
+ // for all falloff values and then sort by these averaged values
+
+ vector<SingleFalloffHistory>::iterator
+ it(m_stats.begin()), end(m_stats.end());
+ map<QString, double> serviceValSum, serviceValWeightSum;
+ int numStats = m_stats.size();
+ for (int statIndex = 0; it != end; ++it, ++statIndex)
+ {
+ // Put more weight on the short term history if m_historyHorizon==0
+ // and more on the the long term history for m_historyHorizon==1
+ double a = 2*(numStats-1)*m_historyHorizon - numStats + 0.5;
+ if (statIndex < a || statIndex > a + numStats)
+ {
+ continue;
+ }
+
+ map<QString, double>::iterator valIt;
+ /*double valSum = 0;
+ for (valIt = it->vals.begin(); valIt != it->vals.end(); ++valIt)
+ {
+ valSum += valIt->second;
+ }
+ if (valSum == 0) valSum = 1;*/
+ for (valIt = it->vals.begin(); valIt != it->vals.end(); ++valIt)
+ {
+ serviceValWeightSum[valIt->first] += 1;
+ serviceValSum[valIt->first] += valIt->second;
+ }
+ }
+
+ m_servicesByPopularity.clear();
+ map<QString, double>::iterator sIt;
+ for (sIt = serviceValWeightSum.begin();
+ sIt != serviceValWeightSum.end(); ++sIt)
+ {
+ Popularity p;
+ p.service = sIt->first;
+ assert(sIt->second > 0);
+ p.popularity = serviceValSum[sIt->first] / sIt->second;
+ m_servicesByPopularity.push_back(p);
+ }
+ stable_sort(m_servicesByPopularity.begin(), m_servicesByPopularity.end());
+ m_serviceRanks.clear();
+ for (uint n = 0; n < m_servicesByPopularity.size(); ++n)
+ {
+ m_serviceRanks[m_servicesByPopularity[n].service] = n;
+ /*kdDebug() << QString("Rank %1: %2 %3").arg(n)
+ .arg(m_servicesByPopularity[n].popularity)
+ .arg(m_servicesByPopularity[n].service) << endl;*/
+ }
+}
diff --git a/kicker/applets/launcher/popularity.h b/kicker/applets/launcher/popularity.h
new file mode 100644
index 000000000..b1dcb32d6
--- /dev/null
+++ b/kicker/applets/launcher/popularity.h
@@ -0,0 +1,127 @@
+/*****************************************************************
+
+Copyright (c) 2005 Fred Schaettgen <[email protected]>
+
+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 __popularity_h__
+#define __popularity_h__
+
+#include <qstring.h>
+#include <qstringlist.h>
+
+class PopularityStatisticsImpl;
+class Prefs;
+
+/**
+ * Tracks the usage of any kind of service to offer recommendations.
+ * A service is identified by a string. After calling @useService
+ * a few times, you can get a popularity ranking for the used
+ * services.
+ * The algorithm tries to take both short- and long-term usage
+ * into account at the same time.
+ * The popularity value can be interpreted as the probability
+ * that the given service will be the next one to be used.
+ * If some new services are suddenly used a few times, their ranking
+ * may grow higher than the ranking of services, which were used very
+ * frequently a while ago. But after this short term usage has
+ * stopped, its influence gets weaker more quickly then for the old,
+ * more frequently used services.
+ * During first time usage, the algorithm needs some time to stabilize,
+ * since there is simply no dependable long term usage data available,
+ * so the ranking is more likely to change at first.
+ * But in the long run, the behaviour of the algorithm is
+ * completely stable, unlike simple usage counting for instance.
+ */
+class PopularityStatistics
+{
+public:
+ PopularityStatistics();
+ virtual ~PopularityStatistics();
+
+ /**
+ * Touch a service. This will increase the usage
+ * counters for the given service and decrease the
+ * counters for all the others.
+ */
+ void useService(const QString& service);
+
+ /**
+ * Exchange all state variables of the most
+ * popular service with those from services,
+ * moving the given services to the top of the
+ * list. Apart from that the order stays the same
+ * as before. Order of items in the string list
+ * does *not* matter/
+ */
+ void moveToTop(const QStringList& services);
+
+ /**
+ * Sets all counters to zero for the given service
+ */
+ void moveToBottom(const QString& service);
+
+ /**
+ * Retrieve the name of a service by its position
+ * in the current popularity ranking
+ */
+ QString serviceByRank(int n) const;
+
+ /**
+ * Retrieve the popularity (0-1) of a service by
+ * its position in the current popularity ranking
+ */
+ double popularityByRank(int n) const;
+
+ /**
+ * Gets the rank of a given service.
+ * Returns -1 if the service is not in the ranking
+ */
+ int rankByService(const QString service);
+
+ /**
+ * Writes the configuration.
+ * A section must be set already for config.
+ */
+ void writeConfig(Prefs* prefs) const;
+
+ /**
+ * Reads the configuration.
+ * A section must be set already for config.
+ */
+ void readConfig(Prefs* prefs);
+
+ /**
+ * Modify the weighting of the history logs.
+ * 0 <= h <= 1. 1 means long term history
+ * 0 means short term history - in fact the popularity ranking
+ * becomes a recently-used list in that case.
+ */
+ void setHistoryHorizon(double h);
+ double historyHorizon();
+
+protected:
+ PopularityStatisticsImpl *d;
+
+private:
+ PopularityStatistics(const PopularityStatistics&) {}
+};
+
+#endif
diff --git a/kicker/applets/launcher/prefs.kcfgc b/kicker/applets/launcher/prefs.kcfgc
new file mode 100644
index 000000000..26a3f3d07
--- /dev/null
+++ b/kicker/applets/launcher/prefs.kcfgc
@@ -0,0 +1,6 @@
+# Code generation options for kconfig_compiler
+File=launcherapplet.kcfg
+ClassName=Prefs
+Singleton=false
+Mutators=AutoAdjustMaxItems,Buttons,VolatileButtons,AutoAdjustMaxItems,AutoAdjustMinItems,AutoAdjustEnabled,IconDim,DragEnabled,ConserveSpace,ServiceInspos,ServiceNames,ServiceHistories
+# MemberVariables=public
diff --git a/kicker/applets/launcher/quickaddappsmenu.cpp b/kicker/applets/launcher/quickaddappsmenu.cpp
new file mode 100644
index 000000000..74d00a6e4
--- /dev/null
+++ b/kicker/applets/launcher/quickaddappsmenu.cpp
@@ -0,0 +1,67 @@
+/*****************************************************************
+
+Copyright (c) 2000 Bill Nagel
+ based on paneladdappsmenu.cpp which is
+ Copyright (c) 1999-2000 the kicker 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 <kstandarddirs.h>
+#include <kdesktopfile.h>
+#include <kglobalsettings.h>
+#include <ksycocaentry.h>
+#include <kservice.h>
+#include <kservicegroup.h>
+
+#include <kdebug.h>
+#include "quickaddappsmenu.h"
+
+QuickAddAppsMenu::QuickAddAppsMenu(const QString &label, const QString &relPath, QWidget *target, QWidget *parent, const char *name, const QString &sender)
+ : PanelServiceMenu(label, relPath, parent, name)
+{
+ _targetObject = target;
+ _sender = sender;
+ connect(this, SIGNAL(addAppBefore(QString,QString)),
+ target, SLOT(addAppBeforeManually(QString,QString)));
+}
+
+QuickAddAppsMenu::QuickAddAppsMenu(QWidget *target, QWidget *parent, const QString &sender, const char *name)
+ : PanelServiceMenu(QString::null, QString::null, parent, name)
+{
+ _targetObject = target;
+ _sender = sender;
+ connect(this, SIGNAL(addAppBefore(QString,QString)),
+ target, SLOT(addAppBeforeManually(QString,QString)));
+}
+
+void QuickAddAppsMenu::slotExec(int id)
+{
+ if (!entryMap_.contains(id)) return;
+ KSycocaEntry * e = entryMap_[id];
+ KService::Ptr service = static_cast<KService *>(e);
+ emit addAppBefore(locate("apps", service->desktopEntryPath()),_sender);
+}
+
+
+PanelServiceMenu *QuickAddAppsMenu::newSubMenu(const QString &label, const QString &relPath, QWidget *parent, const char *name, const QString &insertInlineHeader)
+{
+ return new QuickAddAppsMenu(label, relPath, _targetObject, parent, name, _sender);
+}
+#include "quickaddappsmenu.moc"
diff --git a/kicker/applets/launcher/quickaddappsmenu.h b/kicker/applets/launcher/quickaddappsmenu.h
new file mode 100644
index 000000000..88465049c
--- /dev/null
+++ b/kicker/applets/launcher/quickaddappsmenu.h
@@ -0,0 +1,51 @@
+/*****************************************************************
+
+Copyright (c) 2000 Bill Nagel
+ based on paneladdappsmenu.h which is
+ Copyright (c) 1999-2000 the kicker 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.
+s
+******************************************************************/
+
+#ifndef __quickaddappsmenu_h__
+#define __quickaddappsmenu_h__
+
+#include "service_mnu.h"
+
+class QuickAddAppsMenu: public PanelServiceMenu {
+ Q_OBJECT
+public:
+ QuickAddAppsMenu(const QString &label, const QString &relPath, QWidget *target, QWidget *parent=0, const char *name=0, const QString &sender=QString(""));
+ QuickAddAppsMenu(QWidget *target, QWidget *parent=0, const QString &sender=QString(""), const char *name=0);
+signals:
+ void addAppBefore(QString,QString);
+protected slots:
+ virtual void slotExec(int id);
+protected:
+ virtual PanelServiceMenu *newSubMenu(const QString &label,
+ const QString &relPath,
+ QWidget *parent,
+ const char *name,
+ const QString & _inlineHeader=QString::null);
+private:
+ QWidget *_targetObject;
+ QString _sender;
+};
+
+#endif
diff --git a/kicker/applets/launcher/quickbutton.cpp b/kicker/applets/launcher/quickbutton.cpp
new file mode 100644
index 000000000..933088b04
--- /dev/null
+++ b/kicker/applets/launcher/quickbutton.cpp
@@ -0,0 +1,322 @@
+/*****************************************************************
+
+Copyright (c) 2000 Bill Nagel
+
+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 "quickbutton.h"
+#include "quickaddappsmenu.h"
+
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qpopupmenu.h>
+#include <qtooltip.h>
+
+#include <kactionclasses.h>
+#include <kickertip.h>
+#include <klocale.h>
+#include <kdesktopfile.h>
+#include <krun.h>
+#include <kiconeffect.h>
+#include <kglobalsettings.h>
+#include <kcursor.h>
+#include <kapplication.h>
+#include <kipc.h>
+#include <kiconloader.h>
+#include <kurldrag.h>
+#include <kstandarddirs.h>
+
+#include <math.h>
+#include <algorithm>
+
+#ifdef DEBUG
+ #define DEBUGSTR kdDebug()
+#else
+ #define DEBUGSTR kndDebug()
+#endif
+
+QuickURL::QuickURL(const QString &u)
+{ DEBUGSTR<<"QuickURL::QuickURL("<<u<<")"<<endl<<flush;
+ KService::Ptr _service=0;
+ _menuId = u;
+ if (_menuId.startsWith("file:") && _menuId.endsWith(".desktop")) {
+ // this ensures that desktop entries are referenced by desktop name instead of by file name
+ _menuId=KURL(_menuId).path();
+ }
+ if (_menuId.startsWith("/")) {
+ // Absolute path
+ _kurl.setPath(_menuId);
+
+ if (_menuId.endsWith(".desktop")) {
+ // Strip path
+ QString s = _menuId;
+ s = s.mid(s.findRev('/')+1);
+ s = s.left(s.length()-8);
+ _service = KService::serviceByStorageId(s);
+ if (!_service) {
+ _service = new KService(_menuId);
+ } else {
+ }
+ }
+ } else if (!KURL::isRelativeURL(_menuId)) {
+ // Full URL
+ _kurl = _menuId;
+ } else {
+ // menu-id
+ _service = KService::serviceByMenuId(_menuId);
+ }
+ DEBUGSTR << "QuickURL: _service='"<<_service<<" _kurl="<<_kurl<<" _menuId="<<_menuId<<endl<<flush;
+
+ if (_service) {
+ if (!_service->isValid()) {
+ DEBUGSTR << "QuickURL: _service is not valid"<<endl<<flush;
+ // _service is a KShared pointer, don't try to delete it!
+ _service = 0;
+ } else {
+ DEBUGSTR << "QuickURL: _service='"<<_service<<"' _service->desktopEntryPath()="<<_service->desktopEntryPath()<<endl<<flush;
+ if (_kurl.path().length() == 0)
+ {
+ _kurl.setPath(locate("apps", _service->desktopEntryPath()));
+ }
+ if (!_service->menuId().isEmpty())
+ _menuId = _service->menuId();
+
+ m_genericName = _service->genericName();
+ m_name = _service->name();
+ }
+ } else {
+ m_name = _kurl.prettyURL();
+ }
+ DEBUGSTR<<"QuickURL::QuickURL("<<u<<") END"<<endl<<flush;
+}
+
+void QuickURL::run() const
+{ kapp->propagateSessionManager(); // is this needed?
+ if (_service)
+ KRun::run(*(_service), KURL::List());
+ else
+ new KRun(_kurl, 0, _kurl.isLocalFile());
+}
+
+//similar to MimeType::pixmapForURL
+QPixmap QuickURL::pixmap( mode_t _mode, KIcon::Group _group,
+ int _force_size, int _state, QString *) const
+{ // Load icon
+ QPixmap pxmap = KMimeType::pixmapForURL(_kurl, _mode, _group, _force_size, _state);
+ // Resize to fit button
+ pxmap.convertFromImage(pxmap.convertToImage().smoothScale(_force_size,_force_size, QImage::ScaleMin));
+ return pxmap;
+}
+
+
+QuickButton::QuickButton(const QString &u, KAction* configAction,
+ QWidget *parent, const char *name) :
+ SimpleButton(parent, name),
+ m_flashCounter(0),
+ m_sticky(false)
+{
+ installEventFilter(KickerTip::the());
+ setMouseTracking(true);
+ _highlight = false;
+ _oldCursor = cursor();
+ _qurl=new QuickURL(u);
+
+ QToolTip::add(this, _qurl->name());
+ resize(int(DEFAULT_ICON_DIM),int(DEFAULT_ICON_DIM));
+ QBrush bgbrush(colorGroup().brush(QColorGroup::Background));
+
+ QuickAddAppsMenu *addAppsMenu = new QuickAddAppsMenu(
+ parent, this, _qurl->url());
+ _popup = new QPopupMenu(this);
+ _popup->insertItem(i18n("Add Application"), addAppsMenu);
+ configAction->plug(_popup);
+ _popup->insertSeparator();
+ _popup->insertItem(SmallIcon("remove"), i18n("Remove"),
+ this, SLOT(removeApp()));
+
+ m_stickyAction = new KToggleAction(i18n("Never Remove Automatically"),
+ KShortcut(), this);
+ connect(m_stickyAction, SIGNAL(toggled(bool)),
+ this, SLOT(slotStickyToggled(bool)));
+ m_stickyAction->plug(_popup, 2);
+ m_stickyId = _popup->idAt(2);
+
+ connect(this, SIGNAL(clicked()), SLOT(launch()));
+ connect(this, SIGNAL(removeApp(QuickButton *)), parent,
+ SLOT(removeAppManually(QuickButton *)));
+}
+
+QuickButton::~QuickButton()
+{
+ delete _qurl;
+}
+
+
+QString QuickButton::url() const
+{
+ return _qurl->url();
+}
+
+
+QString QuickButton::menuId() const
+{ return _qurl->menuId();}
+
+
+void QuickButton::loadIcon()
+{
+ // Set Icon Dimension from size
+ _iconDim=std::min(size().width(),size().height())-2*ICON_MARGIN;
+ // Load icons
+ _icon = _qurl->pixmap(0, KIcon::Panel, _iconDim, KIcon::DefaultState);
+ _iconh = _qurl->pixmap(0, KIcon::Panel, _iconDim, KIcon::ActiveState);
+ setPixmap(_icon);
+}
+
+void QuickButton::resizeEvent(QResizeEvent *e)
+{
+ loadIcon();
+ SimpleButton::resizeEvent(e);
+}
+
+void QuickButton::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == RightButton)
+ _popup->popup(e->globalPos());
+ else if (e->button() == LeftButton) {
+ _dragPos = e->pos();
+ QButton::mousePressEvent(e);
+ }
+}
+
+void QuickButton::mouseMoveEvent(QMouseEvent *e)
+{
+ if ((e->state() & LeftButton) == 0) return;
+ QPoint p(e->pos() - _dragPos);
+ if (p.manhattanLength() <= KGlobalSettings::dndEventDelay())
+ return;
+ DEBUGSTR<<"dragstart"<<endl<<flush;
+ setDown(false);
+ if (_dragEnabled) {
+ KURL::List uris;
+ uris.append(_qurl->kurl());
+ DEBUGSTR<<"creating KURLDrag"<<endl<<flush;
+ KURLDrag *dd = new KURLDrag(uris,this);
+ dd->setPixmap(_icon); //PIX
+ DEBUGSTR<<"ready to drag"<<endl<<flush;
+ grabKeyboard();
+ dd->drag();
+ releaseKeyboard();
+ } else {
+ setCursor(Qt::ForbiddenCursor);
+ }
+}
+
+void QuickButton::slotIconChanged(int group)
+{
+ loadIcon();
+ SimpleButton::slotIconChanged(group);
+ update();
+}
+
+void QuickButton::launch()
+{
+ setDown(false);
+ update();
+ KIconEffect::visualActivate(this, rect());
+ _qurl->run();
+ emit executed(_qurl->menuId());
+}
+
+void QuickButton::setDragging(bool enable)
+{
+ setDown(enable);
+ _highlight=enable;
+ update();
+}
+
+void QuickButton::setEnableDrag(bool enable)
+{
+ _dragEnabled=enable;
+}
+
+void QuickButton::removeApp()
+{
+ emit removeApp(this);
+}
+
+void QuickButton::flash()
+{
+ m_flashCounter = 2000;
+ QTimer::singleShot(0, this, SLOT(slotFlash()));
+}
+
+void QuickButton::slotFlash()
+{
+ static const int timeout = 500/4;
+ if (m_flashCounter > 0)
+ {
+ m_flashCounter -= timeout;
+ if (m_flashCounter < 0) m_flashCounter = 0;
+ update();
+ QTimer::singleShot(timeout, this, SLOT(slotFlash()));
+ }
+}
+
+void QuickButton::slotStickyToggled(bool isSticky)
+{
+ m_sticky = isSticky;
+ emit stickyToggled(isSticky);
+}
+
+void QuickButton::setSticky(bool sticky)
+{
+ m_stickyAction->setChecked(sticky);
+ slotStickyToggled(sticky);
+}
+
+void QuickButton::updateKickerTip(KickerTip::Data &data)
+{
+ if (!_qurl)
+ {
+ return;
+ }
+ data.message = _qurl->name();
+ data.direction = m_popupDirection;
+ data.subtext = _qurl->genericName();
+ if (data.subtext == QString())
+ {
+ data.subtext = data.message;
+ }
+ data.icon = KMimeType::pixmapForURL(_qurl->kurl(), 0,
+ KIcon::Panel, KIcon::SizeHuge, KIcon::DefaultState);
+}
+
+void QuickButton::setPopupDirection(KPanelApplet::Direction d)
+{
+ m_popupDirection = d;
+}
+
+void QuickButton::setDynamicModeEnabled(bool enabled)
+{
+ _popup->setItemVisible(m_stickyId, enabled);
+}
+
+
+#include "quickbutton.moc"
diff --git a/kicker/applets/launcher/quickbutton.h b/kicker/applets/launcher/quickbutton.h
new file mode 100644
index 000000000..98eabec6e
--- /dev/null
+++ b/kicker/applets/launcher/quickbutton.h
@@ -0,0 +1,124 @@
+/*****************************************************************
+
+Copyright (c) 2000 Bill Nagel
+
+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 __quickbutton_h__
+#define __quickbutton_h__
+
+#include <qbutton.h>
+#include <qpoint.h>
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+
+#include <kickertip.h>
+#include <kicontheme.h>
+#include <kmimetype.h>
+#include <kpanelapplet.h>
+#include <kservice.h>
+#include <kurl.h>
+
+#include "simplebutton.h"
+
+class QPopupMenu;
+class KAction;
+class KToggleAction;
+
+class QuickURL {
+public:
+ QuickURL(const QString &u);
+ KURL kurl() const {return _kurl;};
+ QString url() const {return _kurl.url();};
+ QString menuId() const {return _menuId;};
+ QString genericName() const { return m_genericName; }
+ QString name() const { return m_name; }
+ KService::Ptr service() const {return _service;};
+ void run() const;
+ QPixmap pixmap(mode_t _mode = 0, KIcon::Group _group = KIcon::Desktop,
+ int _force_size = 0, int _state = 0, QString * _path = 0L) const;
+
+private:
+ KURL _kurl;
+ QString _menuId;
+ QString m_genericName;
+ QString m_name;
+ KService::Ptr _service;
+};
+
+
+class QuickButton: public SimpleButton, public KickerTip::Client {
+ Q_OBJECT
+
+public:
+ enum { DEFAULT_ICON_DIM = 16 };
+ enum { ICON_MARGIN = 1 };
+ QuickButton(const QString &u, KAction* configAction,
+ QWidget *parent=0, const char *name=0);
+ ~QuickButton();
+ QString url() const;
+ QString menuId() const;
+ QPixmap icon() const{ return _icon;}
+ bool sticky() { return m_sticky; }
+ void setSticky(bool bSticky);
+ void setPopupDirection(KPanelApplet::Direction d);
+
+ void setDragging(bool drag);
+ void setEnableDrag(bool enable);
+ void setDynamicModeEnabled(bool enabled);
+ void flash();
+
+signals:
+ void removeApp(QuickButton *);
+ void executed(QString serviceStorageID);
+ void stickyToggled(bool isSticky);
+
+protected:
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void resizeEvent(QResizeEvent *rsevent);
+ void loadIcon();
+ void updateKickerTip(KickerTip::Data &data);
+
+protected slots:
+ void slotIconChanged(int);
+ void launch();
+ void removeApp();
+ void slotFlash();
+ void slotStickyToggled(bool isSticky);
+
+private:
+ int m_flashCounter;
+ QuickURL *_qurl;
+ QPoint _dragPos;
+ QPopupMenu *_popup;
+ QPixmap _icon, _iconh;
+ QCursor _oldCursor;
+ bool _highlight, _changeCursorOverItem, _dragEnabled;
+ int _iconDim;
+ bool m_sticky;
+ KToggleAction *m_stickyAction;
+ int m_stickyId;
+ KPanelApplet::Direction m_popupDirection;
+};
+
+#endif
+
diff --git a/kicker/applets/launcher/quickbuttongroup.h b/kicker/applets/launcher/quickbuttongroup.h
new file mode 100644
index 000000000..1d373ae92
--- /dev/null
+++ b/kicker/applets/launcher/quickbuttongroup.h
@@ -0,0 +1,60 @@
+/* Copyright 2004, Daniel Woods Bullok <[email protected]>
+ distributed under the terms of the
+ GNU GENERAL PUBLIC LICENSE Version 2 -
+ See the file kdebase/COPYING for details
+*/
+
+#ifndef __quickbuttongroup_h__
+#define __quickbuttongroup_h__
+
+#include <qstring.h>
+#include <functional>
+#include "easyvector.h"
+#include "quickbutton.h"
+
+
+class QuickButtonGroup: virtual public EasyVector< QuickButton* > {
+public:
+ QuickButtonGroup(const EasyVector< QuickButton* > &kv):EasyVector< QuickButton* >(kv){};
+ QuickButtonGroup():EasyVector< QuickButton* >(){};
+ Index findDescriptor(const QString &desc);
+
+ void show();
+ void hide();
+ void setDragging(bool drag);
+ void setEnableDrag(bool enable);
+ void deleteContents();
+ void setUpdatesEnabled(bool enable);
+};
+
+QuickButtonGroup::Index QuickButtonGroup::findDescriptor(const QString &desc)
+{ return findProperty(desc, std::mem_fun(&QuickButton::url));}
+
+inline void QuickButtonGroup::setUpdatesEnabled(bool enable)
+{ for (QuickButtonGroup::iterator i=begin();i!=end();++i) {
+ (*i)->setUpdatesEnabled(enable);
+ if (enable) { (*i)->update();}
+ }
+}
+
+inline void QuickButtonGroup::show()
+{ std::for_each(begin(),end(),std::mem_fun(&QWidget::show));}
+
+inline void QuickButtonGroup::hide()
+{ std::for_each(begin(),end(),std::mem_fun(&QWidget::hide));}
+
+inline void QuickButtonGroup::setDragging(bool drag)
+{ std::for_each(begin(),end(),std::bind2nd(std::mem_fun(&QuickButton::setDragging),drag));}
+
+inline void QuickButtonGroup::setEnableDrag(bool enable)
+{ std::for_each(begin(),end(),std::bind2nd(std::mem_fun(&QuickButton::setEnableDrag),enable));}
+
+inline void QuickButtonGroup::deleteContents()
+{ for (QuickButtonGroup::iterator i=begin();i!=end();++i) {
+ delete (*i);
+ (*i)=0;
+ }
+}
+
+#endif
+
diff --git a/kicker/applets/launcher/quicklauncher.cpp b/kicker/applets/launcher/quicklauncher.cpp
new file mode 100644
index 000000000..abae9efe1
--- /dev/null
+++ b/kicker/applets/launcher/quicklauncher.cpp
@@ -0,0 +1,1093 @@
+/*****************************************************************
+
+Copyright (c) 2000 Bill Nagel
+Copyright (c) 2004 Dan Bullok <[email protected]>
+
+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 <qpainter.h>
+#include <qpopupmenu.h>
+#include <qslider.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+
+#include <dcopclient.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kaboutapplication.h>
+#include <kaboutdata.h>
+#include <kdialogbase.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kurldrag.h>
+#include <kdebug.h>
+
+
+#include <algorithm>
+#include <list>
+#include <math.h>
+#include <set>
+#include <assert.h>
+
+#include "configdlg.h"
+#include "popularity.h"
+#include "quicklauncher.h"
+#include "quickbutton.h"
+#include "quickaddappsmenu.h"
+#include "quickbuttongroup.h"
+
+typedef ButtonGroup::iterator ButtonIter;
+const ButtonGroup::Index NotFound=ButtonGroup::NotFound;
+const ButtonGroup::Index Append=ButtonGroup::Append;
+
+#ifdef DEBUG
+ #define DEBUGSTR kdDebug()
+#else
+ #define DEBUGSTR kndDebug()
+#endif
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("quicklauncher");
+ return new QuickLauncher(configFile, KPanelApplet::Normal,
+ KPanelApplet::Preferences,
+ parent, "quicklauncher");
+ }
+}
+
+QuickLauncher::QuickLauncher(const QString& configFile, Type type, int actions,
+ QWidget *parent, const char *name) :
+ KPanelApplet(configFile, type, actions, parent, name)
+{
+ DCOPObject::setObjId("QuickLauncherApplet");
+ DEBUGSTR << endl << endl << endl << "------------" << flush;
+ DEBUGSTR << "QuickLauncher::QuickLauncher(" << configFile << ",...)" <<
+ endl << flush;
+
+ m_settings = new Prefs(sharedConfig());
+ m_settings->readConfig();
+
+ m_needsSave = false;
+ m_needsRefresh = false;
+ m_refreshEnabled = false;
+
+ m_configDialog = 0;
+ m_popup = 0;
+ m_appletPopup = 0;
+ m_removeAppsMenu = 0;
+
+ m_dragAccepted = false;
+
+ m_buttons = new ButtonGroup;
+ m_manager = new FlowGridManager;
+ m_newButtons = 0;
+ m_oldButtons = 0;
+ m_dragButtons = 0;
+
+ m_configAction = new KAction(i18n("Configure Quicklauncher..."), "configure", KShortcut(),
+ this, SLOT(slotConfigure()), this);
+
+ m_saveTimer = new QTimer(this);
+ connect(m_saveTimer, SIGNAL(timeout()), this, SLOT(saveConfig()));
+
+ m_popularity = new PopularityStatistics();
+
+ setBackgroundOrigin(AncestorOrigin);
+
+ loadConfig();
+
+ buildPopupMenu();
+ m_minPanelDim = std::max(16, m_settings->iconDimChoices()[1]);
+ refreshContents();
+ setRefreshEnabled(true);
+
+ setAcceptDrops(true);
+ //QToolTip::add(this, i18n("Drop applications here"));
+ DEBUGSTR << " QuickLauncher::QuickLauncher(" << configFile <<
+ ",...) END" << endl << flush;
+
+ DCOPClient *dcopClient = KApplication::dcopClient();
+ dcopClient->connectDCOPSignal(0, "appLauncher",
+ "serviceStartedByStorageId(QString,QString)",
+ "QuickLauncherApplet",
+ "serviceStartedByStorageId(QString,QString)",
+ false);
+ kdDebug() << "Quicklauncher registered DCOP signal" << endl;
+}
+
+
+//TODO:? Drag/drop more than one item at a time
+
+QuickLauncher::~QuickLauncher()
+{
+ KGlobal::locale()->removeCatalogue("quicklauncher");
+ setCustomMenu(0);
+ delete m_popup;
+ delete m_appletPopup;
+ delete m_removeAppsMenu;
+ delete m_popularity;
+ clearTempButtons();
+ if (m_buttons)
+ {
+ m_buttons->deleteContents();
+ delete m_buttons;
+ }
+}
+
+// Builds, connects _popup menu
+void QuickLauncher::buildPopupMenu()
+{
+ QuickAddAppsMenu *addAppsMenu = new QuickAddAppsMenu(this, this);
+ m_popup = new QPopupMenu(this);
+ m_popup->insertItem(i18n("Add Application"), addAppsMenu);
+ m_configAction->plug(m_popup);
+
+ m_appletPopup = new QPopupMenu(this);
+ m_appletPopup->insertItem(i18n("Add Application"), addAppsMenu);
+ m_removeAppsMenu = new QPopupMenu(this);
+ connect(m_removeAppsMenu, SIGNAL(aboutToShow()),
+ SLOT(fillRemoveAppsMenu()));
+ connect(m_removeAppsMenu, SIGNAL(activated(int)),
+ SLOT(removeAppManually(int)));
+ m_appletPopup->insertItem(i18n("Remove Application"), m_removeAppsMenu);
+
+ m_appletPopup->insertSeparator();
+ m_appletPopup->setCheckable( true );
+ m_appletPopup->insertItem(i18n("About"), this, SLOT(about()));
+ setCustomMenu(m_appletPopup);
+}
+
+
+// Fill the remove apps menu
+void QuickLauncher::fillRemoveAppsMenu()
+{
+ m_removeAppsMenu->clear();
+ ButtonIter iter(m_buttons->begin());
+ int i = 0;
+ while (iter != m_buttons->end())
+ {
+ QString text = QToolTip::textFor(*iter);
+ if (text.isEmpty())
+ {
+ text = (*iter)->url();
+ if (text.isEmpty())
+ {
+ text = i18n("Unknown");
+ }
+ }
+ m_removeAppsMenu->insertItem((*iter)->icon(), text, i);
+ ++iter;
+ ++i;
+ }
+}
+
+void QuickLauncher::slotSettingsDialogChanged()
+{
+ // Update conserve space setting
+ setConserveSpace(m_settings->conserveSpace());
+ m_popularity->setHistoryHorizon(m_settings->historyHorizon()/100.0);
+ slotAdjustToCurrentPopularity();
+ kdDebug() << "Icon size: " << m_settings->iconDim() << endl;
+ refreshContents();
+
+ saveConfig();
+}
+
+void QuickLauncher::action(Action a)
+{
+ if (a == KPanelApplet::Preferences)
+ {
+ slotConfigure();
+ }
+ else
+ {
+ KPanelApplet::action(a);
+ }
+}
+
+void QuickLauncher::slotConfigure()
+{
+ if (!m_configDialog)
+ {
+ m_configDialog = new ConfigDlg(this, "configdialog",
+ m_settings, SIZE_AUTO, KDialogBase::Plain, KDialogBase::Ok |
+ KDialogBase::Cancel | KDialogBase::Apply | KDialogBase::Default);
+ connect(m_configDialog, SIGNAL(settingsChanged()),
+ this, SLOT(slotSettingsDialogChanged()));
+ }
+
+ m_configDialog->show();
+}
+
+
+int QuickLauncher::findApp(QuickButton *button)
+{
+ if (m_buttons->empty())
+ {
+ return NotFound;
+ }
+ int pos = m_buttons->findValue(button);
+ return pos;
+}
+
+
+int QuickLauncher::findApp(QString url)
+{
+ if (m_buttons->empty())
+ {
+ return NotFound;
+ }
+ int pos=m_buttons->findDescriptor(url);
+ return pos;
+}
+
+void QuickLauncher::removeAppManually(int index)
+{
+ removeApp(index, true);
+}
+
+void QuickLauncher::removeApp(int index, bool manuallyRemoved)
+{
+ if (m_buttons->empty())
+ {
+ return;
+ }
+ if (!m_buttons->isValidIndex(index))
+ {
+ kdWarning() << " removeApp (" << index <<
+ ") *******WARNING****** index=" << index << "is out of bounds." <<
+ endl << flush;
+ return;
+ }
+ DEBUGSTR << "Removing button. index=" << index << " url='" <<
+ (*m_buttons)[index]->url() << "'" << endl << flush;
+
+ QString removeAppUrl = (*m_buttons)[index]->url();
+ QString removeAppMenuId = (*m_buttons)[index]->menuId();
+
+ delete (*m_buttons)[index];
+ m_buttons->eraseAt(index);
+ refreshContents();
+
+ if (int(m_buttons->size()) < m_settings->autoAdjustMinItems() && manuallyRemoved)
+ {
+ m_settings->setAutoAdjustMinItems(m_buttons->size());
+ }
+
+ if (manuallyRemoved)
+ {
+ m_popularity->moveToBottom(removeAppMenuId);
+ slotAdjustToCurrentPopularity();
+ }
+
+ saveConfig();
+}
+
+
+void QuickLauncher::removeApp(QString url, bool manuallyRemoved)
+{
+ int index = findApp(url);
+ if (index == NotFound)
+ {
+ kdDebug() << "removeApp: Not found: " << url << endl;
+ return;
+ }
+ removeApp(index, manuallyRemoved);
+}
+
+
+void QuickLauncher::removeAppManually(QuickButton *button)
+{
+ int index = findApp(button);
+ if (index == NotFound)
+ {
+ return;
+ }
+ removeApp(index, true);
+}
+
+
+int QuickLauncher::widthForHeight(int h) const
+{
+ FlowGridManager temp_manager = *m_manager;
+ temp_manager.setFrameSize(QSize(h,h));
+ temp_manager.setOrientation(Qt::Horizontal); // ??? probably not necessary
+ if (temp_manager.isValid())
+ {
+ return temp_manager.frameSize().width();
+ }
+ return m_minPanelDim;
+}
+
+
+int QuickLauncher::heightForWidth(int w) const
+{
+ FlowGridManager temp_manager=*m_manager;
+ temp_manager.setFrameSize(QSize(w,w));
+ temp_manager.setOrientation(Qt::Vertical); // ??? probably not necessary
+ if (temp_manager.isValid())
+ {
+ return temp_manager.frameSize().height();
+ }
+ return m_minPanelDim;
+}
+
+
+int QuickLauncher::dimension() const
+{
+ if (orientation()==Qt::Vertical)
+ {
+ return size().width();
+ }
+ return size().height();
+}
+
+void QuickLauncher::addApp(QString url, bool manuallyAdded)
+{
+ assert(m_buttons);
+ QString newButtonId = QuickURL(url).menuId();
+ if (m_appOrdering.find(newButtonId) == m_appOrdering.end())
+ {
+ m_appOrdering[newButtonId] = m_appOrdering.size();
+ }
+ uint appPos;
+ for (appPos = 0; appPos < m_buttons->size(); ++appPos)
+ {
+ QString buttonId = (*m_buttons)[appPos]->menuId();
+ if (m_appOrdering[buttonId] >= m_appOrdering[newButtonId])
+ {
+ break;
+ }
+ }
+ addApp(url, appPos, manuallyAdded);
+}
+
+QuickButton* QuickLauncher::createButton(QString url)
+{
+ QuickButton* newButton=new QuickButton(url, m_configAction, this);
+ connect(newButton, SIGNAL(executed(QString)),
+ this, SLOT(slotOwnServiceExecuted(QString)));
+ connect(newButton, SIGNAL(stickyToggled(bool)),
+ this, SLOT(slotStickyToggled()));
+ newButton->setPopupDirection(popupDirection());
+ return newButton;
+}
+
+void QuickLauncher::addApp(QString url, int index, bool manuallyAdded)
+{
+ DEBUGSTR << endl <<"About to add: url='" << url <<
+ "' index=" << index << endl << flush;
+ QuickButton *newButton;
+ if (!m_buttons->isValidInsertIndex(index))
+ {
+ kdWarning() << " *******WARNING****** index=" << index <<
+ "is out of bounds." << endl << flush;
+ index = m_buttons->lastIndex();
+ }
+ int old = findApp(QuickURL(url).url());
+ if (old != NotFound)
+ {
+ if (index == old)
+ {
+ return;
+ }
+ if (index > old)
+ {
+ index--;
+ }
+ newButton = (*m_buttons)[old];
+ m_buttons->eraseAt(old);
+ }
+ else
+ {
+ newButton = createButton(url);
+ }
+ m_buttons->insertAt(index, newButton);
+ DEBUGSTR << "Added: url='"<<url<<"' index="<<index<<endl<<endl<<flush;
+ refreshContents();
+
+ if (manuallyAdded)
+ {
+ newButton->setSticky(true);
+ if (int(m_buttons->size()) > m_settings->autoAdjustMaxItems())
+ {
+ m_settings->setAutoAdjustMaxItems(m_buttons->size());
+ }
+ }
+
+ updateInsertionPosToStatusQuo();
+ saveConfig();
+}
+
+void QuickLauncher::updateInsertionPosToStatusQuo()
+{
+ // Update the app ordering map, so that next time,
+ // addApp(url,manAdded) (without index) will insert the
+ // item at the same position again.
+ std::list<QString> appList;
+ std::set<int> posList;
+ //kdDebug() << "Rearranging application order. Before:" << endl;
+ for (uint n = 0; n < m_buttons->size(); ++n)
+ {
+ QString buttonId = (*m_buttons)[n]->menuId();
+ appList.push_back(buttonId);
+ if (m_appOrdering.find(buttonId) == m_appOrdering.end())
+ {
+ m_appOrdering[buttonId] = m_appOrdering.size();
+ }
+ posList.insert(m_appOrdering[buttonId]);
+ //kdDebug() << m_appOrdering[buttonId] << " = " << buttonId << endl;
+ }
+ //kdDebug() << "After:" << endl;
+ while (posList.size() > 0)
+ {
+ assert(appList.size() > 0);
+ m_appOrdering[*appList.begin()] = *posList.begin();
+ kdDebug() << *posList.begin() << " = " << *appList.begin() << endl;
+ posList.erase(posList.begin());
+ appList.pop_front();
+ }
+ //kdDebug() << "Done." << endl;
+}
+
+void QuickLauncher::addAppBeforeManually(QString url, QString sender)
+{
+ if (sender.isNull())
+ {
+ addApp(url, Append, true);
+ }
+ int pos = findApp(sender);
+ if (pos < 0)
+ {
+ pos = Append;
+ }
+ DEBUGSTR << "QuickLauncher::addAppBefore(" << url <<
+ "," << sender << "): pos=" << pos << endl << flush;
+ addApp(url, pos, true);
+}
+
+
+void QuickLauncher::about()
+{
+ KAboutData about("quicklauncher", I18N_NOOP("Quick Launcher"), "2.0",
+ I18N_NOOP("A simple application launcher"),
+ KAboutData::License_GPL_V2,
+ "(C) 2000 Bill Nagel\n(C) 2004 Dan Bullok\n(C) 2005 Fred Schaettgen");
+ KAboutApplication a(&about, this);
+ a.exec();
+}
+
+
+void QuickLauncher::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == RightButton)
+ {
+ m_popup->popup(e->globalPos());
+ }
+}
+
+void QuickLauncher::resizeEvent(QResizeEvent*)
+{
+ refreshContents();
+}
+
+void QuickLauncher::dragEnterEvent(QDragEnterEvent *e)
+{
+ DEBUGSTR << "QuickLauncher::dragEnterEvent(pos=" << e->pos() <<
+ " type=" << e->type() << ")" << endl << flush;
+ m_dragAccepted=false;
+ KURL::List kurlList;
+ if (!isDragEnabled() || !KURLDrag::decode(e, kurlList))
+ {
+ e->accept(false);
+ return;
+ }
+
+ if (kurlList.size()<=0)
+ {
+ e->accept(false);
+ return;
+ }
+ m_dragButtons=new ButtonGroup;
+ m_oldButtons=new ButtonGroup(*m_buttons);
+
+ QString url;
+ KURL::List::ConstIterator it = kurlList.begin();
+ for ( ; it != kurlList.end(); ++it )
+ {
+ url = QuickURL((*it).url()).url();
+ kdDebug() << " Drag Object='"<<url<<"' " << (*it).url() << endl;
+ int pos = m_buttons->findDescriptor(url);
+ if (pos != NotFound)
+ {
+ // if it's already in m_buttons, take it out
+ m_dragButtons->push_back(m_buttons->takeFrom(pos));
+ }
+ else
+ {
+ // otherwise, create a new one
+ QuickButton* button = createButton(url);
+ button->setSticky(true);
+ m_dragButtons->push_back(button);
+ }
+ }
+ if (m_dragButtons->size() > 0)
+ {
+ //make sure we can drag at least one button.
+ m_dragAccepted=true;
+ m_newButtons=new ButtonGroup(*m_buttons);
+ m_dropPos=NotFound;
+ e->accept(true);
+ return;
+ }
+ e->accept(false);
+ clearTempButtons();
+}
+
+
+void QuickLauncher::dragMoveEvent(QDragMoveEvent *e)
+{
+ if (!m_dragAccepted)
+ {
+ kdWarning() << "QuickLauncher::dragMoveEvent: Drag is not accepted." <<
+ m_dragAccepted << endl << flush;
+ e->accept(false);
+ return;
+ }
+
+ e->accept(true);
+ int pos=m_manager->indexNearest(e->pos());
+ if (pos == m_dropPos)
+ {
+ return;// Already been inserted here, no need to update
+ }
+
+ if (m_newButtons->isValidInsertIndex(pos))
+ {
+ mergeButtons(pos);
+ m_dropPos=pos;
+ }
+ refreshContents();
+}
+
+
+void QuickLauncher::dragLeaveEvent(QDragLeaveEvent *e)
+{
+ DEBUGSTR << "QuickLauncher::dragLeaveEvent(type=" <<
+ e->type() << ")" << endl << flush;
+ if (!m_dragAccepted)
+ {
+ return;
+ }
+
+ // No drop. Return to starting state.
+ std::swap(m_buttons,m_oldButtons);
+ clearTempButtons();
+
+ refreshContents();
+ saveConfig();
+}
+
+
+void QuickLauncher::dropEvent(QDropEvent *e)
+{
+ DEBUGSTR << "QuickLauncher::dropEvent(pos=" << e->pos() <<
+ " type=" << e->type() << ")" << endl << flush;
+ if (!m_dragAccepted)
+ {
+ e->accept(false);
+ return;
+ }
+
+ if (e->source() == 0)
+ {
+ for (uint n=0; n<m_dragButtons->size(); ++n)
+ {
+ (*m_dragButtons)[n]->setSticky(true);
+ }
+ }
+
+ clearTempButtons();
+ refreshContents();
+ saveConfig();
+ updateInsertionPosToStatusQuo();
+}
+
+// insert dragbuttons at index in m_newButtons. Put result in m_buttons
+void QuickLauncher::mergeButtons(int index)
+{
+ if (!m_newButtons->isValidInsertIndex(index))
+ {
+ index=m_newButtons->size();
+ }
+
+ m_buttons->clear();
+ (*m_buttons) = (*m_newButtons);
+ m_buttons->insertAt(index, *m_dragButtons);
+ refreshContents();
+}
+
+void QuickLauncher::clearTempButtons()
+{
+ std::set<QuickButton*> allButtons;
+ //put all the m_buttons in a set (removes duplicates automatically
+ if (m_newButtons)
+ {
+ allButtons.insert(m_newButtons->begin(),m_newButtons->end());
+ }
+ if (m_oldButtons)
+ {
+ allButtons.insert(m_oldButtons->begin(),m_oldButtons->end());
+ }
+ if (m_dragButtons)
+ {
+ allButtons.insert(m_dragButtons->begin(),m_dragButtons->end());
+ }
+
+ //delete temp ButtonGroups
+ delete m_newButtons; m_newButtons=0;
+ delete m_oldButtons; m_oldButtons=0;
+ delete m_dragButtons; m_dragButtons=0;
+
+ //if an element allButtons is NOT in m_buttons (the ones we keep), delete it
+ std::set<QuickButton *>::iterator iter = allButtons.begin();
+ while (iter != allButtons.end())
+ {
+ if (findApp(*iter) == NotFound)
+ {
+ delete *iter;
+ }
+ ++iter;
+ }
+ m_dragAccepted = false;
+ m_dropPos = NotFound;
+}
+
+void QuickLauncher::refreshContents()
+{
+ int idim, d(dimension());
+ // determine button size
+ if (m_settings->iconDim() == SIZE_AUTO)
+ {
+ if (d < 18)
+ {
+ idim = std::min(16,d);
+ }
+ else if (d < 64)
+ {
+ idim = 16;
+ }
+ else if (d < 80)
+ {
+ idim = 20;
+ }
+ else if (d < 122)
+ {
+ idim = 24;
+ }
+ else
+ {
+ idim = 28;
+ }
+ }
+ else
+ {
+ idim = std::min(m_settings->iconDim(), d - std::max((d/8)-1, 0) * 2);
+ }
+ m_space = std::max((idim/8)-1, 0);
+ m_border = m_space;
+ m_buttonSize = QSize(idim, idim);
+ m_manager->setOrientation(orientation());
+ m_manager->setNumItems(m_buttons->size());
+ m_manager->setFrameSize(size());
+ m_manager->setItemSize(m_buttonSize);
+ m_manager->setSpaceSize(QSize(m_space, m_space));
+ m_manager->setBorderSize(QSize(m_border, m_border));
+ if (!m_refreshEnabled)
+ {
+ m_needsRefresh=true;
+ return;
+ }
+ if (!m_manager->isValid())
+ {
+ kdDebug()<<endl<<"******WARNING****** Layout is invalid."<<
+ endl << flush;
+ m_manager->dump();
+ return;
+ }
+
+ unsigned index;
+ QPoint pos;
+ setUpdatesEnabled(false);
+ m_buttons->setUpdatesEnabled(false);
+ for (index = 0; index < m_buttons->size(); index++)
+ {
+ pos = m_manager->pos(index);
+ QuickButton *button = (*m_buttons)[index];
+ button->resize(m_manager->itemSize());
+ button->move(pos.x(), pos.y());
+ button->setDragging(false);
+ button->setEnableDrag(isDragEnabled());
+ button->setDynamicModeEnabled(m_settings->autoAdjustEnabled());
+ }
+ if (m_newButtons)
+ {
+ m_newButtons->setDragging(false);
+ }
+ if (m_dragButtons)
+ {
+ m_dragButtons->setDragging(true);
+ }
+ m_buttons->show();
+ setUpdatesEnabled(true);
+ update();
+ m_buttons->setUpdatesEnabled(true);
+ updateGeometry();
+ emit updateLayout();
+ updateStickyHighlightLayer();
+}
+
+
+void QuickLauncher::setDragEnabled(bool enable)
+{
+ m_settings->setDragEnabled(enable);
+}
+
+void QuickLauncher::setConserveSpace(bool conserve_space)
+{
+ m_manager->setConserveSpace(conserve_space);
+ if (conserve_space)
+ {
+ m_manager->setSlack(FlowGridManager::SpaceSlack,
+ FlowGridManager::SpaceSlack);
+ }
+ else
+ {
+ m_manager->setSlack(FlowGridManager::ItemSlack,
+ FlowGridManager::ItemSlack);
+ }
+ refreshContents();
+}
+
+class SortByPopularity {
+public:
+ bool operator()(const QuickLauncher::PopularityInfo& a,
+ const QuickLauncher::PopularityInfo& b)
+ {
+ return a.popularity < b.popularity;
+ }
+};
+
+void QuickLauncher::loadConfig()
+{
+ DEBUGSTR << "QuickLauncher::loadConfig()" << endl << flush;
+ //KConfig *c = config();
+ //c->setGroup("General");
+ setConserveSpace(m_settings->conserveSpace());
+ setDragEnabled(m_settings->dragEnabled());
+ /*DEBUGSTR << " IconDim="<<m_iconDim << endl << flush;
+ DEBUGSTR << " ConserveSpace=" << (m_manager->conserveSpace()) <<
+ endl << flush;
+ DEBUGSTR << " DragEnabled=" << isDragEnabled() << endl << flush;*/
+ QStringList volatileButtons = m_settings->volatileButtons();
+ QStringList urls = m_settings->buttons();
+ kdDebug() << "GetButtons " << urls.join("/") << endl;
+ QStringList::Iterator iter(urls.begin());
+ int n = 0;
+ while (iter != urls.end()) {
+ QString url = *iter;
+ addApp(url, n, false);
+ ++iter;
+ ++n;
+ }
+
+ // Restore sticky state
+ for (n=0; n<int(m_buttons->size()); ++n)
+ {
+ QuickButton* button = (*m_buttons)[n];
+ if (volatileButtons.contains(button->menuId()) == false)
+ {
+ button->setSticky(true);
+ }
+ button->setDynamicModeEnabled(m_settings->autoAdjustEnabled());
+ }
+
+ m_popularity->readConfig(m_settings);
+ m_popularity->setHistoryHorizon(m_settings->historyHorizon()/100.0);
+
+ QStringList serviceNames = m_settings->serviceNames();
+ QValueList<int> insPos = m_settings->serviceInspos();
+ for (int n=std::min(serviceNames.size(),insPos.size())-1; n>=0; --n)
+ {
+ m_appOrdering[serviceNames[n]] = insPos[n];
+ }
+}
+
+void QuickLauncher::saveConfig()
+{
+ if (!m_refreshEnabled)
+ {
+ m_needsSave=true;
+ return;
+ }
+ QStringList urls, volatileUrls;
+ ButtonIter iter = m_buttons->begin();
+ while (iter != m_buttons->end()) {
+ if ((*iter)->sticky() == false)
+ {
+ volatileUrls.append((*iter)->menuId());
+ }
+ urls.append((*iter)->menuId());
+ ++iter;
+ }
+ m_settings->setButtons(urls);
+ kdDebug() << "SetButtons " << urls.join("/") << endl;
+ m_settings->setVolatileButtons(volatileUrls);
+ m_settings->setConserveSpace(m_manager->conserveSpace());
+ m_settings->setDragEnabled(isDragEnabled());
+
+ m_popularity->writeConfig(m_settings);
+
+ // m_popularity must have written the current service list by now
+ QStringList serviceNames = m_settings->serviceNames();
+ QValueList<int> insertionPositions;
+ for (int n=0; n<int(serviceNames.size()); ++n)
+ {
+ if (m_appOrdering.find(serviceNames[n]) != m_appOrdering.end())
+ {
+ insertionPositions.push_back(m_appOrdering[serviceNames[n]]);
+ }
+ }
+ m_settings->setServiceInspos(insertionPositions);
+
+ m_settings->writeConfig();
+}
+
+
+void QuickLauncher::setRefreshEnabled(bool enable)
+{
+ m_refreshEnabled=enable;
+ if (m_refreshEnabled)
+ {
+ if (m_needsSave) {
+ saveConfig();
+ }
+ if (m_needsRefresh) {
+ refreshContents();
+ }
+ }
+}
+
+void QuickLauncher::serviceStartedByStorageId(QString /*starter*/, QString storageId)
+{
+ KService::Ptr service = KService::serviceByStorageId(storageId);
+ if (service->icon() == QString::null)
+ {
+ kdDebug() << storageId << " has no icon. Makes no sense to add it.";
+ return;
+ }
+ QuickURL url = QuickURL(locate("apps", service->desktopEntryPath()));
+ QString desktopMenuId(url.menuId());
+ kdDebug() << "storageId=" << storageId << " desktopURL=" << desktopMenuId << endl;
+ // A service was started somwhere else. If the quicklauncher contains
+ // this service too, we flash the icon
+ QuickButton *startedButton = 0;
+ std::set<QString> buttonIdSet;
+ for (uint n = 0; n < m_buttons->size(); ++n)
+ {
+ QuickButton *button = (*m_buttons)[n];
+ QString buttonMenuId = button->menuId();
+ buttonIdSet.insert(buttonMenuId);
+ if (desktopMenuId == buttonMenuId)
+ {
+ kdDebug() << "QuickLauncher: I know that one: " << storageId << endl;
+ button->flash();
+ startedButton = button;
+ }
+ }
+
+ // Update popularity info.
+ // We do this even if autoadjust is disabled
+ // so there are sane values to start with if it's turned on.
+ m_popularity->useService(desktopMenuId);
+
+ if (m_settings->autoAdjustEnabled())
+ {
+ QTimer::singleShot(0, this, SLOT(slotAdjustToCurrentPopularity()));
+ }
+}
+
+void QuickLauncher::slotAdjustToCurrentPopularity()
+{
+ // TODO: Shrink immediately if buttons->size() > maxItems
+ kdDebug() << "Starting popularity update" << endl;
+ PopularityStatistics* stats = m_popularity;
+ int minItems = m_settings->autoAdjustMinItems();
+ int maxItems = m_settings->autoAdjustMaxItems();
+
+ static const double hysteresisFactor = 0.90;
+ double minAddPopularity = 0;
+ for (int n = 0; n < maxItems; ++n)
+ {
+ // All items with a popularity not less than 0.75 of the average
+ // of the first maxItems apps are included in the list
+ double belowAvgAllowed = 0.75;
+ minAddPopularity += (belowAvgAllowed * stats->popularityByRank(n)) / maxItems;
+ }
+ double minDelPopularity = minAddPopularity * hysteresisFactor;
+ std::map<QString, QuickButton*> removeableApps;
+ std::set<QString> existingApps;
+ int numApps = m_buttons->size();
+ for (int n = 0; n < int(m_buttons->size()); ++n)
+ {
+ QuickButton *button = (*m_buttons)[n];
+ if (((stats->popularityByRank(stats->rankByService(button->menuId())) <
+ minDelPopularity) || m_settings->autoAdjustEnabled()==false) &&
+ (button->sticky() == false))
+ {
+ removeableApps[button->menuId()] = button;
+ --numApps;
+ }
+ existingApps.insert(button->menuId());
+ }
+ for (int n = 0;
+ (numApps < minItems && stats->popularityByRank(n) > 0) ||
+ (numApps < maxItems && stats->popularityByRank(n) > minAddPopularity);
+ ++n)
+ {
+ QString app = m_popularity->serviceByRank(n);
+ if (existingApps.find(app) == existingApps.end())
+ {
+ addApp(QuickURL(m_popularity->serviceByRank(n)).url(), false);
+ kdDebug() << "Adding app " << app << endl;
+ ++numApps;
+ }
+ else if (removeableApps.find(app) != removeableApps.end())
+ {
+ removeableApps.erase(app);
+ ++numApps;
+ }
+ }
+ while (removeableApps.size() > 0)
+ {
+ removeApp(findApp(removeableApps.begin()->second), false);
+ kdDebug() << "Removing app " << removeableApps.begin()->first << endl;
+ removeableApps.erase(removeableApps.begin()->first);
+ }
+ kdDebug() << "done popularity update" << endl;
+ m_settings->setAutoAdjustMinItems(minItems);
+ m_settings->setAutoAdjustMaxItems(maxItems);
+
+ // TODO: Think of something better than that:
+ m_saveTimer->start(10000,true);
+}
+
+void QuickLauncher::slotOwnServiceExecuted(QString serviceMenuId)
+{
+ m_popularity->useService(serviceMenuId);
+ if (m_settings->autoAdjustEnabled())
+ {
+ QTimer::singleShot(0, this, SLOT(slotAdjustToCurrentPopularity()));
+ }
+}
+
+void QuickLauncher::updateStickyHighlightLayer()
+{
+ // Creates a transparent image which is used
+ // to highlight those buttons which will never
+ // be removed automatically from the launcher
+ QPixmap areaPix(width(), height());
+ QPainter areaPixPainter(&areaPix);
+ areaPixPainter.fillRect(0, 0, width(), height(), QColor(255, 255, 255));
+ QSize itemSize = m_manager->itemSize();
+ QSize spaceSize = m_manager->spaceSize();
+ for (uint n=0; n<m_buttons->size(); ++n)
+ {
+ QPoint pos = m_manager->pos(n);
+ if ((*m_buttons)[n]->sticky() == false)
+ {
+ areaPixPainter.fillRect(pos.x()-(spaceSize.width()+1)/2,
+ pos.y()-(spaceSize.height()+1)/2,
+ itemSize.width()+spaceSize.width()+1,
+ itemSize.height()+spaceSize.height()+1,
+ QColor(0, 0, 0));
+ }
+ }
+ QImage areaLayer = areaPix.convertToImage();
+ m_stickyHighlightLayer = QImage(width(), height(), 32);
+ m_stickyHighlightLayer.setAlphaBuffer(true);
+ int pix, tlPix, brPix, w(width()), h(height());
+ QRgb transparent(qRgba(0, 0, 0, 0));
+ for (int y = h-1; y >= 0; --y)
+ {
+ for (int x = w-1; x >= 0; --x)
+ {
+ pix = qRed(areaLayer.pixel(x, y));
+ if (pix == 0)
+ {
+ tlPix = (y>0 && x>0) ? qRed(areaLayer.pixel(x-1,y-1)) : 255;
+ brPix = (y<h-1 && x<w-1) ? qRed(areaLayer.pixel(x+1,y+1)) : 255;
+ int c = tlPix-brPix < 0 ? 255 : 0;
+ int alpha = abs(tlPix-brPix)/2;
+ m_stickyHighlightLayer.setPixel(x, y, qRgba(c, c, c, alpha));
+ }
+ else
+ {
+ m_stickyHighlightLayer.setPixel(x, y, transparent);
+ }
+ }
+ }
+ repaint();
+}
+
+void QuickLauncher::paintEvent(QPaintEvent* e)
+{
+ KPanelApplet::paintEvent(e);
+
+ if (m_settings->autoAdjustEnabled() &&
+ m_settings->showVolatileButtonIndicator())
+ {
+ QPainter p(this);
+ p.drawImage(0, 0, m_stickyHighlightLayer);
+ }
+}
+
+void QuickLauncher::slotStickyToggled()
+{
+ updateStickyHighlightLayer();
+ saveConfig();
+}
+
+void QuickLauncher::positionChange(Position)
+{
+ for (int n=0; n<int(m_buttons->size()); ++n)
+ {
+ (*m_buttons)[n]->setPopupDirection(popupDirection());
+ }
+}
+
+
+#include "quicklauncher.moc"
diff --git a/kicker/applets/launcher/quicklauncher.desktop b/kicker/applets/launcher/quicklauncher.desktop
new file mode 100644
index 000000000..0e80149aa
--- /dev/null
+++ b/kicker/applets/launcher/quicklauncher.desktop
@@ -0,0 +1,140 @@
+[Desktop Entry]
+Type=Plugin
+Name=Quick Launcher
+Name[af]=Vinnige Lanseerder
+Name[ar]=الإنطلاق السريع
+Name[az]=Sür'ətli Başladıcı
+Name[be]=Хуткі запускальнік
+Name[bg]=Бързо стартиране
+Name[bn]=কুইক লঞ্চার
+Name[br]=Loc'her prim
+Name[bs]=Brzo pokretanje
+Name[ca]=Engegador ràpid
+Name[cs]=Rychlé spouštění aplikací
+Name[csb]=Chùtczé zrëszenié
+Name[cy]=Cychwynydd Cyflym
+Name[da]=Hurtigstarter
+Name[de]=Schnellstarter
+Name[el]=Γρήγορη φόρτωση
+Name[eo]=Rapidlanĉilo
+Name[es]=Lanzador rápido
+Name[et]=Kiirkäivitaja
+Name[eu]=Abiarazle bizkorra
+Name[fa]=راه‌انداز سریع
+Name[fi]=Sovellusten pikakäynnistin
+Name[fr]=Lanceur d'applications
+Name[fy]=Snel útfierder
+Name[ga]=Tosaitheoir Tapa
+Name[gl]=Lanzador Rápido
+Name[he]=הפעלה מהירה
+Name[hi]=द्रुत लांचर
+Name[hr]=Brzo pokretanje
+Name[hu]=Gyorsindító
+Name[id]=Launcher Cepat
+Name[is]=Flýtiræsir
+Name[it]=Esecuzione rapida
+Name[ja]=クイックランチャー
+Name[ka]=სწრაფი დაწყება
+Name[kk]=Жедел жегуші
+Name[km]=អ្នក​ចាប់ផ្ដើម​រហ័ស
+Name[lo]=ຮງກທຳງານດ່ວນ
+Name[lt]=Greitasis paleidimas
+Name[lv]=Ātrais Palaidējs
+Name[mk]=Брз стартувач
+Name[mn]=Түргэн ажилуулагч
+Name[ms]=Pelancar Pantas
+Name[mt]=Ħaddem Malajr
+Name[nb]=Hurtigstarter
+Name[nds]=Fixstarter
+Name[ne]=द्रुत सुरुआत
+Name[nl]=Snelstarter
+Name[nn]=Snøggstartar
+Name[nso]=Ngwadisoleswa ya Kapela
+Name[oc]=Engegador rapid
+Name[pa]=ਚੁਸਤ ਸ਼ੁਰੂਆਤੀ
+Name[pl]=Szybkie uruchamianie
+Name[pt]=Execução de Aplicações
+Name[pt_BR]=Lançador rápido
+Name[ro]=Executor rapid
+Name[ru]=Быстрый запуск
+Name[rw]=Mutangiza Yihuta
+Name[se]=Jođánisálggaheaddji
+Name[sk]=Rýchly spúšťač
+Name[sl]=Hitri zaganjalnik
+Name[sr]=Брзи покретач
+Name[sr@Latn]=Brzi pokretač
+Name[sv]=Snabbstartare
+Name[ta]=உடனடியாக திரையில் தெரிதல்
+Name[te]=త్వరగా మొదలుపెట్టెది
+Name[tg]=Сар додани тез
+Name[th]=เรียกทำงานด่วน
+Name[tr]=Hızlı Başlatıcı
+Name[tt]=Tiz Cibärgeç
+Name[uk]=Швидкий запуск
+Name[uz]=Tez ishga tushirgich
+Name[uz@cyrillic]=Тез ишга туширгич
+Name[ven]=Tavhanya
+Name[vi]=Khởi động nhanh
+Name[wa]=Enondeu al vole di programes
+Name[zh_CN]=快速启动
+Name[zh_TW]=快速起動
+Name[zu]=Umqalisi osheshayo
+Comment=Directly access your frequently used applications
+Comment[af]=Kry direkte toegang tot die programme wat jy gereeld gebruik
+Comment[ar]=للوصول المباشر إلى تطبيقاتك الأكثر إستعمالاً
+Comment[be]=Наўпрост запускае праграму
+Comment[bg]=Бърз достъп до често използваните програми
+Comment[bn]=আপনার সবচেয়ে ঘনঘন ব্যবহৃত অ্যাপলিকেশনগুলি সরাসরি চালু করুন
+Comment[bs]=Direktno pristupite vašim često korištenim programima
+Comment[ca]=Accedeix directament a les aplicacions més usades
+Comment[cs]=Přímý přístup k nejčastěji používaným aplikacím
+Comment[csb]=Prosti przistãp do nôczãstczi brëkòwónëch programów
+Comment[da]=Direkte adgang til programmer du ofte bruger
+Comment[de]=Schneller Zugriff auf häufig verwendete Programme
+Comment[el]=Απευθείας πρόσβαση στις συχνά χρησιμοποιούμενες εφαρμογές σας
+Comment[eo]=Rekte atingi viajn preferatajn aplikaĵojn
+Comment[es]=Acceso directo a las aplicaciones usadas más frecuentemente
+Comment[et]=Ligipääs sagedamini kasutatud rakendustele
+Comment[eu]=Sarbide zuzena zure ohiko aplikazioei
+Comment[fa]=دستیابی مستقیم به کاربردهای مکرر استفاده‌شدۀ شما
+Comment[fi]=Siirry suoraan useimmin käyttämiisi sovelluksiin
+Comment[fr]=Accès direct aux applications les plus utilisées
+Comment[fy]=Direkte tagong ta jo faak brûkte programma's
+Comment[gl]=Aceda directamenta ás aplicacións que use mais amiudo
+Comment[he]=גישה מהירה ליישומים שאתה משתמש בהם הכי הרבה
+Comment[hr]=Izravni pristup najčešće upotrebljavanim aplikacijama
+Comment[hu]=A gyakran használt alkalmazások közvetlen elérése
+Comment[is]=Beinn aðgangur að mest notuðu forritunum þínum
+Comment[it]=Accesso diretto alle applicazioni usate più frequentemente
+Comment[ja]=よく用いるアプリケーションに直接アクセス
+Comment[kk]=Жиі пайдаланатын қолданбаларды тез жегу
+Comment[km]=ដំណើរការ​កម្មវិធី​ដែល​បាន​ប្រើ​ជា​រឿយៗ​របស់អ្នក​ដោយ​ផ្ទាល់
+Comment[lt]=Tiesiogiai pasiekite dažniausiai naudojamas programas
+Comment[mk]=Пристапете директно на вашите често користени апликации
+Comment[nb]=Få direkte tilgang til ofte brukte programmer
+Comment[nds]=Direktemang Dien meist bruukte Programmen opropen
+Comment[ne]=बारम्बार प्रयोग भएका अनुप्रयोगमा तपाईँको प्रत्यक्ष पहुँच
+Comment[nl]=Directe toegang tot uw veelgebruikte programma's
+Comment[nn]=Direkte tilgang til program du brukar ofte
+Comment[pa]=ਅਕਸਰ ਵਰਤੇ ਜਾਂਦੇ ਕਾਰਜਾਂ ਲਈ ਸਿੱਧੀ ਪਹੁੰਚ
+Comment[pl]=Bezpośredni dostęp do najczęściej używanych programów
+Comment[pt]=Aceder directamente às aplicações usadas com mais frequência por si
+Comment[pt_BR]=Acesso direito à seus aplicativos mais freqüentemente usados
+Comment[ro]=Accesează direct aplicațiile folosite frecvent
+Comment[ru]=Быстрый вызов часто используемых приложений
+Comment[sk]=Priamo zprístupní najčastejšie používané programy.
+Comment[sl]=Neposreden dostop do vaših najbolj uporabljanih programov
+Comment[sr]=Директно приступите својим често коришћеним програмима
+Comment[sr@Latn]=Direktno pristupite svojim često korišćenim programima
+Comment[sv]=Direkt åtkomst av program du ofta använder
+Comment[th]=เรียกใช้งานแอพพลิเคชั่นที่คุณใช้บ่อยๆ ได้โดยตรง
+Comment[tr]=Sıkça kullanılan programlara erişim sağlar
+Comment[uk]=Безпосередній доступ до програм, які часто вживаються
+Comment[uz]=Eng koʻp ishlatilgan dasturlarga qisqa yoʻl
+Comment[uz@cyrillic]=Энг кўп ишлатилган дастурларга қисқа йўл
+Comment[vi]=Chạy ngay các trình bạn thường xuyên dùng
+Comment[wa]=Accès direk ås programes sovint eployîs
+Comment[zh_CN]=直接访问您最经常使用的应用程序
+Comment[zh_TW]=直接存取您最常使用的應用程式
+Icon=launch
+X-KDE-Library=launcher_panelapplet
diff --git a/kicker/applets/launcher/quicklauncher.h b/kicker/applets/launcher/quicklauncher.h
new file mode 100644
index 000000000..c82d39661
--- /dev/null
+++ b/kicker/applets/launcher/quicklauncher.h
@@ -0,0 +1,138 @@
+/*****************************************************************
+
+Copyright (c) 2000 Bill Nagel
+
+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 __quicklauncher_h__
+#define __quicklauncher_h__
+
+#include <dcopobject.h>
+#include <qimage.h>
+#include <qstring.h>
+#include <qvaluevector.h>
+#include <kpanelapplet.h>
+#include <map>
+
+#include "flowgridmanager.h"
+#include "prefs.h"
+#include "quickbutton.h"
+
+class ConfigDlg;
+class QPopupMenu;
+class QuickButtonGroup;
+class PopularityStatistics;
+class KAction;
+
+typedef QuickButtonGroup ButtonGroup;
+
+class QuickLauncher: public KPanelApplet, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+k_dcop:
+ void serviceStartedByStorageId(QString starter, QString storageId);
+
+public:
+ enum {DEFAULT_ICON_DIM=QuickButton::DEFAULT_ICON_DIM};
+ enum {SIZE_AUTO=0};
+
+ struct PopularityInfo {
+ float popularity;
+ };
+
+ QuickLauncher(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ ~QuickLauncher();
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+ void addApp(QString url, int index, bool manuallyAdded);
+ virtual void action(Action a);
+
+public slots:
+ void addApp(QString url, bool manuallyAdded);
+ void addAppBeforeManually(QString url, QString sender);
+ void removeAppManually(QuickButton *button);
+ void removeApp(QString url, bool manuallyRemoved);
+ void removeApp(int index, bool manuallyRemoved);
+ void removeAppManually(int index);
+ void saveConfig();
+ void about();
+
+protected:
+ int findApp(QString url);
+ int findApp(QuickButton *button);
+
+ void mousePressEvent(QMouseEvent *e);
+ void resizeEvent(QResizeEvent*);
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dragLeaveEvent(QDragLeaveEvent *e);
+ void dragMoveEvent(QDragMoveEvent *e);
+ void dropEvent(QDropEvent *e);
+ void refreshContents();
+ void setRefreshEnabled(bool enable);
+ void setConserveSpace(bool conserve_space);
+ void setDragEnabled(bool conserve_space);
+
+ bool conserveSpace() const { return m_manager->conserveSpace(); }
+ bool isDragEnabled() const { return m_settings->dragEnabled(); }
+
+ void buildPopupMenu();
+ void loadConfig();
+
+ void mergeButtons(int index);
+ void clearTempButtons();
+ int dimension() const;
+
+protected slots:
+ void slotConfigure();
+ void slotSettingsDialogChanged();
+ void fillRemoveAppsMenu();
+ void slotOwnServiceExecuted(QString serviceMenuId);
+ void slotAdjustToCurrentPopularity();
+ void slotStickyToggled();
+
+protected:
+ void updateInsertionPosToStatusQuo();
+ void updateStickyHighlightLayer();
+ QuickButton* createButton(QString url);
+ virtual void paintEvent(QPaintEvent* e);
+ virtual void positionChange(Position);
+
+ QPopupMenu *m_popup;
+ QPopupMenu *m_appletPopup;
+ QPopupMenu *m_removeAppsMenu;
+ QuickButtonGroup *m_buttons, *m_newButtons, *m_oldButtons, *m_dragButtons;
+ int m_space, m_border;
+ QSize m_buttonSize;
+ FlowGridManager *m_manager;
+ int m_dropLen, m_dropPos, m_minPanelDim;
+ bool m_dragAccepted, m_refreshEnabled, m_needsSave, m_needsRefresh;
+ std::map<QString, int> m_appOrdering;
+ Prefs* m_settings;
+ KAction *m_configAction;
+ ConfigDlg *m_configDialog;
+ PopularityStatistics* m_popularity;
+ QImage m_stickyHighlightLayer;
+ QTimer *m_saveTimer;
+};
+
+#endif
diff --git a/kicker/applets/lockout/Makefile.am b/kicker/applets/lockout/Makefile.am
new file mode 100644
index 000000000..f9772adf5
--- /dev/null
+++ b/kicker/applets/lockout/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = -I$(top_srcdir)/kicker/libkicker $(all_includes)
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = lockout_panelapplet.la
+
+lockout_panelapplet_la_SOURCES = lockout.cpp
+lockout_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+lockout_panelapplet_la_LIBADD = ../../libkicker/libkickermain.la $(LIB_KSYCOCA)
+
+noinst_HEADERS = lockout.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = lockout.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/lockout.pot
diff --git a/kicker/applets/lockout/README b/kicker/applets/lockout/README
new file mode 100644
index 000000000..e25954c3d
--- /dev/null
+++ b/kicker/applets/lockout/README
@@ -0,0 +1,4 @@
+A very simple applet that shows two buttons, one for locking the desktop,
+the other to invoke the logout process.
+
+Carsten Pfeiffer <[email protected]>
diff --git a/kicker/applets/lockout/lockout.cpp b/kicker/applets/lockout/lockout.cpp
new file mode 100644
index 000000000..d22e4a8ed
--- /dev/null
+++ b/kicker/applets/lockout/lockout.cpp
@@ -0,0 +1,278 @@
+/*****************************************************************
+
+Copyright (c) 2001 Carsten Pfeiffer <[email protected]>
+ 2001 Matthias Elter <[email protected]>
+ 2001 Martijn Klingens <[email protected]>
+
+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 <qlayout.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qpopupmenu.h>
+#include <qtoolbutton.h>
+#include <qstyle.h>
+#include <qtooltip.h>
+
+#include <dcopclient.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <krun.h>
+#include <kdebug.h>
+
+#include <stdlib.h>
+#include "lockout.h"
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("lockout");
+ return new Lockout(configFile, parent, "lockout");
+ }
+}
+
+Lockout::Lockout( const QString& configFile, QWidget *parent, const char *name)
+ : KPanelApplet( configFile, KPanelApplet::Normal, 0, parent, name ), bTransparent( false )
+{
+ KConfig *conf = config();
+ conf->setGroup("lockout");
+
+ //setFrameStyle(Panel | Sunken);
+ setBackgroundOrigin( AncestorOrigin );
+
+ if ( orientation() == Horizontal )
+ layout = new QBoxLayout( this, QBoxLayout::TopToBottom );
+ else
+ layout = new QBoxLayout( this, QBoxLayout::LeftToRight );
+
+ layout->setAutoAdd( true );
+ layout->setMargin( 0 );
+ layout->setSpacing( 0 );
+
+ lockButton = new SimpleButton( this, "lock");
+ logoutButton = new SimpleButton( this, "logout");
+
+ QToolTip::add( lockButton, i18n("Lock the session") );
+ QToolTip::add( logoutButton, i18n("Log out") );
+
+ lockButton->setPixmap( SmallIcon( "lock" ));
+ logoutButton->setPixmap( SmallIcon( "exit" ));
+
+ bTransparent = conf->readBoolEntry( "Transparent", bTransparent );
+
+ connect( lockButton, SIGNAL( clicked() ), SLOT( lock() ));
+ connect( logoutButton, SIGNAL( clicked() ), SLOT( logout() ));
+
+ lockButton->installEventFilter( this );
+ logoutButton->installEventFilter( this );
+
+ if (!kapp->authorize("lock_screen"))
+ lockButton->hide();
+
+ if (!kapp->authorize("logout"))
+ logoutButton->hide();
+
+ lockButton->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
+ logoutButton->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
+
+ if ( !kapp->dcopClient()->isAttached() )
+ kapp->dcopClient()->attach();
+
+ connect( kapp, SIGNAL( iconChanged(int) ), SLOT( slotIconChanged() ));
+}
+
+Lockout::~Lockout()
+{
+ KGlobal::locale()->removeCatalogue("lockout");
+}
+
+// the -2 is due to kicker allowing us a width/height of 42 and the buttons
+// having a size of 44. So we rather cut those 2 pixels instead of changing
+// direction and wasting a lot of space.
+void Lockout::checkLayout( int height ) const
+{
+ QSize s = minimumSizeHint();
+ QBoxLayout::Direction direction = layout->direction();
+
+ if ( direction == QBoxLayout::LeftToRight &&
+ ( ( orientation() == Vertical && s.width() - 2 >= height ) ||
+ ( orientation() == Horizontal && s.width() - 2 < height ) ) ) {
+ layout->setDirection( QBoxLayout::TopToBottom );
+ }
+ else if ( direction == QBoxLayout::TopToBottom &&
+ ( ( orientation() == Vertical && s.height() - 2 < height ) ||
+ ( orientation() == Horizontal && s.height() - 2 >= height ) ) ) {
+ layout->setDirection( QBoxLayout::LeftToRight );
+ }
+}
+
+int Lockout::widthForHeight( int height ) const
+{
+ checkLayout( height );
+ return sizeHint().width();
+}
+
+int Lockout::heightForWidth( int width ) const
+{
+ checkLayout( width );
+ return sizeHint().height();
+}
+
+void Lockout::lock()
+{
+ QCString appname( "kdesktop" );
+ int kicker_screen_number = qt_xscreen();
+ if ( kicker_screen_number )
+ appname.sprintf("kdesktop-screen-%d", kicker_screen_number);
+ kapp->dcopClient()->send(appname, "KScreensaverIface", "lock()", "");
+}
+
+void Lockout::logout()
+{
+ kapp->requestShutDown();
+}
+
+void Lockout::mousePressEvent(QMouseEvent* e)
+{
+ propagateMouseEvent(e);
+}
+
+void Lockout::mouseReleaseEvent(QMouseEvent* e)
+{
+ propagateMouseEvent(e);
+}
+
+void Lockout::mouseDoubleClickEvent(QMouseEvent* e)
+{
+ propagateMouseEvent(e);
+}
+
+void Lockout::mouseMoveEvent(QMouseEvent* e)
+{
+ propagateMouseEvent(e);
+}
+
+void Lockout::propagateMouseEvent(QMouseEvent* e)
+{
+ if ( !isTopLevel() ) {
+ QMouseEvent me(e->type(), mapTo( topLevelWidget(), e->pos() ),
+ e->globalPos(), e->button(), e->state() );
+ QApplication::sendEvent( topLevelWidget(), &me );
+ }
+}
+
+bool Lockout::eventFilter( QObject *o, QEvent *e )
+{
+ if (!kapp->authorizeKAction("kicker_rmb"))
+ return false; // Process event normally:
+
+ if( e->type() == QEvent::MouseButtonPress )
+ {
+ KConfig *conf = config();
+ conf->setGroup("lockout");
+
+ QMouseEvent *me = static_cast<QMouseEvent *>( e );
+ if( me->button() == QMouseEvent::RightButton )
+ {
+ if( o == lockButton )
+ {
+ QPopupMenu *popup = new QPopupMenu();
+
+ popup->insertItem( SmallIcon( "lock" ), i18n("Lock Session"),
+ this, SLOT( lock() ) );
+ popup->insertSeparator();
+
+ i18n("&Transparent");
+ //popup->insertItem( i18n( "&Transparent" ), 100 );
+ popup->insertItem( SmallIcon( "configure" ),
+ i18n( "&Configure Screen Saver..." ),
+ this, SLOT( slotLockPrefs() ) );
+
+ //popup->setItemChecked( 100, bTransparent );
+ //popup->connectItem(100, this, SLOT( slotTransparent() ) );
+ //if (conf->entryIsImmutable( "Transparent" ))
+ // popup->setItemEnabled( 100, false );
+ popup->exec( me->globalPos() );
+ delete popup;
+
+ return true;
+ }
+ else if ( o == logoutButton )
+ {
+ QPopupMenu *popup = new QPopupMenu();
+
+ popup->insertItem( SmallIcon( "exit" ), i18n("&Log Out..."),
+ this, SLOT( logout() ) );
+ popup->insertSeparator();
+ //popup->insertItem( i18n( "&Transparent" ), 100 );
+ popup->insertItem( SmallIcon( "configure" ),
+ i18n( "&Configure Session Manager..." ),
+ this, SLOT( slotLogoutPrefs() ) );
+
+ //popup->setItemChecked( 100, bTransparent );
+ //popup->connectItem(100, this, SLOT( slotTransparent() ) );
+ //if (conf->entryIsImmutable( "Transparent" ))
+ // popup->setItemEnabled( 100, false );
+ popup->exec( me->globalPos() );
+ delete popup;
+
+ return true;
+ } // if o
+ } // if me->button
+ } // if e->type
+
+ // Process event normally:
+ return false;
+}
+
+void Lockout::slotLockPrefs()
+{
+ // Run the screensaver settings
+ KRun::run( "kcmshell screensaver", KURL::List() );
+}
+
+void Lockout::slotTransparent()
+{
+ bTransparent = !bTransparent;
+
+ KConfig* conf = config();
+ conf->setGroup("lockout");
+ conf->writeEntry( "Transparent", bTransparent );
+ conf->sync();
+}
+
+void Lockout::slotLogoutPrefs()
+{
+ // Run the logout settings.
+ KRun::run( "kcmshell kcmsmserver", KURL::List() );
+}
+
+void Lockout::slotIconChanged()
+{
+ lockButton->setPixmap( SmallIcon( "lock" ));
+ logoutButton->setPixmap( SmallIcon( "exit" ));
+}
+
+#include "lockout.moc"
diff --git a/kicker/applets/lockout/lockout.desktop b/kicker/applets/lockout/lockout.desktop
new file mode 100644
index 000000000..e8681cc88
--- /dev/null
+++ b/kicker/applets/lockout/lockout.desktop
@@ -0,0 +1,125 @@
+[Desktop Entry]
+Type=Plugin
+Name=Lock/Logout Buttons
+Name[af]=Sluit/Teken af Knoppies
+Name[ar]=أزرار الإقفال/الخروج
+Name[be]=Кнопкі блакавання/выхаду
+Name[bg]=Заключване и изход
+Name[bn]=লক/লগ-আউট বাটন
+Name[bs]=Dugmad za zaključavanje/odjavu
+Name[ca]=Botons bloqueja/surt
+Name[cs]=Tlačítka odhlášení/uzamčení
+Name[csb]=Knąpë blokòwaniô ekranu/wëlogòwaniô
+Name[da]=Lås/Logaf-knapper
+Name[de]=Bildschirmsperre und Abmeldung aus KDE
+Name[el]=Κουμπιά κλειδώματος/αποσύνδεσης
+Name[eo]=Ŝloso- kaj adiaŭo-butonoj
+Name[es]=Botones de bloqueo/salida
+Name[et]=Lukustamise/väljalogimise nupud
+Name[eu]=Blokeatu/Irteteko botoiak
+Name[fa]=دکمه‌های قفل/خروج
+Name[fi]=Lukitus/Uloskirjautumispainikkeet
+Name[fr]=Boutons de verrouillage et déconnexion
+Name[fy]=Beskoattelje/ôfmeldknoppen
+Name[ga]=Cnaipí Glasála/Logála Amach
+Name[gl]=Botóns de Bloqueo/Saída
+Name[he]=כפתורי נעילה\יציאה
+Name[hr]=Gumb za zaključavanje/odjavljivanje
+Name[hu]=Zároló/kijelentkező gombok
+Name[is]=Læsa/stimpla út hnappar
+Name[it]=Pulsanti di uscita e bloccaggio schermo
+Name[ja]=ロック/ログアウトボタン
+Name[ka]=დაბლოკვის/გამოსვლის ღილაკები
+Name[kk]=Шығу не экранды бұғаттау батырмалары
+Name[km]=ប៊ូតុង ចាក់សោ/ចេញ
+Name[ko]=잠금/로그아웃
+Name[lt]=Užrakinimo/išsiregistravimo mygtukai
+Name[mk]=Копчиња „Заклучи/Одјави се“
+Name[nb]=Panelprogram for skjermlås/utlogging
+Name[nds]=Knööp för dat Afsluten oder Afmellen
+Name[ne]=ताल्चा लगाउने/लगआउट गर्ने बटन
+Name[nl]=Vergrendel/afmeldknoppen
+Name[nn]=Knappar for skjermlås/utlogging
+Name[pa]=ਤਾਲਾ/ਬਾਹਰੀ ਦਰ ਬਟਨ
+Name[pl]=Przyciski blokowania ekranu/wylogowania
+Name[pt]=Botões de Bloqueio/Saída
+Name[pt_BR]=Botões de Travar/Sair
+Name[ro]=Butoane de blocare/ieșire
+Name[ru]=Кнопки выхода и запирания экрана
+Name[se]=Lohkadan/olggosčálihan boalut
+Name[sk]=Tlačidlá na ohlásenie/zamknutie
+Name[sl]=Gumba za zaklep in odjavo
+Name[sr]=Дугмад за закључавање/одјављивање
+Name[sr@Latn]=Dugmad za zaključavanje/odjavljivanje
+Name[sv]=Lås/Logga ut-knappar
+Name[te]=తాళం వెయి/లాగౌట్ బటన్లు
+Name[tg]=Тугмаҳои Қулф/Баромадан
+Name[th]=ปุ่มล็อค/ล็อกเอาท์
+Name[tr]=Kilitle/Çık Düğmeleri
+Name[uk]=Кнопки Замикання/Виходу з системи
+Name[uz]=Qulflash/chiqish tugmalari
+Name[uz@cyrillic]=Қулфлаш/чиқиш тугмалари
+Name[vi]=Tiểu ứng dụng Khoá/Đăng xuất
+Name[wa]=Boton po serer a clé ou dislodjî
+Name[zh_CN]=锁定/注销按钮
+Name[zh_TW]=「螢幕鎖定/登出」按鈕
+Comment=Adds buttons for locking screen and session logout
+Comment[af]=Voeg skerm sluit en afteken knoppies by
+Comment[ar]=يضيف أزرار لإقفال الشاشة و الخروج من الجلسة
+Comment[be]=Дадае кнопкі для блакіроўкі экрана і заканчэння сесіі
+Comment[bg]=Добавяне на бутоните за заключване на екрана и изход
+Comment[bn]=স্ক্রীণ লক এবং লগ-আউট করার জন্য বাটন যোগ করে
+Comment[bs]=Dodaje na panel dugmad za zaključavanje ekrana i odjavu sa sistema
+Comment[ca]=Afegeix botons per bloquejar la pantalla i sortir de la sessió
+Comment[cs]=Přidá tlačítka pro uzamčení obrazovky a odhlášení z relace
+Comment[csb]=Dodôwô knapë blokòwaniô ekranu ë wëlogòwaniô
+Comment[da]=Tilføjer knapper for at låse skærmen og logge ud fra sessionen
+Comment[de]=Fügt Knöpfe zur Bildschirmsperre und Abmeldung aus KDE hinzu
+Comment[el]=Προσθέτει κουμπιά για το κλείδωμα της οθόνης και την αποσύνδεση συνεδρίας
+Comment[eo]=Aldonu butonojn por ŝlosi ekranon kaj seanco-eliron
+Comment[es]=Añade botones para bloquear la sesión y para salirse de esta
+Comment[et]=Lisab nupud ekraani lukustamiseks ning seansi lõpetamiseks
+Comment[eu]=Pantaila blokeatu eta saiotik irteteko botoiak gehitzen ditu
+Comment[fa]=دکمه‌ها را برای قفل پرده و خروج نشست اضافه می‌کند
+Comment[fi]=Lisää painikkeet ruudun lukitsemiseen ja uloskirjautumiseen
+Comment[fr]=Ajoute des boutons permettant de verrouiller l'écran et de déconnecter la session en cours
+Comment[fy]=Heakket knoppen ta foar it beskoattelje fan it skerm en it sluten fan de sesje
+Comment[gl]=Engade botóns para bloquear a pantalla e sair da sesión
+Comment[he]=מוסיף כפתורים לנעילת המסך ויציאה מהמערכת
+Comment[hr]=Dodavanje gumba za zaključavanje zaslona i odjavljivanja sesije
+Comment[hu]=Nyomógombok a képernyő zárolásához és kijelentkezéshez
+Comment[is]=Bætir við hnöppum til að læsa skjánum og stimpla sig út
+Comment[it]=Aggiunge i pulsanti per bloccare lo schermo o uscire dalla sessione
+Comment[ja]=スクリーンロックとセッションログアウト用ボタンを追加
+Comment[kk]=Экранды бұғаттау және сеанстан шығу батырмаларды қосу
+Comment[km]=បន្ថែម​ប៊ូតុង​សម្រាប់​ចាក់សោ​អេក្រង់ និង​ចេញ​ពី​សម័យ
+Comment[ko]=세션을 잠그거나 끝내기
+Comment[lt]=Prideda mygtukus ekrano užrakinimui ir sesijos užbaigimui
+Comment[mk]=Додава копчиња за заклучување на екранот и одјавување од сесијата
+Comment[nb]=Legger til knapper for å låse skjermen og logge ut av økta.
+Comment[nds]=Föögt Knööp för dat Afsluten vun den Schirm oder dat Afmellen ut KDE to
+Comment[ne]=पर्दा ताल्चा लगाउन र सत्र लग आउट गर्नका लागि बटनहरू थप्छ
+Comment[nl]=Voegt knoppen toe voor het vergrendelen van het scherm en het afsluiten van de sessie
+Comment[nn]=Legg til knappar for å låsa skjermen og logga ut av økta.
+Comment[pa]=ਪਰਦੇ ਨੂੰ ਤਾਲਾਬੰਦ ਕਰਨ ਅਤੇ ਅਜਲਾਸ ਬੰਦ ਕਰਨ ਲਈ ਬਟਨ ਜੋੜਦਾ ਹੈ
+Comment[pl]=Dodaje przyciski zablokowania ekranu i wylogowania
+Comment[pt]=Adiciona botões para bloquear o ecrã e encerrar a sessão
+Comment[pt_BR]=Adiciona os botões para bloquear a tela e finalizar a sessão
+Comment[ro]=Adaugă butoane pentru blocarea ecranului și sesiunea de ieșire
+Comment[ru]=Добавление кнопок выхода из KDE и запирания экрана
+Comment[se]=Lasit boaluid mat sáhttet lohkadit šearpma ja heaittihit bargovuoru
+Comment[sk]=Pridá tlačidlá na zamknutie obrazovky a ukončenie relácie
+Comment[sl]=Doda gumba za zaklep zaslona in odjavo iz seje
+Comment[sr]=Додаје дугмад за закључавање екрана и одјављивање из сесије
+Comment[sr@Latn]=Dodaje dugmad za zaključavanje ekrana i odjavljivanje iz sesije
+Comment[sv]=Lägger till knappar för att låsa skärmen och logga ut från sessionen
+Comment[th]=เพิ่มปุ่มสำหรับล็อคหน้าจอและล็อกเอาท์ออกจากวาระที่กำลังใช้งานอยู่
+Comment[uk]=Додає кнопки для замикання екрана та виходу з сеансу
+Comment[uz]=Ekranni qulflash va seansdan chiqish uchun tugmalar
+Comment[uz@cyrillic]=Экранни қулфлаш ва сеансдан чиқиш учун тугмалар
+Comment[vi]=Thêm nút khoá màn hình và đăng xuất khỏi phiên làm việc
+Comment[wa]=Radjout des botons po serer l' waitroûle a clé et dislodjî del session
+Comment[zh_CN]=添加锁定屏幕和注销会话的按钮
+Comment[zh_TW]=加入用來鎖定螢幕與登出作業階段的按鈕
+Icon=exit
+X-KDE-Library=lockout_panelapplet
diff --git a/kicker/applets/lockout/lockout.h b/kicker/applets/lockout/lockout.h
new file mode 100644
index 000000000..606870a99
--- /dev/null
+++ b/kicker/applets/lockout/lockout.h
@@ -0,0 +1,52 @@
+#ifndef LOCKOUT_H
+#define LOCKOUT_H
+
+#include <qevent.h>
+#include <qstring.h>
+#include <kpanelapplet.h>
+
+#include "simplebutton.h"
+
+class QBoxLayout;
+class QToolButton;
+
+class Lockout : public KPanelApplet
+{
+ Q_OBJECT
+
+public:
+ Lockout( const QString& configFile,
+ QWidget *parent = 0, const char *name = 0 );
+ ~Lockout();
+
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+
+protected:
+ virtual void mousePressEvent( QMouseEvent * );
+ virtual void mouseMoveEvent( QMouseEvent * );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+ virtual void mouseDoubleClickEvent( QMouseEvent * );
+
+ virtual bool eventFilter( QObject *, QEvent * );
+
+private slots:
+ void lock();
+ void logout();
+
+ void slotLockPrefs();
+ void slotLogoutPrefs();
+ void slotTransparent();
+ void slotIconChanged();
+
+private:
+ void propagateMouseEvent( QMouseEvent * );
+ void checkLayout( int height ) const;
+
+ SimpleButton *lockButton, *logoutButton;
+ QBoxLayout *layout;
+
+ bool bTransparent;
+};
+
+#endif // LOCKOUT_H
diff --git a/kicker/applets/media/Makefile.am b/kicker/applets/media/Makefile.am
new file mode 100644
index 000000000..0b971aef2
--- /dev/null
+++ b/kicker/applets/media/Makefile.am
@@ -0,0 +1,20 @@
+INCLUDES = -I$(top_srcdir)/libkonq -I$(top_srcdir)/kicker/libkicker $(all_includes)
+
+kde_module_LTLIBRARIES = media_panelapplet.la
+media_panelapplet_la_SOURCES = preferencesdialog.cpp mediumbutton.cpp mediaapplet.cpp
+
+METASOURCES = AUTO
+
+noinst_HEADERS = mediaapplet.h mediumbutton.h preferencesdialog.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = mediaapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+media_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+media_panelapplet_la_LIBADD = ../../../libkonq/libkonq.la ../../libkicker/libkickermain.la $(LIB_KDEUI) $(LIB_KIO) $(LIB_KUTILS)
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/mediaapplet.pot
+
diff --git a/kicker/applets/media/mediaapplet.cpp b/kicker/applets/media/mediaapplet.cpp
new file mode 100644
index 000000000..4ccd0eeef
--- /dev/null
+++ b/kicker/applets/media/mediaapplet.cpp
@@ -0,0 +1,444 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kaboutapplication.h>
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+
+#include "mediaapplet.h"
+
+#include "preferencesdialog.h"
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init( QWidget *parent, const QString configFile)
+ {
+ KGlobal::locale()->insertCatalogue("mediaapplet");
+ return new MediaApplet(configFile, KPanelApplet::Normal,
+ KPanelApplet::About | KPanelApplet::Preferences,
+ parent, "mediaapplet");
+ }
+}
+
+MediaApplet::MediaApplet(const QString& configFile, Type type, int actions, QWidget *parent, const char *name)
+ : KPanelApplet(configFile, type, actions, parent, name),
+ mButtonSizeSum(0)
+{
+ if (!parent)
+ setBackgroundMode(X11ParentRelative);
+
+ setBackgroundOrigin(AncestorOrigin);
+
+ setAcceptDrops(true);
+
+ loadConfig();
+
+ mpDirLister = new KDirLister();
+
+ connect( mpDirLister, SIGNAL( clear() ),
+ this, SLOT( slotClear() ) );
+ connect( mpDirLister, SIGNAL( started(const KURL&) ),
+ this, SLOT( slotStarted(const KURL&) ) );
+ connect( mpDirLister, SIGNAL( completed() ),
+ this, SLOT( slotCompleted() ) );
+ connect( mpDirLister, SIGNAL( newItems( const KFileItemList & ) ),
+ this, SLOT( slotNewItems( const KFileItemList & ) ) );
+ connect( mpDirLister, SIGNAL( deleteItem( KFileItem * ) ),
+ this, SLOT( slotDeleteItem( KFileItem * ) ) );
+ connect( mpDirLister, SIGNAL( refreshItems( const KFileItemList & ) ),
+ this, SLOT( slotRefreshItems( const KFileItemList & ) ) );
+
+ reloadList();
+}
+
+MediaApplet::~MediaApplet()
+{
+ delete mpDirLister;
+
+ while (!mButtonList.isEmpty())
+ {
+ MediumButton *b = mButtonList.first();
+ mButtonList.remove(b);
+ delete b;
+ }
+
+ KGlobal::locale()->removeCatalogue("mediaapplet");
+}
+
+void MediaApplet::about()
+{
+ KAboutData data("mediaapplet",
+ I18N_NOOP("Media Applet"),
+ "1.0",
+ I18N_NOOP("\"media:/\" ioslave frontend applet"),
+ KAboutData::License_GPL_V2,
+ "(c) 2004, Kevin Ottens");
+
+ data.addAuthor("Kevin \'ervin\' Ottens",
+ I18N_NOOP("Maintainer"),
+ "ervin ipsquad net",
+ "http://ervin.ipsquad.net");
+
+ data.addCredit("Joseph Wenninger",
+ I18N_NOOP("Good mentor, patient and helpful. Thanks for all!"),
+
+ KAboutApplication dialog(&data);
+ dialog.exec();
+}
+
+void MediaApplet::preferences()
+{
+ PreferencesDialog dialog(mMedia);
+
+ dialog.setExcludedMediumTypes(mExcludedTypesList);
+ dialog.setExcludedMedia(mExcludedList);
+
+ if(dialog.exec())
+ {
+ mExcludedTypesList = dialog.excludedMediumTypes();
+ mExcludedList = dialog.excludedMedia();
+ saveConfig();
+ reloadList();
+ }
+}
+
+int MediaApplet::widthForHeight( int /*height*/ ) const
+{
+ return mButtonSizeSum;
+}
+
+int MediaApplet::heightForWidth( int /*width*/ ) const
+{
+ return mButtonSizeSum;
+}
+
+void MediaApplet::resizeEvent( QResizeEvent *)
+{
+ arrangeButtons();
+}
+
+void MediaApplet::arrangeButtons()
+{
+ int button_size = 1;
+ int x_offset = 0;
+ int y_offset = 0;
+
+ // Determine upper bound for the button size
+ MediumButtonList::iterator it;
+ MediumButtonList::iterator end = mButtonList.end();
+ for ( it = mButtonList.begin(); it != end; ++it )
+ {
+ MediumButton *button = *it;
+
+ button_size = std::max(button_size,
+ orientation() == Vertical ?
+ button->heightForWidth(width()) :
+ button->widthForHeight(height()) );
+ // button->widthForHeight(height()) :
+ // button->heightForWidth(width()) );
+ }
+
+ int kicker_size;
+ if (orientation() == Vertical)
+ {
+ kicker_size = width();
+ }
+ else
+ {
+ kicker_size = height();
+ }
+
+ unsigned int max_packed_buttons = kicker_size / button_size;
+ // Center icons if we only have one column/row
+ if (mButtonList.count() < max_packed_buttons)
+ {
+ max_packed_buttons = QMAX(uint(1), mButtonList.count());
+ }
+ max_packed_buttons = QMAX(uint(1), max_packed_buttons);
+
+ int padded_button_size = kicker_size / max_packed_buttons;
+ mButtonSizeSum = 0;
+ unsigned int pack_count = 0;
+
+ // Arrange the buttons. If kicker is more than twice as high/wide
+ // as the maximum preferred size of an icon, we put several icons
+ // in one column/row
+ for ( it = mButtonList.begin(); it != end; ++it )
+ {
+ MediumButton *button = *it;
+
+ button->move(x_offset, y_offset);
+ button->setPanelPosition(position());
+
+ if(pack_count == 0)
+ {
+ mButtonSizeSum += button_size;
+ }
+
+ ++pack_count;
+
+ if(orientation() == Vertical)
+ {
+ if (pack_count < max_packed_buttons)
+ {
+ x_offset += padded_button_size;
+ }
+ else
+ {
+ x_offset = 0;
+ y_offset += button_size;
+ pack_count = 0;
+ }
+
+ button->resize(padded_button_size, button_size);
+ }
+ else
+ {
+ if (pack_count < max_packed_buttons)
+ {
+ y_offset += padded_button_size;
+ }
+ else
+ {
+ y_offset = 0;
+ x_offset += button_size;
+ pack_count = 0;
+ }
+
+ button->resize(button_size, padded_button_size);
+ }
+
+ button->unsetPalette();
+ button->setBackgroundOrigin(AncestorOrigin);
+ }
+
+ updateGeometry();
+ emit updateLayout();
+}
+
+void MediaApplet::slotClear()
+{
+ kdDebug()<<"MediaApplet::slotClear"<<endl;
+
+ while (!mButtonList.isEmpty())
+ {
+ MediumButton *b = mButtonList.first();
+ mButtonList.remove(b);
+ delete b;
+ }
+
+ arrangeButtons();
+}
+
+void MediaApplet::slotStarted(const KURL &/*url*/)
+{
+}
+
+void MediaApplet::slotCompleted()
+{
+ mMedia = mpDirLister->items(KDirLister::AllItems);
+}
+
+void MediaApplet::slotNewItems(const KFileItemList &entries)
+{
+ kdDebug()<<"MediaApplet::slotNewItems"<<endl;
+
+ for(KFileItemListIterator it(entries); it.current(); ++it)
+ {
+ kdDebug() << "item: " << it.current()->url() << endl;
+
+ bool found = false;
+ MediumButtonList::iterator it2;
+ MediumButtonList::iterator end = mButtonList.end();
+ for ( it2 = mButtonList.begin(); it2 != end; ++it2 )
+ {
+ MediumButton *button = *it2;
+
+ if(button->fileItem().url()==it.current()->url())
+ {
+ found = true;
+ button->setFileItem(*it.current());
+ break;
+ }
+ }
+
+ if(!found && !mExcludedList.contains(it.current()->url().url()) )
+ {
+ MediumButton *button = new MediumButton(this, *it.current());
+ button->show();
+ mButtonList.append(button);
+ }
+ }
+
+ arrangeButtons();
+}
+
+void MediaApplet::slotDeleteItem(KFileItem *fileItem)
+{
+ kdDebug()<<"MediumApplet::slotDeleteItem:"<< fileItem->url() << endl;
+
+ MediumButtonList::iterator it;
+ MediumButtonList::iterator end = mButtonList.end();
+ for ( it = mButtonList.begin(); it != end; ++it )
+ {
+ MediumButton *button = *it;
+
+ if(button->fileItem().url()==fileItem->url())
+ {
+ mButtonList.remove(button);
+ delete button;
+ break;
+ }
+ }
+ slotCompleted();
+ arrangeButtons();
+}
+
+void MediaApplet::slotRefreshItems(const KFileItemList &entries)
+{
+ for(KFileItemListIterator it(entries); it.current(); ++it)
+ {
+ kdDebug()<<"MediaApplet::slotRefreshItems:"<<(*it.current()).url().url()<<endl;
+
+ QString mimetype = (*it.current()).mimetype();
+ bool found = false;
+
+ kdDebug()<<"mimetype="<<mimetype<<endl;
+
+ MediumButtonList::iterator it2;
+ MediumButtonList::iterator end = mButtonList.end();
+ for ( it2 = mButtonList.begin(); it2 != end; ++it2 )
+ {
+ MediumButton *button = *it2;
+
+ if(button->fileItem().url()==(*it.current()).url())
+ {
+ if(mExcludedTypesList.contains(mimetype))
+ {
+ mButtonList.remove(button);
+ delete button;
+ }
+ else
+ {
+ button->setFileItem(*it.current());
+ }
+ found = true;
+ break;
+ }
+ }
+
+ if(!found && !mExcludedTypesList.contains(mimetype) && !mExcludedList.contains(it.current()->url().url()) )
+ {
+ MediumButton *button = new MediumButton(this, *it.current());
+ button->show();
+ mButtonList.append(button);
+ }
+ }
+
+ arrangeButtons();
+}
+
+void MediaApplet::positionChange(Position)
+{
+ arrangeButtons();
+}
+
+void MediaApplet::loadConfig()
+{
+ KConfig *c = config();
+ c->setGroup("General");
+
+ if(c->hasKey("ExcludedTypes"))
+ {
+ mExcludedTypesList = c->readListEntry("ExcludedTypes",';');
+ }
+ else
+ {
+ mExcludedTypesList.clear();
+ mExcludedTypesList << "media/hdd_mounted";
+ mExcludedTypesList << "media/hdd_unmounted";
+ mExcludedTypesList << "media/nfs_mounted";
+ mExcludedTypesList << "media/nfs_unmounted";
+ mExcludedTypesList << "media/smb_mounted";
+ mExcludedTypesList << "media/smb_unmounted";
+ }
+
+ if(c->hasKey("ExcludedMedia"))
+ {
+ mExcludedList = c->readListEntry("ExcludedMedia",';');
+ }
+ else
+ {
+ mExcludedList.clear();
+ }
+}
+
+void MediaApplet::saveConfig()
+{
+ KConfig *c = config();
+ c->setGroup("General");
+
+ c->writeEntry("ExcludedTypes", mExcludedTypesList, ';');
+ c->writeEntry("ExcludedMedia", mExcludedList, ';');
+
+ c->sync();
+}
+
+void MediaApplet::reloadList()
+{
+ mpDirLister->stop();
+
+ while (!mButtonList.isEmpty())
+ {
+ MediumButton *b = mButtonList.first();
+ mButtonList.remove(b);
+ delete b;
+ }
+
+ mpDirLister->clearMimeFilter();
+ mpDirLister->setMimeExcludeFilter(mExcludedTypesList);
+ mpDirLister->openURL(KURL("media:/"));
+}
+
+void MediaApplet::mousePressEvent(QMouseEvent *e)
+{
+ if(e->button()==RightButton)
+ {
+ KPopupMenu menu(this);
+
+ menu.insertTitle(i18n("Media"));
+ menu.insertItem(SmallIcon("configure"), i18n("&Configure..."), 1);
+
+ int choice = menu.exec(this->mapToGlobal(e->pos()));
+
+ if(choice==1)
+ {
+ preferences();
+ }
+ }
+}
+
+#include "mediaapplet.moc"
diff --git a/kicker/applets/media/mediaapplet.desktop b/kicker/applets/media/mediaapplet.desktop
new file mode 100644
index 000000000..958ebb753
--- /dev/null
+++ b/kicker/applets/media/mediaapplet.desktop
@@ -0,0 +1,130 @@
+[Desktop Entry]
+Type=Plugin
+Comment=Directly access your storage media
+Comment[af]=Kry direkte toegang tot jou stoor media
+Comment[ar]=الوصول مباشرة إلى وسائطك للتخزين
+Comment[be]=Наўпрост дае доступ да носьбітаў інфармацыі
+Comment[bg]=Директен достъп до съхраняващите устройства
+Comment[bn]=আপনার স্টোরেজ মিডিয়া সরাসরি খুলুন
+Comment[bs]=Direktno pristupite vašim uređajima
+Comment[ca]=Accedeix directament als suports d'emmagatzematge
+Comment[cs]=Přímý přístup k úložným zařízením
+Comment[csb]=Prosti przistãp do Twòjëch zôpisownëch mediów
+Comment[da]=Direkte adgang til opbevaringsmedie
+Comment[de]=Direkter Zugriff auf Ihre Speichermedien
+Comment[el]=Απευθείας πρόσβαση στις συσκευές αποθήκευσής σας
+Comment[eo]=Rekte atingi vian konservejon
+Comment[es]= Acceso directo a sus dispositivos de almacenamiento
+Comment[et]=Ligipääs andmekandjatele
+Comment[eu]=Atzitu zure biltegiratze-euskarriak
+Comment[fa]=دستیابی مستقیم رسانۀ ذخیره‌گاه شما
+Comment[fi]=Tallennuslaitteet näyttävä paneelisovelma
+Comment[fr]=Accès direct aux périphériques de stockage
+Comment[fy]=Direkte tagong ta jo opslachmedia
+Comment[gl]=Unha applet que mostra os seus dispositivos
+Comment[he]=גישה ישירה אל ההתקנים שלך
+Comment[hr]=Izravni pristup medijima za pohranjivanje
+Comment[hu]=A tárolóeszközök közvetlen elérése
+Comment[is]=Beinn aðgangur að geymslumiðlum
+Comment[it]=Accesso diretto ai dispositivi di archiviazione
+Comment[ja]=記憶メディアに直接アクセス
+Comment[ka]=თქვენი შენახვის მედიის პირდაპირი წვდომა
+Comment[kk]=Жинақтаушыларыңызды тез ашу
+Comment[km]=ចូលដំណើរការ​ឧបករណ៍​ផ្ទុក​របស់​អ្នក​ដោយ​ផ្ទាល់
+Comment[lt]=Tiesiogiai pasiekite savo saugojimo įrenginius
+Comment[mk]=Пристапете директно на вашите медиуми за податоци
+Comment[nb]=Direkte tilgang til lagringsenheter
+Comment[nds]=Direktemang op Dien Spiekermedien togriepen
+Comment[ne]=भण्डारण मिडियामा तपाईँको प्रत्यक्ष पहुँच
+Comment[nl]=Directe toegang tot uw opslagmedia
+Comment[nn]=Direkte tilgang til lagringseiningar
+Comment[pa]=ਜੋ ਕਿ ਤੁਹਾਡਾ ਸਟੋਰੇਜ਼ ਮਾਧਿਅਮ ਵੇਖਾਉਦਾ ਹੈ।
+Comment[pl]=Bezpośredni dostęp do Twoich urządzeń przechowywania danych
+Comment[pt]=Aceder directamente aos seus suportes de armazenamento
+Comment[pt_BR]=Acesso direto às suas mídias de armazenamento
+Comment[ro]=Accesează direct dispozitivele de stocare
+Comment[ru]=Аплет панели, показывающий устройства хранения
+Comment[se]=Njuolggoluotta vurkenmediaide
+Comment[sk]=Priamy prístup na zálohovacie médiá
+Comment[sl]=Neposreden dostop do nosilcev za shranjevanje
+Comment[sr]=Директно приступите складишним медијима
+Comment[sr@Latn]=Direktno pristupite skladišnim medijima
+Comment[sv]=Direkt åtkomst av lagringsmedia
+Comment[th]=เข้าใช้งานสื่อที่เก็บข้อมูลของคุณโดยตรง
+Comment[tr]=Depolama aygıtlarına doğrudan erişim
+Comment[uk]=Безпосередній доступ до пристроїв зберігання інформації
+Comment[uz]=Saqlash usunalariga qisqa yoʻl
+Comment[uz@cyrillic]=Сақлаш усуналарига қисқа йўл
+Comment[vi]=Truy cập ngay vào các ổ chứa dữ liệu của bạn
+Comment[wa]=Accès direk a vos sopoirts di wårdaedje
+Comment[zh_CN]=直接访问您的存储介质
+Comment[zh_TW]=直接存取您的儲存媒體
+Name=Storage Media
+Name[af]=Stoor Media
+Name[ar]=وسائط التخزين
+Name[be]=Носьбіты
+Name[bg]=Съхраняващи устройства
+Name[bn]=স্টোরেজ মিডিয়া
+Name[bs]=Uređaji za smještaj podataka
+Name[ca]=Suports d'emmagatzematge
+Name[cs]=Úložná zařízení
+Name[csb]=Zôpisowné media
+Name[da]=Opbevaringsmedie
+Name[de]=Speichermedien
+Name[el]=Συσκευές αποθήκευσης
+Name[eo]=Enmemoriga Medio
+Name[es]=Dispositivos de almacenamiento
+Name[et]=Andmekandjad
+Name[eu]=Biltegiratze-euskarria
+Name[fa]=رسانۀ ذخیره‌گاه
+Name[fi]=Tallennusmedia
+Name[fr]=Support de stockage
+Name[fy]=Opslachapparaten
+Name[ga]=Meán Stórais
+Name[gl]=Medios de armacenaxe
+Name[he]=התקנים
+Name[hi]=भंडार मीडिया
+Name[hr]=Mediji za pohranjivanje
+Name[hu]=Tárolóeszközök
+Name[is]=Geymslumiðlar
+Name[it]=Dispositivi di archiviazione
+Name[ja]=記憶メディア
+Name[ka]=მონაცემთა შენახვის მოწყობილობები
+Name[kk]=Жинақтаушы құрылғылар
+Name[km]=ឧបករណ៍​ផ្ទុក
+Name[lt]=Saugojimo įrenginiai
+Name[lv]=Datu nesējs
+Name[mk]=Медиуми за податоци
+Name[ms]=Media Storan
+Name[nb]=Lagringsenheter
+Name[nds]=Spiekermedien
+Name[ne]=भण्डारण मिडिया
+Name[nl]=Opslagapparaten
+Name[nn]=Lagringsmedium
+Name[pa]=ਸਟੋਰੇਜ਼ ਮੀਡਿਆ
+Name[pl]=Urządzenia przechowywania danych
+Name[pt]=Dispositivos de Armazenamento
+Name[pt_BR]=Mídia de Armazenamento
+Name[ro]=Mediu de stocare
+Name[ru]=Устройства хранения данных
+Name[rw]=Uburyo bwo Kubika
+Name[se]=Vurkenmedia
+Name[sk]=Zálohovacie médiá
+Name[sl]=Nosilci za shranjevanje
+Name[sr]=Складишни медијуми
+Name[sr@Latn]=Skladišni medijumi
+Name[sv]=Lagringsmedia
+Name[ta]=சேகரிப்பு ஊடகம்
+Name[tg]=Захирагоҳи маълумот
+Name[th]=สื่อเก็บข้อมูล
+Name[tr]=Depolama Ortamı
+Name[tt]=Saqlawlı Media
+Name[uk]=Пристрої зберігання інформації
+Name[uz]=Saqlash uskunalari
+Name[uz@cyrillic]=Сақлаш ускуналари
+Name[vi]=Ổ chứa Dữ liệu
+Name[wa]=Sopoirts di wårdaedje
+Name[zh_CN]=存储介质
+Name[zh_TW]=儲存媒體
+Icon=3floppy_unmount
+X-KDE-Library=media_panelapplet
diff --git a/kicker/applets/media/mediaapplet.h b/kicker/applets/media/mediaapplet.h
new file mode 100644
index 000000000..5e2320be0
--- /dev/null
+++ b/kicker/applets/media/mediaapplet.h
@@ -0,0 +1,79 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef MEDIAAPPLET_H
+#define MEDIAAPPLET_H
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#include <kpanelapplet.h>
+#include <qstring.h>
+#include <kconfig.h>
+#include <kurl.h>
+#include <kfileitem.h>
+#include <kdirlister.h>
+
+#include <qptrlist.h>
+#include "mediumbutton.h"
+typedef QValueList<MediumButton*> MediumButtonList;
+
+
+class MediaApplet : public KPanelApplet
+{
+Q_OBJECT
+
+public:
+ MediaApplet(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ ~MediaApplet();
+
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+ void about();
+ void preferences();
+
+protected:
+ void arrangeButtons();
+ void resizeEvent(QResizeEvent *e);
+ void positionChange(Position p);
+ void reloadList();
+ void loadConfig();
+ void saveConfig();
+ void mousePressEvent(QMouseEvent *e);
+
+protected slots:
+ void slotClear();
+ void slotStarted(const KURL &url);
+ void slotCompleted();
+ void slotNewItems(const KFileItemList &entries);
+ void slotDeleteItem(KFileItem *fileItem);
+ void slotRefreshItems(const KFileItemList &entries);
+
+private:
+ KDirLister *mpDirLister;
+ MediumButtonList mButtonList;
+ QStringList mExcludedTypesList;
+ QStringList mExcludedList;
+ KFileItemList mMedia;
+ int mButtonSizeSum;
+};
+
+#endif
diff --git a/kicker/applets/media/mediumbutton.cpp b/kicker/applets/media/mediumbutton.cpp
new file mode 100644
index 000000000..2c96601ea
--- /dev/null
+++ b/kicker/applets/media/mediumbutton.cpp
@@ -0,0 +1,202 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "mediumbutton.h"
+
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qpopupmenu.h>
+#include <qstyle.h>
+#include <qtooltip.h>
+
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kdesktopfile.h>
+#include <krun.h>
+#include <kglobalsettings.h>
+#include <kcursor.h>
+#include <kapplication.h>
+#include <kipc.h>
+#include <kiconloader.h>
+#include <kurldrag.h>
+#include <kpopupmenu.h>
+
+#include <konq_operations.h>
+#include <konq_popupmenu.h>
+#include <konq_drag.h>
+
+MediumButton::MediumButton(QWidget *parent, const KFileItem &fileItem)
+ : PanelPopupButton(parent), mActions(this, this), mFileItem(fileItem)
+{
+ KAction *a = KStdAction::paste(this, SLOT(slotPaste()),
+ &mActions, "pasteto");
+ a->setShortcut(0);
+ a = KStdAction::copy(this, SLOT(slotCopy()), &mActions, "copy");
+ a->setShortcut(0);
+
+ setBackgroundOrigin(AncestorOrigin);
+
+ resize(20, 20);
+
+ setAcceptDrops(mFileItem.isWritable());
+
+ setTitle(mFileItem.text());
+
+ refreshType();
+
+ connect(&mOpenTimer, SIGNAL(timeout()), SLOT(slotDragOpen()));
+
+ // Activate this code only if we find a way to have both an
+ // action and a popup menu for the same kicker button
+ //connect(this, SIGNAL(clicked()), this, SLOT(slotClicked()));
+
+ setPopup(new QPopupMenu());
+}
+
+MediumButton::~MediumButton()
+{
+ QPopupMenu *menu = popup();
+ setPopup(0);
+ delete menu;
+}
+
+const KFileItem &MediumButton::fileItem() const
+{
+ return mFileItem;
+}
+
+void MediumButton::setFileItem(const KFileItem &fileItem)
+{
+ mFileItem.assign(fileItem);
+ setAcceptDrops(mFileItem.isWritable());
+ setTitle(mFileItem.text());
+ refreshType();
+}
+
+void MediumButton::initPopup()
+{
+ QPopupMenu *old_popup = popup();
+
+ KFileItemList items;
+ items.append(&mFileItem);
+
+ KonqPopupMenu::KonqPopupFlags kpf =
+ KonqPopupMenu::ShowProperties
+ | KonqPopupMenu::ShowNewWindow;
+
+ KParts::BrowserExtension::PopupFlags bef =
+ KParts::BrowserExtension::DefaultPopupItems;
+
+ KonqPopupMenu *new_popup = new KonqPopupMenu(0L, items,
+ KURL("media:/"), mActions, 0L,
+ this, kpf, bef);
+ KPopupTitle *title = new KPopupTitle(new_popup);
+ title->setTitle(mFileItem.text());
+
+ new_popup->insertItem(title, -1, 0);
+
+ setPopup(new_popup);
+
+ if (old_popup!=0L) delete old_popup;
+}
+
+void MediumButton::refreshType()
+{
+ KMimeType::Ptr mime = mFileItem.determineMimeType();
+ QToolTip::add(this, mime->comment());
+ setIcon(mime->icon(QString::null, false));
+}
+
+// Activate this code only if we find a way to have both an
+// action and a popup menu for the same kicker button
+/*
+void MediumButton::slotClicked()
+{
+ mFileItem.run();
+}
+*/
+
+void MediumButton::slotPaste()
+{
+ KonqOperations::doPaste(this, mFileItem.url());
+}
+
+void MediumButton::slotCopy()
+{
+ KonqDrag * obj = KonqDrag::newDrag(mFileItem.url(), false);
+
+ QApplication::clipboard()->setData( obj );
+}
+
+void MediumButton::dragEnterEvent(QDragEnterEvent* e)
+{
+ if (mFileItem.isWritable())
+ {
+ mOpenTimer.start(1000, true);
+ e->accept(true);
+ }
+}
+
+void MediumButton::dragLeaveEvent(QDragLeaveEvent* e)
+{
+ mOpenTimer.stop();
+
+ PanelPopupButton::dragLeaveEvent( e );
+}
+
+void MediumButton::dropEvent(QDropEvent *e)
+{
+ mOpenTimer.stop();
+
+ KonqOperations::doDrop(&mFileItem, mFileItem.url(), e, this);
+}
+
+void MediumButton::slotDragOpen()
+{
+ mFileItem.run();
+}
+
+QString MediumButton::tileName()
+{
+ return mFileItem.text();
+}
+
+void MediumButton::setPanelPosition(KPanelApplet::Position position)
+{
+ switch(position)
+ {
+ case KPanelApplet::pBottom:
+ setPopupDirection(KPanelApplet::Up);
+ break;
+ case KPanelApplet::pTop:
+ setPopupDirection(KPanelApplet::Down);
+ break;
+ case KPanelApplet::pRight:
+ setPopupDirection(KPanelApplet::Left);
+ break;
+ case KPanelApplet::pLeft:
+ setPopupDirection(KPanelApplet::Right);
+ break;
+ }
+}
+
+#include "mediumbutton.moc"
diff --git a/kicker/applets/media/mediumbutton.h b/kicker/applets/media/mediumbutton.h
new file mode 100644
index 000000000..8d7970d89
--- /dev/null
+++ b/kicker/applets/media/mediumbutton.h
@@ -0,0 +1,66 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef MEDIUMBUTTON_H
+#define MEDIUMBUTTON_H
+
+#include <panelbutton.h>
+#include <qpoint.h>
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qtimer.h>
+#include <kfileitem.h>
+#include <kpanelapplet.h>
+#include <kactioncollection.h>
+
+class MediumButton : public PanelPopupButton
+{
+Q_OBJECT
+
+public:
+ MediumButton(QWidget *parent, const KFileItem &fileItem);
+ ~MediumButton();
+ const KFileItem &fileItem() const;
+ void setFileItem(const KFileItem &fileItem);
+ void setPanelPosition(KPanelApplet::Position position);
+
+protected:
+ QString tileName();
+ void refreshType();
+ void initPopup();
+ void dragEnterEvent( QDragEnterEvent* );
+ void dragLeaveEvent( QDragLeaveEvent* );
+ void dropEvent(QDropEvent *e);
+
+protected slots:
+ // Activate this code only if we find a way to have both an
+ // action and a popup menu for the same kicker button
+ //void slotClicked();
+ void slotPaste();
+ void slotCopy();
+ void slotDragOpen();
+
+private:
+ KActionCollection mActions;
+ KFileItem mFileItem;
+ QTimer mOpenTimer;
+};
+
+#endif
diff --git a/kicker/applets/media/preferencesdialog.cpp b/kicker/applets/media/preferencesdialog.cpp
new file mode 100644
index 000000000..179878e89
--- /dev/null
+++ b/kicker/applets/media/preferencesdialog.cpp
@@ -0,0 +1,167 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "preferencesdialog.h"
+
+#include <klocale.h>
+#include <kmimetype.h>
+#include <qvbox.h>
+#include <qwhatsthis.h>
+#include <klistview.h>
+#include <kfiledetailview.h>
+
+class MediumTypeItem : public QCheckListItem
+{
+public:
+ MediumTypeItem(QListView *parent, const QString name,
+ const QString mimetype)
+ : QCheckListItem(parent, name, CheckBox),
+ mMimeType(mimetype) { }
+
+ const QString &mimeType() const { return mMimeType; }
+
+private:
+ QString mMimeType;
+};
+
+class MediumItem : public QCheckListItem
+{
+public:
+ MediumItem(QListView *parent, const QString name,
+ const KFileItem medium)
+ : QCheckListItem(parent, name, CheckBox),
+ mMedium(medium) { }
+
+ const QString itemURL() const { return mMedium.url().url(); }
+
+private:
+ KFileItem mMedium;
+};
+
+
+
+PreferencesDialog::PreferencesDialog(KFileItemList media, QWidget *parent,
+ const char *name)
+ : KDialogBase(Tabbed, i18n("Media Applet Preferences"), Ok|Cancel|Default,
+ Ok, parent, name, true),
+ mMedia(media)
+{
+ QVBox *types_page = addVBoxPage( i18n("Medium Types") );
+ mpMediumTypesListView = new KListView(types_page);
+
+ //mpMediumTypesListView->setFullWidth(true);
+ mpMediumTypesListView->addColumn( i18n("Types to Display") );
+ QWhatsThis::add(mpMediumTypesListView, i18n("Deselect the medium types which you do not want to see in the applet"));
+
+
+
+ QVBox *media_page = addVBoxPage( i18n("Media") );
+ mpMediaListView = new KListView(media_page);
+
+ //mpMediaListView->setFullWidth(true);
+ mpMediaListView->addColumn( i18n("Media to Display") );
+ QWhatsThis::add(mpMediaListView, i18n("Deselect the media which you do not want to see in the applet"));
+
+ slotDefault();
+}
+
+PreferencesDialog::~PreferencesDialog()
+{
+}
+
+void PreferencesDialog::slotDefault()
+{
+ QStringList defaultExclude;
+
+ defaultExclude << "media/hdd_mounted";
+ defaultExclude << "media/hdd_unmounted";
+ defaultExclude << "media/nfs_mounted";
+ defaultExclude << "media/nfs_unmounted";
+ defaultExclude << "media/smb_mounted";
+ defaultExclude << "media/smb_unmounted";
+
+ setExcludedMediumTypes(defaultExclude);
+ setExcludedMedia(QStringList());
+}
+
+QStringList PreferencesDialog::excludedMediumTypes()
+{
+ QStringList excludedTypes;
+
+ for(MediumTypeItem *it=static_cast<MediumTypeItem *>(mpMediumTypesListView->firstChild());
+ it; it=static_cast<MediumTypeItem *>(it->nextSibling()))
+ {
+ if(!it->isOn()) excludedTypes << it->mimeType();
+ }
+
+ return excludedTypes;
+}
+
+void PreferencesDialog::setExcludedMediumTypes(QStringList excludedTypesList)
+{
+ mpMediumTypesListView->clear();
+ mpMediumTypesListView->setRootIsDecorated(false);
+ KMimeType::List mimetypes = KMimeType::allMimeTypes();
+
+ QValueListIterator<KMimeType::Ptr> it(mimetypes.begin());
+
+ for(; it != mimetypes.end(); ++it)
+ {
+ if ((*it)->name().startsWith("media/"))
+ {
+ bool ok=excludedTypesList.contains((*it)->name())==0;
+ MediumTypeItem *item = new MediumTypeItem(mpMediumTypesListView, (*it)->comment(), (*it)->name());
+ item->setOn(ok);
+ }
+ }
+}
+
+QStringList PreferencesDialog::excludedMedia()
+{
+ QStringList excluded;
+
+ for(MediumItem *it=static_cast<MediumItem *>(mpMediaListView->firstChild());
+ it; it=static_cast<MediumItem *>(it->nextSibling()))
+ {
+ if(!it->isOn()) excluded << it->itemURL();
+ }
+
+ return excluded;
+}
+
+void PreferencesDialog::setExcludedMedia(QStringList excludedList)
+{
+ mpMediaListView->clear();
+ mpMediaListView->setRootIsDecorated(false);
+
+ KFileItemListIterator it( mMedia );
+ KFileItem *file;
+ while ( (file = it.current()) != 0 )
+ {
+ ++it;
+
+ bool ok = excludedList.contains(file->url().url())==0;
+ MediumItem *item = new MediumItem(mpMediaListView,
+ file->text(), *file);
+ item->setOn(ok);
+ }
+}
+
+
+#include "preferencesdialog.moc"
diff --git a/kicker/applets/media/preferencesdialog.h b/kicker/applets/media/preferencesdialog.h
new file mode 100644
index 000000000..bb400564b
--- /dev/null
+++ b/kicker/applets/media/preferencesdialog.h
@@ -0,0 +1,53 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PREFERENCESDIALOG_H
+#define PREFERENCESDIALOG_H
+
+#include <qwidget.h>
+#include <kdialogbase.h>
+#include <kfileitem.h>
+
+/**
+ *@author ervin
+ */
+
+class PreferencesDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ PreferencesDialog(KFileItemList media, QWidget *parent=0, const char *name=0);
+ ~PreferencesDialog();
+
+ QStringList excludedMediumTypes();
+ void setExcludedMediumTypes(QStringList excludedTypesList);
+
+ QStringList excludedMedia();
+ void setExcludedMedia(QStringList excludedList);
+
+protected slots:
+ void slotDefault();
+
+private:
+ KListView *mpMediumTypesListView;
+ KListView *mpMediaListView;
+ KFileItemList mMedia;
+};
+
+#endif
diff --git a/kicker/applets/menu/Makefile.am b/kicker/applets/menu/Makefile.am
new file mode 100644
index 000000000..5bfaeee18
--- /dev/null
+++ b/kicker/applets/menu/Makefile.am
@@ -0,0 +1,20 @@
+INCLUDES = $(all_includes)
+
+kde_module_LTLIBRARIES = menu_panelapplet.la
+
+menu_panelapplet_la_SOURCES = menuapplet.cpp menuapplet.skel
+
+noinst_HEADERS = menuapplet.h
+
+menu_panelapplet_la_METASOURCES = AUTO
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = menuapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+menu_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+menu_panelapplet_la_LIBADD = $(LIB_KDEUI)
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kmenuapplet.pot
diff --git a/kicker/applets/menu/menuapplet.cpp b/kicker/applets/menu/menuapplet.cpp
new file mode 100644
index 000000000..ae10614c6
--- /dev/null
+++ b/kicker/applets/menu/menuapplet.cpp
@@ -0,0 +1,511 @@
+/*****************************************************************
+
+Copyright (c) 2002 Siegfried Nijssen <[email protected]>
+Copyright (c) 2003 Lubos Lunak <[email protected]>
+
+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.
+
+******************************************************************/
+
+#define _MENUAPPLET_CPP_
+
+#include "menuapplet.h"
+
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qvariant.h> // avoid X11 #define's
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kwin.h>
+#include <kwinmodule.h>
+
+#include <netwm.h>
+
+#include <X11/Xlib.h>
+
+/*
+
+ KMenuBar from KDE3.1 and older won't work very well with this applet.
+ This is because QMenuBar tries really hard to keep its preffered size,
+ se even if the X window for the menubar has the size enforced by this
+ applet, Qt thinks it has the size Qt wants. This results in parts
+ of the menubar not being repainted. Also, old KMenuBar always forced
+ with to be the width of the screen, so even if the menubar has only
+ few entries, this applet will still indicate the menubar doesn't
+ fit completely in it. There's no way to fix this, besides upgrading
+ to KDE3.2.
+
+*/
+
+
+extern Time qt_x_time;
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init( QWidget* parent_P, const QString& configFile_P )
+ {
+ KGlobal::locale()->insertCatalogue("kmenuapplet");
+ return new KickerMenuApplet::Applet( configFile_P, parent_P );
+ }
+}
+
+namespace KickerMenuApplet
+{
+
+static const int MOVE_DIFF = 100; // size increment for left/right menu moving
+static const int GROW_WIDTH = 10; // width of grow buttons
+
+const long SUPPORTED_WINDOW_TYPES = NET::NormalMask | NET::DesktopMask | NET::DockMask
+ | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask
+ | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask;
+
+Applet::Applet( const QString& configFile_P, QWidget* parent_P )
+ : KPanelApplet( configFile_P, Normal, 0, parent_P, "menuapplet" ),
+ DCOPObject( "menuapplet" ),
+ module( NULL ),
+ active_menu( NULL ),
+ selection( NULL ),
+ selection_watcher( NULL ),
+ desktop_menu( false ),
+ topEdgeOffset( 0 )
+ {
+ setBackgroundOrigin(AncestorOrigin);
+ dcopclient.registerAs( "menuapplet", false );
+ // toolbarAppearanceChanged(int) is sent when changing macstyle
+ connect( kapp, SIGNAL( toolbarAppearanceChanged( int )),
+ this, SLOT( readSettings()));
+ claimSelection();
+ readSettings();
+ updateTopEdgeOffset();
+ }
+
+Applet::~Applet()
+ {
+ lostSelection(); // release all menu's before really loosing the selection
+ delete selection;
+ delete selection_watcher;
+ delete module;
+ KGlobal::locale()->removeCatalogue("kmenuapplet");
+ }
+
+void Applet::windowAdded( WId w_P )
+ {
+ NETWinInfo info( qt_xdisplay(), w_P, qt_xrootwin(), NET::WMWindowType );
+ if( info.windowType( SUPPORTED_WINDOW_TYPES ) != NET::TopMenu )
+ return;
+// kdDebug() << "embedding:" << w_P << endl;
+ Window transient_for = KWin::transientFor( w_P );
+ if( transient_for == None )
+ return;
+ MenuEmbed* embed;
+ if( transient_for == qt_xrootwin())
+ {
+ embed = new MenuEmbed( transient_for, true, this );
+ }
+ else
+ {
+ KWin::WindowInfo info2 = KWin::windowInfo( transient_for, NET::WMWindowType );
+ embed = new MenuEmbed( transient_for,
+ info2.windowType( SUPPORTED_WINDOW_TYPES ) == NET::Desktop, this );
+ }
+ embed->hide();
+ embed->move( 0, -topEdgeOffset );
+ embed->resize( embed->width(), height() + topEdgeOffset );
+ embed->embed( w_P );
+ if( embed->embeddedWinId() == None )
+ {
+ delete embed;
+ return;
+ }
+ menus.append( embed );
+ // in case the app mapped its menu after its mainwindow, check which menu should be shown
+ activeWindowChanged( module->activeWindow());
+ }
+
+// - if the active window has its topmenu -> show the menu
+// - if desktop menu is enabled (i.e. explicitly in kdesktop) :
+// - show it
+// - otherwise show nothing
+void Applet::activeWindowChanged( WId w_P )
+ {
+// kdDebug() << "active:" << w_P << endl;
+ for( WId window = w_P;
+ window != None;
+ window = tryTransientFor( window ))
+ {
+ for( QValueList< MenuEmbed* >::ConstIterator it = menus.begin();
+ it != menus.end();
+ ++it )
+ {
+ if( window == (*it)->mainWindow())
+ {
+ activateMenu( *it );
+ return;
+ }
+ }
+ }
+// kdDebug() << "no active" << endl;
+ // No menu for active window found - if desktop menu
+ // (in kdesktoprc) is enabled, use kdesktop's menu instead of none.
+ bool try_desktop = desktop_menu;
+ if( !try_desktop && w_P != None )
+ { // also use the desktop menu if the active window is desktop
+ KWin::WindowInfo info = KWin::windowInfo( w_P, NET::WMWindowType );
+ if( info.windowType( SUPPORTED_WINDOW_TYPES ) == NET::Desktop )
+ try_desktop = true;
+ }
+ if( try_desktop )
+ {
+ for( QValueList< MenuEmbed* >::ConstIterator it = menus.begin();
+ it != menus.end();
+ ++it )
+ {
+ if( (*it)->isDesktopMenu())
+ {
+ activateMenu( *it );
+ return;
+ }
+ }
+ }
+ activateMenu( NULL );
+ }
+
+void Applet::activateMenu( MenuEmbed* embed_P )
+ {
+ if( embed_P != active_menu )
+ {
+// kdDebug() << "activate:" << embed_P << endl;
+ if( active_menu != NULL )
+ active_menu->hide();
+ active_menu = embed_P;
+ if( active_menu != NULL )
+ {
+ active_menu->show();
+ //if (embed->isDesktopMenu())
+ {
+ active_menu->setMinimumSize( width(), height() + topEdgeOffset );
+ }
+ }
+ emit updateLayout();
+ }
+
+ setBackground();
+ }
+
+void Applet::updateMenuGeometry( MenuEmbed* embed )
+ {
+ if( embed == active_menu )
+ emit updateLayout();
+ }
+
+// If there's no menu for the window, try finding menu for its mainwindow
+// (where the window's WM_TRANSIENT_FOR property points).
+// If the window is modal (_NET_WM_STATE_MODAL), stop.
+WId Applet::tryTransientFor( WId w_P )
+ {
+ KWin::WindowInfo info = KWin::windowInfo( w_P, NET::WMState );
+ if( info.state() & NET::Modal )
+ return None;
+ WId ret = KWin::transientFor( w_P );
+ if( ret == qt_xrootwin())
+ ret = None;
+ return ret;
+ }
+
+void Applet::menuLost( MenuEmbed* embed )
+ {
+ for( QValueList< MenuEmbed* >::Iterator it = menus.begin();
+ it != menus.end();
+ ++it )
+ {
+ if( *it == embed )
+ {
+ menus.remove( it );
+ embed->deleteLater();
+// kdDebug() << "deleting:" << (*it)->mainWindow() << endl;
+ if( embed == active_menu )
+ {
+ active_menu = NULL;
+ // trigger selecting new active menu
+ activeWindowChanged( module->activeWindow());
+ }
+ return;
+ }
+ }
+ }
+
+void Applet::positionChange( Position )
+ {
+ updateTopEdgeOffset();
+ }
+
+// Detect mouse movement at the top screen edge also if the menubar
+// has a popup open - in such case, Qt has a grab, and this avoids
+// Kicker's FittsLawFrame. Therefore move the menubar a bit higher,
+// so that it actually is positioned exactly at the screen edge
+// (i.e. at a negative y coordinate within this applet, due to
+// Kicker's frame).
+void Applet::updateTopEdgeOffset()
+ {
+ QPoint p = topLevelWidget()->mapToGlobal( QPoint( 0, 0 ));
+ if( p.y() <= 2 ) // 2 = work also when running in appletproxy
+ topEdgeOffset = mapToGlobal( QPoint( 0, 0 )).y() - p.y();
+ else
+ topEdgeOffset = 0;
+ if( active_menu != NULL )
+ active_menu->move( active_menu->x(), -topEdgeOffset );
+ }
+
+void Applet::paletteChange(const QPalette & /* oldPalette */)
+{
+ setBackground();
+}
+
+void Applet::moveEvent( QMoveEvent* )
+{
+ setBackground();
+}
+
+void Applet::setBackground()
+{
+ if (active_menu)
+ active_menu->setBackground();
+}
+
+void Applet::claimSelection()
+ {
+ assert( selection == NULL );
+ selection = new KSelectionOwner( makeSelectionAtom(), DefaultScreen( qt_xdisplay()));
+// force taking the selection, but don't kill previous owner
+ if( selection->claim( true, false ))
+ {
+ delete selection_watcher;
+ selection_watcher = NULL;
+ connect( selection, SIGNAL( lostOwnership()), SLOT( lostSelection()));
+ module = new KWinModule;
+ connect( module, SIGNAL( windowAdded( WId )), this, SLOT( windowAdded( WId )));
+ connect( module, SIGNAL( activeWindowChanged( WId )),
+ this, SLOT( activeWindowChanged( WId )));
+ QValueList< WId > windows = module->windows();
+ for( QValueList< WId >::ConstIterator it = windows.begin();
+ it != windows.end();
+ ++it )
+ windowAdded( *it );
+ activeWindowChanged( module->activeWindow());
+ }
+ else
+ lostSelection();
+ }
+
+void Applet::lostSelection()
+ {
+ if( selection == NULL )
+ return;
+// kdDebug() << "lost selection" << endl;
+ for( QValueList< MenuEmbed* >::ConstIterator it = menus.begin();
+ it != menus.end();
+ ++it )
+ delete (*it); // delete all MenuEmbed's = release all menus
+ menus.clear();
+ active_menu = NULL;
+ if( selection_watcher == NULL )
+ {
+ selection_watcher = new KSelectionWatcher( makeSelectionAtom(), DefaultScreen( qt_xdisplay()));
+ connect( selection_watcher, SIGNAL( lostOwner()), this, SLOT( claimSelection()));
+ }
+ delete module;
+ module = NULL;
+ selection->deleteLater();
+ selection = NULL;
+ // selection_watcher stays
+ }
+
+void Applet::readSettings()
+ {
+ KConfig cfg( "kdesktoprc", true );
+ cfg.setGroup( "Menubar" );
+ desktop_menu = cfg.readBoolEntry( "ShowMenubar", false );
+ cfg.setGroup( "KDE" );
+ if( cfg.readBoolEntry( "macStyle", false ) || desktop_menu )
+ QToolTip::remove( this );
+ else
+ QToolTip::add( this, i18n(
+ "You do not appear to have enabled the standalone menubar; "
+ "enable it in the Behavior control module for desktop." ));
+ if( !isDisabled() && active_menu == NULL )
+ activeWindowChanged( module->activeWindow()); //enforce desktop_menu
+ }
+
+void Applet::configure()
+ {
+ readSettings();
+ }
+
+int Applet::widthForHeight( int ) const
+ {
+ if (active_menu)
+ return active_menu->width();
+ return 0; // we're stretch applet
+ }
+
+int Applet::heightForWidth( int ) const
+ {
+ // *shrug* running this applet in vertical mode is a bad idea anyway
+ return 50;
+ }
+
+static Atom selection_atom = None;
+static Atom msg_type_atom = None;
+
+static
+void initAtoms()
+ {
+ char nm[ 100 ];
+ sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay()));
+ char nm2[] = "_KDE_TOPMENU_MINSIZE";
+ char* names[ 2 ] = { nm, nm2 };
+ Atom atoms[ 2 ];
+ XInternAtoms( qt_xdisplay(), names, 2, False, atoms );
+ selection_atom = atoms[ 0 ];
+ msg_type_atom = atoms[ 1 ];
+ }
+
+Atom Applet::makeSelectionAtom()
+ {
+ if( selection_atom == None )
+ initAtoms();
+ return selection_atom;
+ }
+
+MenuEmbed::MenuEmbed( WId mainwindow_P, bool desktop_P,
+ QWidget* parent_P, const char* name_P )
+ : QXEmbed( parent_P, name_P ),
+ main_window( mainwindow_P ),
+ desktop( desktop_P )
+ {
+ setAutoDelete( false );
+ }
+
+void MenuEmbed::windowChanged( WId w_P )
+ {
+ if( w_P == None )
+ static_cast< Applet* >( parent())->menuLost( this );
+ }
+
+bool MenuEmbed::x11Event( XEvent* ev_P )
+ {
+ if( ev_P->type == ConfigureRequest
+ && ev_P->xconfigurerequest.window == embeddedWinId()
+ && ev_P->xconfigurerequest.value_mask & ( CWWidth | CWHeight ))
+ {
+ XConfigureRequestEvent& ev = ev_P->xconfigurerequest;
+ QSize new_size = size();
+ if( ev.value_mask & CWWidth )
+ new_size.setWidth( ev.width );
+ if( ev.value_mask & CWHeight )
+ new_size.setHeight( ev.height );
+ // resize when the embedded window resizes (still obey min size)
+// kdDebug() << "RES:" << embeddedWinId() << ":" << ev.width << ":" << ev.height << endl;
+ if( ev.width != width() || ev.height != height())
+ {
+ resize( ev.width, ev.height );
+ static_cast< Applet* >( parent())->updateMenuGeometry( this );
+ }
+ sendSyntheticConfigureNotifyEvent();
+// int x, y;
+// unsigned int w, h, d, b;
+// Window root;
+// XGetGeometry( qt_xdisplay(), embeddedWinId(), &root, &x, &y, &w, &h, &b, &d );
+// kdDebug() << "RES3:" << width() << ":" << height() << ":" << w << ":" << h << endl;
+ return true;
+ }
+ return QXEmbed::x11Event( ev_P );
+ }
+
+void MenuEmbed::sendSyntheticConfigureNotifyEvent()
+{
+ QPoint globalPos = mapToGlobal(QPoint(0,0));
+ if (embeddedWinId()) {
+ XConfigureEvent c;
+ memset(&c, 0, sizeof(c));
+ c.type = ConfigureNotify;
+ c.display = qt_xdisplay();
+ c.send_event = True;
+ c.event = embeddedWinId();
+ c.window = winId();
+ c.x = globalPos.x();
+ c.y = globalPos.y();
+ c.width = width();
+ c.height = height();
+ c.border_width = 0;
+ c.above = None;
+ c.override_redirect = 0;
+ XSendEvent(qt_xdisplay(), c.event, true, StructureNotifyMask, (XEvent*)&c);
+ }
+}
+
+void MenuEmbed::setMinimumSize( int w, int h )
+{
+ QXEmbed::setMinimumSize( w, h );
+ // tell the menubar also the allowed minimum size
+ // the applet won't allow resizing to smaller size
+ if( embeddedWinId() != None )
+ {
+// kdDebug() << "RES2:" << width() << ":" << height() << ":" << minimumWidth() << ":" << minimumHeight() << endl;
+ XEvent ev;
+ ev.xclient.display = qt_xdisplay();
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = embeddedWinId();
+ assert( msg_type_atom != None );
+ ev.xclient.message_type = msg_type_atom;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = qt_x_time;
+ ev.xclient.data.l[1] = minimumWidth();
+ ev.xclient.data.l[2] = minimumHeight();
+ ev.xclient.data.l[3] = 0;
+ ev.xclient.data.l[4] = 0;
+ XSendEvent( qt_xdisplay(), embeddedWinId(), False, NoEventMask, &ev );
+ }
+}
+
+void MenuEmbed::setBackground()
+{
+ const QPixmap *pbg = parentWidget()->backgroundPixmap();
+
+ if (pbg)
+ {
+ QPixmap bg(width(), height());
+ bg.fill(parentWidget(), pos());
+ setPaletteBackgroundPixmap(bg);
+ setBackgroundOrigin(WidgetOrigin);
+ }
+ else
+ unsetPalette();
+
+ hide();
+ show();
+ //XClearArea(x11Display(), embeddedWinId(), 0, 0, 0, 0, True);
+}
+
+} // namespace
+
+#include "menuapplet.moc"
diff --git a/kicker/applets/menu/menuapplet.desktop b/kicker/applets/menu/menuapplet.desktop
new file mode 100644
index 000000000..741c2ae29
--- /dev/null
+++ b/kicker/applets/menu/menuapplet.desktop
@@ -0,0 +1,128 @@
+[Desktop Entry]
+Hidden=true
+Type=Plugin
+Name=Menu
+Name[af]=Kieslys
+Name[ar]=قائمة
+Name[be]=Меню
+Name[bg]=Меню
+Name[bn]=মেনু
+Name[br]=Meuziad
+Name[bs]=Meni
+Name[ca]=Menú
+Name[cs]=Nabídka
+Name[cy]=Dewislen
+Name[de]=Menü
+Name[el]=Μενού
+Name[eo]=Menuo
+Name[es]=Menú
+Name[et]=Menüü
+Name[eu]=Menua
+Name[fa]=گزینگان
+Name[fi]=Valikko
+Name[ga]=Roghchlár
+Name[he]=תפריט
+Name[hi]=मेन्यू
+Name[hr]=Izbornik
+Name[hu]=Menü
+Name[is]=Valmynd
+Name[ja]=メニュー
+Name[ka]=მენიუ
+Name[kk]=Мәзір
+Name[km]=ម៉ឺនុយ
+Name[lt]=Meniu
+Name[lv]=Izvēlne
+Name[mk]=Мени
+Name[mn]=Цэс
+Name[nb]=Meny
+Name[nds]=Menü
+Name[ne]=मेनु
+Name[nn]=Meny
+Name[pa]=ਮੇਨੂ
+Name[ro]=Meniu
+Name[ru]=Меню
+Name[rw]=Ibikubiyemo
+Name[sl]=Meni
+Name[sr]=Мени
+Name[sr@Latn]=Meni
+Name[sv]=Meny
+Name[ta]=பட்டி
+Name[te]=పట్టి
+Name[tg]=Меню
+Name[th]=เมนู
+Name[tr]=Menü
+Name[tt]=Saylaq
+Name[uk]=Меню
+Name[uz]=Menyu
+Name[uz@cyrillic]=Меню
+Name[vi]=Thực đơn
+Name[wa]=Dressêye
+Name[zh_CN]=菜单
+Name[zh_TW]=選單
+Comment=Applet embedding standalone menubars
+Comment[ar]=بريمج يضمّن أشرطة قوائم منفردة بذاتها
+Comment[be]=Аплет з убудаваным меню
+Comment[bg]=Системен панел за вграждане на самостоятелни менюта
+Comment[bn]=আলাদা মেনুবার ধারণ করার উপযোগী অ্যাপলেট
+Comment[bs]=Applet koji uvezuje samostalne menije
+Comment[ca]=Un applet encastat estàndard per a les barres de menú
+Comment[cs]=Applet pohlcující samostatné lišty s nabídkami
+Comment[csb]=Aplet zbiérający ùwòlnioné lëstwë menu
+Comment[cy]=Rhaglennig sy'n mewn-adeiladu bariau dewislen unigol
+Comment[da]=Applet der indlejrer alenestående menulinjer
+Comment[de]=Programm zur Einbettung einzelner Menüleisten
+Comment[el]=Μικροεφαρμογή που ενσωματώνει αυτόνομες γραμμές μενού
+Comment[eo]=Aplikaĵeniganta solfunkcia menuzono
+Comment[es]=Una miniaplicación que incluye barras de menú autónomas
+Comment[et]=Aplett, mis põimib endasse isseisvaid menüüribasid
+Comment[eu]=Menu-barrak txertaturik dituen appleta
+Comment[fa]=میله گزینگان خوداتکای نهفتۀ برنامک
+Comment[fi]=Sovelma, joka pystyy upottamaan yksittäisiä valikkorivejä
+Comment[fr]=Une applet intégrant les barres de menu externes
+Comment[fy]=Een applet die lossteande menubalken ynslút
+Comment[gl]=Barras de menu estándar con incrustamento de applets
+Comment[he]=שורת תפריטים משובצת יישומונים העומדת בפני עצמה
+Comment[hi]=ऐपलेट एम्बेडिंग स्टैंडअलोन मेन्यूबार्स
+Comment[hr]=Samostalne trake izbornika s ugrađenim apletima
+Comment[hu]=Kisalkalmazásokat tartalmazni képes önálló menüsorok
+Comment[is]=Smáforrit sem byggir inn sjálfstæðar valmyndastikur
+Comment[it]=Applet per inglobare le barre dei menu
+Comment[ja]=単独のメニューバーに組み込むアプレット
+Comment[ka]=აპლეტი, რომელიც ამატებს ავტონომიურ პანელებს
+Comment[kk]=Бөлек мәзір панельдерді құру апплеті
+Comment[km]=របារ​ម៉ឺនុយ​នៅ​តែ​ឯង​ដែល​បង្កប់​ក្នុង​អាប់ភ្លេត
+Comment[lt]=Įskiepis, rodantis atskiras meniu dalis
+Comment[lv]=Sīklietotne, kas iegulda pastāvīgas izvēlnes
+Comment[mk]=Аплет кој ги вгнездува самостојните менија
+Comment[ms]=Menu bar tersendiri pembenaman aplet
+Comment[mt]=Applet li fiha menubars indipendenti
+Comment[nb]=Et panelprogram som bygger inn frittstående menylinjer
+Comment[nds]=Lüttprogramm för't Inbetten vun enkelte Warktüüchbalkens
+Comment[ne]=एप्लेट सम्मिलित गर्ने स्ट्यान्डअलोन मेनुपट्टी
+Comment[nl]=Een applet die losstaande menubalken insluit
+Comment[nn]=Eit panelprogram som kan innehalda frittståande menylinjer
+Comment[pa]=ਇੱਕਲੀ ਮੇਨੂਪੱਟੀ ਐਪਲਿਟ
+Comment[pl]=Aplet zbierający uwolnione paski menu
+Comment[pt]=Uma 'applet' que incorpora barras de menu autónomas
+Comment[pt_BR]=Mini-aplicativo para embutir barras de menu ao painel
+Comment[ro]=O miniaplicație ce înglobează bare de meniu
+Comment[ru]=Аплет, встраивающий автономные панели меню
+Comment[rw]=Apuleti zifitemo umwanya-ibikubiyemo wigenga
+Comment[se]=Prográmmaš mii vuojuha oktanas fálloholggaid
+Comment[sk]=Applet pre samostatné pruhy menu
+Comment[sl]=Vstavek, ki vključuje samostojne menijske vrstice
+Comment[sr]=Аплет за уграђивање самосталних менија
+Comment[sr@Latn]=Aplet za ugrađivanje samostalnih menija
+Comment[sv]=Miniprogram för inbäddning av fristående menyer
+Comment[ta]=குறுநிரல் பொதிந்த தனியான மெனுபட்டிகள்
+Comment[th]=แอพเพล็ตสำหรับฝังแถบเมนูลงพาเนล
+Comment[tr]=Yalnız menü çubuklarını gömen uygulamacık 
+Comment[tt]=Ayırım torğan saylaq-tirälär berläşterüçe applet
+Comment[uk]=Аплет вбудовних окремих смужок меню
+Comment[vi]=Tiểu ứng dụng nhúng các thanh thực đơn đứng riêng
+Comment[wa]=Aplikete po fé ravaler des bårs di dressêye totes seules
+Comment[zh_CN]=嵌入独立菜单栏的小程序
+Comment[zh_TW]=單獨置於面板中的選單列
+
+X-KDE-Library=menu_panelapplet
+X-KDE-UniqueApplet=true
diff --git a/kicker/applets/menu/menuapplet.h b/kicker/applets/menu/menuapplet.h
new file mode 100644
index 000000000..8374e897b
--- /dev/null
+++ b/kicker/applets/menu/menuapplet.h
@@ -0,0 +1,258 @@
+/*****************************************************************
+
+Copyright (c) 2002 Siegfried Nijssen <[email protected]>
+Copyright (c) 2003 Lubos Lunak <[email protected]>
+
+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 _MENUAPPLET_H_
+#define _MENUAPPLET_H_
+
+#include <assert.h>
+
+#include <qvaluelist.h>
+#include <qevent.h>
+#include <qxembed.h>
+
+#include <kpanelapplet.h>
+#include <kmanagerselection.h>
+
+#include <dcopobject.h>
+#include <dcopclient.h>
+
+#include <karrowbutton.h>
+
+class KWinModule;
+
+namespace KickerMenuApplet
+{
+
+class MenuEmbed;
+
+/**
+ * @short A central menu bar
+ *
+ * @description All status change, such as when an window is activated,
+ * a new window popped up, etc, is received via @ref KWin::WindowInfo and @ref
+ * NETWinInfo. Status changes for X selections are done via KSelectionWatcher.
+ *
+ * How it works in broad terms: KickerMenuApplet gets notified as soon a window
+ * changes(a new pops up etc.) and accordingly updates the list @ref menus,
+ * which contains all known menus. When a new window gains focus, it looks up the
+ * correct MenuEmbed in @ref menus, and then switches to that one.
+ *
+ * The documentation is a bit rusty -- read it with a critical eye.
+ *
+ * @author Siegfried Nijssen <[email protected]>
+ * @author Lubos Lunak <[email protected]>
+ */
+
+class Applet : public KPanelApplet, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+k_dcop:
+
+ /**
+ * Called by the Kicker configuration(KCM). Does in turn call
+ * readSettings().
+ */
+ ASYNC configure();
+
+public:
+ Applet( const QString& configFile, QWidget *parent );
+ virtual ~Applet();
+ virtual int widthForHeight( int height ) const;
+ virtual int heightForWidth( int width ) const;
+
+ /**
+ * Looks up @param embed in @ref menus, and removes it.
+ */
+ void menuLost( MenuEmbed* embed );
+ void updateMenuGeometry( MenuEmbed* embed );
+ void setBackground();
+
+protected:
+
+ virtual void paletteChange(const QPalette& );
+ virtual void positionChange( Position p );
+ virtual void moveEvent(QMoveEvent *);
+
+private slots:
+
+ /**
+ * Called each time a window is added. When the selection is
+ * initially claimed, it is called for every window. It does the big
+ * work, and does the embedding with MenuEmbed.
+ */
+ void windowAdded( WId w );
+
+ /**
+ * Finds @p w's menubar in @see menus, and then activates it.
+ *
+ * @param w the activated window.
+ */
+ void activeWindowChanged( WId w );
+
+ /**
+ * Called when the selection(selection_atom) is lost. Deletes the
+ * embedded menus, and starts listening for the selection again.
+ *
+ */
+ void lostSelection();
+
+ /**
+ * Reads whether a central menu bar should be used or not, basically.
+ */
+ void readSettings();
+ void claimSelection();
+
+private:
+
+ /**
+ * Returns true if the selection is Not owned. That is, the menu applet
+ * isn't "running" and is listening for the selection to be released.
+ */
+ bool isDisabled() const;
+
+ WId tryTransientFor( WId w );
+
+ /**
+ * Does some sanity checks, and then sets active_menu to @param embed.
+ */
+ void activateMenu( MenuEmbed* embed );
+
+ /**
+ * Creates msg_type_atom and selection_atom, and returns the latter.
+ */
+ static Atom makeSelectionAtom();
+ void updateTopEdgeOffset();
+ KWinModule* module;
+
+ /**
+ * List of all known menus.
+ */
+ QValueList< MenuEmbed* > menus;
+
+ /**
+ * A pointer to the current active menu, which is member
+ * of @ref menus.
+ */
+ MenuEmbed* active_menu;
+
+ KSelectionOwner* selection;
+
+ /**
+ * Only the messenger. Dispatches signals to claimSelection().
+ */
+ KSelectionWatcher* selection_watcher;
+
+ /**
+ * Whether the Desktop menu should be used, when a window
+ * with no menu is used.
+ */
+ bool desktop_menu;
+ DCOPClient dcopclient;
+
+ /**
+ * The distance to the top of the screen.
+ */
+ int topEdgeOffset;
+};
+
+/**
+ *
+ * @author Siegfried Nijssen <[email protected]>
+ * @author Lubos Lunak <[email protected]>
+ */
+class MenuEmbed
+ : public QXEmbed
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Default constructor
+ *
+ * @param mainwindow window ID for the window to be plugged
+ * @param desktop true if @p mainwindow is the desktop
+ */
+ MenuEmbed( WId mainwindow, bool desktop,
+ QWidget* parent = NULL, const char* name = NULL );
+
+ void setBackground();
+
+ /**
+ * @returns the window ID for the handled window.
+ */
+ WId mainWindow() const;
+
+ /**
+ */
+ bool isDesktopMenu() const;
+ virtual void setMinimumSize( int w, int h );
+ void setMinimumSize( const QSize& s ) { setMinimumSize( s.width(), s.height()); }
+
+protected:
+
+ /**
+ * When @p w is None, that is the embedded window was lost, it calls
+ * menuLost() such that the this is deleted from @ref menus list.
+ */
+ virtual void windowChanged( WId w );
+
+ virtual bool x11Event( XEvent* ev );
+
+private:
+
+ void sendSyntheticConfigureNotifyEvent();
+ WId main_window;
+
+ /**
+ * If the window is the desktop window.
+ */
+ bool desktop;
+};
+
+inline
+bool Applet::isDisabled() const
+{
+ assert( ( selection == NULL && selection_watcher != NULL )
+ || ( selection != NULL && selection_watcher == NULL ));
+ return selection == NULL;
+}
+
+inline
+WId MenuEmbed::mainWindow() const
+{
+ return main_window;
+}
+
+inline
+bool MenuEmbed::isDesktopMenu() const
+{
+ return desktop;
+}
+
+} // namespace
+
+#endif
diff --git a/kicker/applets/minipager/Makefile.am b/kicker/applets/minipager/Makefile.am
new file mode 100644
index 000000000..da149f468
--- /dev/null
+++ b/kicker/applets/minipager/Makefile.am
@@ -0,0 +1,25 @@
+INCLUDES = $(all_includes) -I$(srcdir)/../../taskmanager \
+ -I$(srcdir)/../../libkicker -I../../libkicker
+
+kde_module_LTLIBRARIES = minipager_panelapplet.la
+
+minipager_panelapplet_la_SOURCES = pagerapplet.cpp pagerbutton.cpp pagersettings.kcfgc
+
+minipager_panelapplet_la_METASOURCES = AUTO
+noinst_HEADERS = pagerapplet.h pagerbutton.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = minipagerapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+minipager_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+minipager_panelapplet_la_LIBADD = $(LIB_KDEUI) \
+ ../../taskmanager/libtaskmanager.la \
+ ../../libkicker/libkickermain.la
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kminipagerapplet.pot
+
+srcdoc:
+ kdoc -a -p -H -d $$HOME/web/src/kminipagerapplet kminipagerapplet *.h -lqt -lkdecore -lkdeui -lkfile
diff --git a/kicker/applets/minipager/minipagerapplet.desktop b/kicker/applets/minipager/minipagerapplet.desktop
new file mode 100644
index 000000000..df5dcfb03
--- /dev/null
+++ b/kicker/applets/minipager/minipagerapplet.desktop
@@ -0,0 +1,122 @@
+[Desktop Entry]
+Type=Plugin
+Name=Desktop Preview & Pager
+Name[af]=Werkskerm Voorskou & Boodskapper
+Name[be]=Прагляд працоўных сталоў і пэйджар
+Name[bg]=Изглед на екрана и пейджър
+Name[bn]=ডেস্কটপ প্রাকদর্শন এবং পেজার
+Name[bs]=Pregled i promjena radnih površina
+Name[ca]=Vista prèvia d'escriptori i paginador
+Name[cs]=Přepínač a náhled ploch
+Name[csb]=Przestôwnik ë przezérnik pùltów
+Name[da]=Desktop-forhåndsviser & -pager
+Name[de]=Umschalten zwischen Arbeitsflächen
+Name[el]=Προεπισκόπηση και αλλαγή επιφάνειας εργασίας
+Name[eo]=Tabula antaŭrigardilo kaj paĝilo
+Name[es]=Paginador y previsualizador del escritorio
+Name[et]=Töölaudade eelvaatlus ja vahetaja
+Name[eu]=Mahaigain aurrebista eta orrialdekatzailea
+Name[fa]=پیش‌نمایش و پی‌جوی رومیزی
+Name[fi]=Työpöydän esikatselu ja sivutus
+Name[fr]=Gestionnaire et aperçu des bureaux
+Name[fy]=Buroblêdfoarbyld en Pager
+Name[gl]=Antevisor e Paxinador do Escritório
+Name[hr]=Pager i preglednik radne površine
+Name[hu]=Asztali előnézet és lapozó
+Name[is]=Skjáborðs forskoðari & flettir
+Name[it]=Anteprime e gestione dei desktop
+Name[ja]=デスクトッププレビューとページャ
+Name[ka]=სამუშაო დაფისა და გვერდების ჩვენება
+Name[kk]=Үстелдер ақтарғышы
+Name[km]=ការ​មើលផ្ទៃតុ​ជាមុន និង​ភេកយ័រ
+Name[lt]=Darbastalių peržiūrėjimo ir puslapiavimo priemonė
+Name[mk]=Преглед и пејџер на раб. површина
+Name[nb]=Forhåndsvising og bytte av skrivebord
+Name[nds]=Schriefdisch-Ümschalter & Vöransicht
+Name[ne]=डेस्कटप पूर्वावलोकन र पेजर
+Name[nl]=Bureaubladvoorbeeld en pager
+Name[nn]=Førehandsvising og byte av skrivebord
+Name[pa]=ਵੇਹੜਾ ਝਲਕ ਅਤੇ ਪੇਜ਼ਰ
+Name[pl]=Przełącznik i przeglądarka pulpitów
+Name[pt]=Antevisão e Paginador do Ecrã
+Name[pt_BR]=Pager & Pré-visualizador de Área de Trabalho
+Name[ro]=Paginator și previzualizor pentru desktop
+Name[ru]=Переключатель рабочих столов
+Name[se]=Čállinbevddiid ovdačájeheaddji ja molssodeaddji
+Name[sk]=Náhľad a stránkovač pracovnej plochy
+Name[sl]=Ogledovalnik in pozivnik namizja
+Name[sr]=Прегледач и пејџер радних површина
+Name[sr@Latn]=Pregledač i pejdžer radnih površina
+Name[sv]=Förhandsgranskning och hantering av skrivbord
+Name[te]=రంగస్థల ముందు వీక్షణం & పెజర్
+Name[th]=แสดงตัวอย่างและเปลี่ยนพื้นที่ทำงาน
+Name[tr]=Masaüstü Önizleyici ve Sayfalayıcı
+Name[uk]=Перегляд стільниці і пейджер
+Name[uz]=Ish stolining peyjeri
+Name[uz@cyrillic]=Иш столининг пейжери
+Name[vi]=Xem thử Màn hình nền & Chuyển đổi
+Name[wa]=Préveyeu et pådjeu do scribanne
+Name[zh_CN]=桌面预览器和页面切换器
+Name[zh_TW]=桌面預覽與縮圖
+
+Comment=Preview, manage and switch to multiple virtual desktops
+Comment[af]=Voorskou van, bestuur van en wissel tussen veelvuldige virtuelewerkskerms
+Comment[ar]=عايين، دبِر و بدل إلى أسطح المكتب الوهمية المتعددة
+Comment[be]=Прагляд, кіраванне і пераключэнне між некалькімі віртуальнымі працоўнымі сталамі
+Comment[bg]=Преглед, управление и превключване към виртуалните работни плотове
+Comment[bs]=Pregledajte, upravljajte i mijenjajte radne površine
+Comment[ca]=Vista prèvia, gestió i canvi entre diversos escriptoris virtuals
+Comment[cs]=Správa, náhled a přepínání virtuálních pracovních ploch
+Comment[csb]=Pòdzérk, sprôwianié ë przestôwianié wirtualnëch pùltów
+Comment[da]=Forhåndsvis, håndtér og skift mellem flere virtuelle desktoppe
+Comment[de]=Vorschau und Verwaltung der virtuellen Arbeitsflächen.
+Comment[el]=Προεπισκόπηση, διαχείριση και εναλλαγή σε πολλαπλές εικονικές επιφάνειες εργασίας
+Comment[eo]=Antaŭrigardi, mastrumi kaj komuti al pluraj virtualaj labortabloj
+Comment[es]=Previsualizar, gestionar y cambiar a múltiples escritorios virtuales
+Comment[et]=Virtuaalsete töölaudade eelvaatlus, haldus ja vahetamine
+Comment[eu]=Aurrebista, kudeatu eta aldatu mahaigain birtual anitzez
+Comment[fa]=پیش‌نمایش، مدیریت و سودهی به رومیزیهای مجازی چندگانه
+Comment[fi]=Esikatsele, hallitse ja vaihda virtuaalisia työpöytiä
+Comment[fr]=Affichage, gestion et changement des bureaux virtuels multiples
+Comment[fy]=Foarbyld, beheare en skeakel nei meardere firtuele buroblêden
+Comment[gl]=Xestione, cambie e antevexa múltiplos escritórios virtuais
+Comment[he]=תצוגה מקדימה, והעברה של שולחנות עבודה וירטואלים
+Comment[hr]=Pregled, upravljanje i prebacivanje između višestrukih virtualnih radnih površina
+Comment[hu]=A virtuális asztalok előnézete, kezelése, használata
+Comment[is]=Forskoðaðu, stjórnaðu og flettu á milli marga sýndarskjáborða
+Comment[it]=Gestisce, cambia e mostra le anteprime dei desktop virtuali multipli
+Comment[ja]=複数の仮想デスクトップのプレビュー、管理と切り替え
+Comment[kk]=Көп қиртуалды үстелдерді қарау, басқару және олаға ауысу
+Comment[km]=ការ​មើល​ជាមុន, គ្រប់គ្រង និង​ប្តូរ​ទៅពហុផ្ទៃតុ​និម្មិត​
+Comment[lt]=Peržiūrėkite, tvarkykite ir lengvai vaikščiokite tarp daugelio menamų darbastalių
+Comment[mk]=Преглед, управување и префрлање на повеќе виртуелни работни површини
+Comment[nb]=Forhåndsvisning, håndtere og bytte til virtuelle skrivebord
+Comment[nds]=Vöransicht un Pleeg vun virtuelle Schriefdischen
+Comment[ne]=पूर्वावलोकन अनि प्रबन्ध गर्नुहोस् र अवास्तविक डेस्कटपमा स्विच गर्नुहोस्
+Comment[nl]=Vooruitblik, beheer en schakel naar meerdere virtuele bureaubladen
+Comment[nn]=Førehandsvis, handter og byt til virtuelle skrivebord
+Comment[pa]=ਕਈ ਫ਼ਰਜ਼ੀ ਵੇਹੜਿਆਂ ਦੀ ਝਲਕ ਵੇਖਣ, ਉਹਨਾਂ ਦੇ ਪਰਬੰਧ ਅਤੇ ਤਬਦੀਲ ਕਰਨ ਲਈ ਹੈ
+Comment[pl]=Podgląd, zarządzanie i przełączanie wirtualnych pulpitów
+Comment[pt]=Antever, gerir e mudar para vários ecrãs virtuais
+Comment[pt_BR]=Fornece uma pré-visualização, gerencia e alterna entre múltiplos ambientes de trabalho virtuais
+Comment[ro]=Previzualizează, gestionează și schimbă desktop-uri virtuale
+Comment[ru]=Переключение между виртуальными рабочими столами с возможностью показа их содержимого
+Comment[sk]=Náhľad, nastavenie a prepínanie viacerých virtuálnych pracovných plôch
+Comment[sl]=Predogled, upravljanje in preklapljanje za več navideznih namizij
+Comment[sr]=Прегледајте, управљајте, и пребацујте се између радних површина
+Comment[sr@Latn]=Pregledajte, upravljajte, i prebacujte se između radnih površina
+Comment[sv]=Förhandsgranska, hantera och byt mellan flera virtuella skrivbord
+Comment[te]=ముందు వీక్షణ, ఎక్కువ మిధ్యా రంగస్థలాల నియంత్రణ మరయు మార్పు
+Comment[th]=ดูตัวอย่าง, จัดการและเปลี่ยนไปใช้พื้นที่ทำงานเสมือนอื่นๆ
+Comment[uk]=Перегляд, керування та перемикання на багато віртуальних стільниць
+Comment[uz]=Virtual ish stollarini koʻrib chiqish, boshqarish va ularga oʻtish uchun qulay vosita
+Comment[uz@cyrillic]=Виртуал иш столларини кўриб чиқиш, бошқариш ва уларга ўтиш учун қулай восита
+Comment[vi]=Xem thử, quản lý và chuyển đổi giữa các màn hình nền ảo
+Comment[wa]=Prévey, manaedjî et candjî viè sacwants forveyous scribannes
+Comment[zh_CN]=预览、管理及切换多个虚拟桌面
+Comment[zh_TW]=預覽、管理並切換到多個虛擬桌面
+
+Icon=kpager
+
+X-KDE-Library=minipager_panelapplet
+X-KDE-UniqueApplet=false
diff --git a/kicker/applets/minipager/pagerapplet.cpp b/kicker/applets/minipager/pagerapplet.cpp
new file mode 100644
index 000000000..3ba87c0b1
--- /dev/null
+++ b/kicker/applets/minipager/pagerapplet.cpp
@@ -0,0 +1,906 @@
+/*****************************************************************
+
+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 <qpainter.h>
+#include <qtooltip.h>
+#include <qlineedit.h>
+#include <qpopupmenu.h>
+#include <qlayout.h>
+#include <qbuttongroup.h>
+
+#include <dcopref.h>
+#include <kglobalsettings.h>
+#include <kwin.h>
+#include <kwinmodule.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kprocess.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <dcopclient.h>
+#include <netwm.h>
+#include <kmanagerselection.h>
+
+#include "global.h"
+#include "kickertip.h"
+#include "kickerSettings.h"
+#include "kshadowengine.h"
+#include "kshadowsettings.h"
+#include "paneldrag.h"
+#include "taskmanager.h"
+
+#include "pagerapplet.h"
+#include "pagerapplet.moc"
+
+#ifdef FocusOut
+#undef FocusOut
+#endif
+
+const int knDesktopPreviewSize = 12;
+const int knBtnSpacing = 1;
+
+// The previews tend to have a 4/3 aspect ratio
+static const int smallHeight = 32;
+static const int smallWidth = 42;
+
+// config menu id offsets
+static const int rowOffset = 2000;
+static const int labelOffset = 200;
+static const int bgOffset = 300;
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("kminipagerapplet");
+ return new KMiniPager(configFile, KPanelApplet::Normal, 0, parent, "kminipagerapplet");
+ }
+}
+
+KMiniPager::KMiniPager(const QString& configFile, Type type, int actions,
+ QWidget *parent, const char *name)
+ : KPanelApplet( configFile, type, actions, parent, name ),
+ m_layout(0),
+ m_desktopLayoutOwner( NULL ),
+ m_shadowEngine(0),
+ m_contextMenu(0),
+ m_settings( new PagerSettings(sharedConfig()) )
+{
+ setBackgroundOrigin( AncestorOrigin );
+ int scnum = QApplication::desktop()->screenNumber(this);
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+ if (desk.width() <= 800)
+ {
+ KConfigSkeleton::ItemBool* item = dynamic_cast<KConfigSkeleton::ItemBool*>(m_settings->findItem("Preview"));
+ if (item)
+ {
+ item->setDefaultValue(false);
+ }
+ }
+ m_settings->readConfig();
+ m_windows.setAutoDelete(true);
+ if (m_settings->preview())
+ {
+ TaskManager::the()->trackGeometry();
+ }
+
+ m_group = new QButtonGroup(this);
+ m_group->setBackgroundOrigin(AncestorOrigin);
+ m_group->setFrameStyle(QFrame::NoFrame);
+ m_group->setExclusive( true );
+
+ setFont( KGlobalSettings::taskbarFont() );
+
+ m_kwin = new KWinModule(this);
+ m_activeWindow = m_kwin->activeWindow();
+ m_curDesk = m_kwin->currentDesktop();
+
+ if (m_curDesk == 0) // kwin not yet launched
+ {
+ m_curDesk = 1;
+ }
+
+ desktopLayoutOrientation = Qt::Horizontal;
+ desktopLayoutX = -1;
+ desktopLayoutY = -1;
+
+ QSize s(m_kwin->numberOfViewports(m_kwin->currentDesktop()));
+ m_useViewports = s.width() * s.height() > 1;
+
+ drawButtons();
+
+ connect( m_kwin, SIGNAL( currentDesktopChanged(int)), SLOT( slotSetDesktop(int) ) );
+ connect( m_kwin, SIGNAL( currentDesktopViewportChanged(int, const QPoint&)),
+ SLOT(slotSetDesktopViewport(int, const QPoint&)));
+ connect( m_kwin, SIGNAL( numberOfDesktopsChanged(int)), SLOT( slotSetDesktopCount(int) ) );
+ connect( m_kwin, SIGNAL( activeWindowChanged(WId)), SLOT( slotActiveWindowChanged(WId) ) );
+ connect( m_kwin, SIGNAL( windowAdded(WId) ), this, SLOT( slotWindowAdded(WId) ) );
+ connect( m_kwin, SIGNAL( windowRemoved(WId) ), this, SLOT( slotWindowRemoved(WId) ) );
+ connect( m_kwin, SIGNAL( windowChanged(WId,unsigned int) ), this, SLOT( slotWindowChanged(WId,unsigned int) ) );
+ connect( m_kwin, SIGNAL( desktopNamesChanged() ), this, SLOT( slotDesktopNamesChanged() ) );
+ connect( kapp, SIGNAL(backgroundChanged(int)), SLOT(slotBackgroundChanged(int)) );
+
+ if (kapp->authorizeKAction("kicker_rmb") && kapp->authorizeControlModule("kde-kcmtaskbar.desktop"))
+ {
+ m_contextMenu = new QPopupMenu();
+ connect(m_contextMenu, SIGNAL(aboutToShow()), SLOT(aboutToShowContextMenu()));
+ connect(m_contextMenu, SIGNAL(activated(int)), SLOT(contextMenuActivated(int)));
+ setCustomMenu(m_contextMenu);
+ }
+
+ QValueList<WId>::ConstIterator it;
+ QValueList<WId>::ConstIterator itEnd = m_kwin->windows().end();
+ for ( it = m_kwin->windows().begin(); it != itEnd; ++it)
+ {
+ slotWindowAdded( (*it) );
+ }
+
+ slotSetDesktop( m_curDesk );
+ updateLayout();
+}
+
+KMiniPager::~KMiniPager()
+{
+ KGlobal::locale()->removeCatalogue("kminipagerapplet");
+ delete m_contextMenu;
+ delete m_settings;
+ delete m_shadowEngine;
+}
+
+void KMiniPager::slotBackgroundChanged(int desk)
+{
+ unsigned numDesktops = m_kwin->numberOfDesktops();
+ if (numDesktops != m_desktops.count())
+ {
+ slotSetDesktopCount(numDesktops);
+ }
+
+ if (desk < 1 || (unsigned) desk > m_desktops.count())
+ {
+ // should not happen, but better to be paranoid than crash
+ return;
+ }
+
+ m_desktops[desk - 1]->backgroundChanged();
+}
+
+void KMiniPager::slotSetDesktop(int desktop)
+{
+ if (m_kwin->numberOfDesktops() > static_cast<int>(m_desktops.count()))
+ {
+ slotSetDesktopCount( m_kwin->numberOfDesktops() );
+ }
+
+ if (!m_useViewports && (desktop != KWin::currentDesktop()))
+ {
+ // this can happen when the user clicks on a desktop,
+ // holds down the key combo to switch desktops, lets the
+ // mouse go but keeps the key combo held. the desktop will switch
+ // back to the desktop associated with the key combo and then it
+ // becomes a race condition between kwin's signal and the button's
+ // signal. usually kwin wins.
+ return;
+ }
+
+ m_curDesk = desktop;
+ if (m_curDesk < 1)
+ {
+ m_curDesk = 1;
+ }
+
+ KMiniPagerButton* button = m_desktops[m_curDesk - 1];
+ if (!button->isOn())
+ {
+ button->toggle();
+ }
+}
+
+void KMiniPager::slotSetDesktopViewport(int desktop, const QPoint& viewport)
+{
+ // ###
+ Q_UNUSED(desktop);
+ QSize s(m_kwin->numberOfViewports(m_kwin->currentDesktop()));
+ slotSetDesktop((viewport.y()-1) * s.width() + viewport.x() );
+}
+
+void KMiniPager::slotButtonSelected( int desk )
+{
+ if (m_kwin->numberOfViewports(m_kwin->currentDesktop()).width() *
+ m_kwin->numberOfViewports(m_kwin->currentDesktop()).height() > 1)
+ {
+ QPoint p;
+
+ p.setX( (desk-1) * QApplication::desktop()->width());
+ p.setY( 0 );
+
+ KWin::setCurrentDesktopViewport(m_kwin->currentDesktop(), p);
+ }
+ else
+ KWin::setCurrentDesktop( desk );
+
+ slotSetDesktop( desk );
+}
+
+int KMiniPager::widthForHeight(int h) const
+{
+ if (orientation() == Qt::Vertical)
+ {
+ return width();
+ }
+
+ int deskNum = m_kwin->numberOfDesktops() * m_kwin->numberOfViewports(0).width()
+ * m_kwin->numberOfViewports(0).height();
+
+ int rowNum = m_settings->numberOfRows();
+ if (rowNum == 0)
+ {
+ if (h <= 32 || deskNum <= 1)
+ {
+ rowNum = 1;
+ }
+ else
+ {
+ rowNum = 2;
+ }
+ }
+
+ int deskCols = deskNum/rowNum;
+ if(deskNum == 0 || deskNum % rowNum != 0)
+ deskCols += 1;
+
+ int bw = (h / rowNum);
+ if( m_settings->labelType() != PagerSettings::EnumLabelType::LabelName )
+ {
+ if (desktopPreview() || m_settings->backgroundType() == PagerSettings::EnumBackgroundType::BgLive)
+ {
+ bw = (int) ( bw * (double) QApplication::desktop()->width() / QApplication::desktop()->height() );
+ }
+ }
+ else
+ {
+ // scale to desktop width as a minimum
+ bw = (int) (bw * (double) QApplication::desktop()->width() / QApplication::desktop()->height());
+ QFontMetrics fm = fontMetrics();
+ for (int i = 1; i <= deskNum; i++)
+ {
+ int sw = fm.width( m_kwin->desktopName( i ) ) + 8;
+ if (sw > bw)
+ {
+ bw = sw;
+ }
+ }
+ }
+
+ // we add one to the width for the spacing in between the buttons
+ // however, the last button doesn't have a space on the end of it (it's
+ // only _between_ buttons) so we then remove that one pixel
+ return (deskCols * (bw + 1)) - 1;
+}
+
+int KMiniPager::heightForWidth(int w) const
+{
+ if (orientation() == Qt::Horizontal)
+ {
+ return height();
+ }
+
+ int deskNum = m_kwin->numberOfDesktops() * m_kwin->numberOfViewports(0).width()
+ * m_kwin->numberOfViewports(0).height();
+ int rowNum = m_settings->numberOfRows(); // actually these are columns now... oh well.
+ if (rowNum == 0)
+ {
+ if (w <= 48 || deskNum == 1)
+ {
+ rowNum = 1;
+ }
+ else
+ {
+ rowNum = 2;
+ }
+ }
+
+ int deskCols = deskNum/rowNum;
+ if(deskNum == 0 || deskNum % rowNum != 0)
+ {
+ deskCols += 1;
+ }
+
+ int bh = (w/rowNum) + 1;
+ if ( desktopPreview() )
+ {
+ bh = (int) ( bh * (double) QApplication::desktop()->height() / QApplication::desktop()->width() );
+ }
+ else if ( m_settings->labelType() == PagerSettings::EnumLabelType::LabelName )
+ {
+ bh = fontMetrics().lineSpacing() + 8;
+ }
+
+ // we add one to the width for the spacing in between the buttons
+ // however, the last button doesn't have a space on the end of it (it's
+ // only _between_ buttons) so we then remove that one pixel
+ int nHg = (deskCols * (bh + 1)) - 1;
+
+ return nHg;
+}
+
+void KMiniPager::updateDesktopLayout(int o, int x, int y)
+{
+ if ((desktopLayoutOrientation == o) &&
+ (desktopLayoutX == x) &&
+ (desktopLayoutY == y))
+ {
+ return;
+ }
+
+ desktopLayoutOrientation = o;
+ desktopLayoutX = x;
+ desktopLayoutY = y;
+ if( x == -1 ) // do-the-maths-yourself is encoded as 0 in the wm spec
+ x = 0;
+ if( y == -1 )
+ y = 0;
+ if( m_desktopLayoutOwner == NULL )
+ { // must own manager selection before setting global desktop layout
+ int screen = DefaultScreen( qt_xdisplay());
+ m_desktopLayoutOwner = new KSelectionOwner( QString( "_NET_DESKTOP_LAYOUT_S%1" ).arg( screen ).latin1(),
+ screen, this );
+ if( !m_desktopLayoutOwner->claim( false ))
+ {
+ delete m_desktopLayoutOwner;
+ m_desktopLayoutOwner = NULL;
+ return;
+ }
+ }
+ NET::Orientation orient = o == Qt::Horizontal ? NET::OrientationHorizontal : NET::OrientationVertical;
+ NETRootInfo i( qt_xdisplay(), 0 );
+ i.setDesktopLayout( orient, x, y, NET::DesktopLayoutCornerTopLeft );
+}
+
+void KMiniPager::resizeEvent(QResizeEvent*)
+{
+ bool horiz = orientation() == Horizontal;
+
+ int deskNum = m_desktops.count();
+ int rowNum = m_settings->numberOfRows();
+ if (rowNum == 0)
+ {
+ if (((horiz && height()<=32)||(!horiz && width()<=48)) || deskNum <= 1)
+ rowNum = 1;
+ else
+ rowNum = 2;
+ }
+
+ int deskCols = deskNum/rowNum;
+ if(deskNum == 0 || deskNum % rowNum != 0)
+ deskCols += 1;
+
+ if (m_layout)
+ {
+ delete m_layout;
+ m_layout = 0;
+ }
+
+ int nDX, nDY;
+ if (horiz)
+ {
+ nDX = rowNum;
+ nDY = deskCols;
+ updateDesktopLayout(Qt::Horizontal, -1, nDX);
+ }
+ else
+ {
+ nDX = deskCols;
+ nDY = rowNum;
+ updateDesktopLayout(Qt::Horizontal, nDY, -1);
+ }
+
+ // 1 pixel spacing.
+ m_layout = new QGridLayout(this, nDX, nDY, 0, 1);
+
+ QValueList<KMiniPagerButton*>::Iterator it = m_desktops.begin();
+ QValueList<KMiniPagerButton*>::Iterator itEnd = m_desktops.end();
+ int c = 0,
+ r = 0;
+ while( it != itEnd ) {
+ c = 0;
+ while( (it != itEnd) && (c < nDY) ) {
+ m_layout->addWidget( *it, r, c );
+ ++it;
+ ++c;
+ }
+ ++r;
+ }
+
+ m_layout->activate();
+ updateGeometry();
+}
+
+void KMiniPager::wheelEvent( QWheelEvent* e )
+{
+ int newDesk;
+ int desktops = KWin::numberOfDesktops();
+ if (m_kwin->numberOfViewports(0).width() * m_kwin->numberOfViewports(0).height() > 1 )
+ desktops = m_kwin->numberOfViewports(0).width() * m_kwin->numberOfViewports(0).height();
+ if (e->delta() < 0)
+ {
+ newDesk = m_curDesk % desktops + 1;
+ }
+ else
+ {
+ newDesk = (desktops + m_curDesk - 2) % desktops + 1;
+ }
+
+ slotButtonSelected(newDesk);
+}
+
+void KMiniPager::drawButtons()
+{
+ int deskNum = m_kwin->numberOfDesktops();
+ KMiniPagerButton *desk;
+
+ int count = 1;
+ int i = 1;
+ do
+ {
+ QSize viewportNum = m_kwin->numberOfViewports(i);
+ for (int j = 1; j <= viewportNum.width() * viewportNum.height(); ++j)
+ {
+ QSize s(m_kwin->numberOfViewports(m_kwin->currentDesktop()));
+ QPoint viewport( (j-1) % s.width(), (j-1) / s.width());
+ desk = new KMiniPagerButton( count, m_useViewports, viewport, this );
+ if ( m_settings->labelType() != PagerSettings::EnumLabelType::LabelName )
+ {
+ QToolTip::add( desk, desk->desktopName() );
+ }
+
+ m_desktops.append( desk );
+ m_group->insert( desk, count );
+
+ connect(desk, SIGNAL(buttonSelected(int)),
+ SLOT(slotButtonSelected(int)) );
+ connect(desk, SIGNAL(showMenu(const QPoint&, int )),
+ SLOT(slotShowMenu(const QPoint&, int )) );
+
+ desk->show();
+ ++count;
+ }
+ }
+ while ( ++i <= deskNum );
+}
+
+void KMiniPager::slotSetDesktopCount( int )
+{
+ QValueList<KMiniPagerButton*>::ConstIterator it;
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+ for( it = m_desktops.begin(); it != itEnd; ++it )
+ {
+ delete (*it);
+ }
+ m_desktops.clear();
+
+ drawButtons();
+
+ m_curDesk = m_kwin->currentDesktop();
+ if ( m_curDesk == 0 )
+ {
+ m_curDesk = 1;
+ }
+
+ resizeEvent(0);
+ updateLayout();
+}
+
+void KMiniPager::slotActiveWindowChanged( WId win )
+{
+ if (desktopPreview())
+ {
+ KWin::WindowInfo* inf1 = m_activeWindow ? info( m_activeWindow ) : NULL;
+ KWin::WindowInfo* inf2 = win ? info( win ) : NULL;
+ m_activeWindow = win;
+
+ QValueList<KMiniPagerButton*>::ConstIterator it;
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+ for ( it = m_desktops.begin(); it != itEnd; ++it)
+ {
+ if ( ( inf1 && (*it)->shouldPaintWindow(inf1)) ||
+ ( inf2 && (*it)->shouldPaintWindow(inf2)) )
+ {
+ (*it)->windowsChanged();
+ }
+ }
+ }
+}
+
+void KMiniPager::slotWindowAdded( WId win)
+{
+ if (desktopPreview())
+ {
+ KWin::WindowInfo* inf = info( win );
+
+ if (inf->state() & NET::SkipPager)
+ {
+ return;
+ }
+
+ QValueList<KMiniPagerButton*>::ConstIterator it;
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+ for ( it = m_desktops.begin(); it != itEnd; ++it)
+ {
+ if ( (*it)->shouldPaintWindow(inf) )
+ {
+ (*it)->windowsChanged();
+ }
+ }
+ }
+}
+
+void KMiniPager::slotWindowRemoved(WId win)
+{
+ if (desktopPreview())
+ {
+ KWin::WindowInfo* inf = info(win);
+ bool onAllDesktops = inf->onAllDesktops();
+ bool onAllViewports = inf->hasState(NET::Sticky);
+ bool skipPager = inf->state() & NET::SkipPager;
+ int desktop = inf->desktop();
+
+ if (win == m_activeWindow)
+ m_activeWindow = 0;
+
+ m_windows.remove((long) win);
+
+ if (skipPager)
+ {
+ return;
+ }
+
+ QValueList<KMiniPagerButton*>::ConstIterator it;
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+ for (it = m_desktops.begin(); it != itEnd; ++it)
+ {
+ if (onAllDesktops || onAllViewports || desktop == (*it)->desktop())
+ {
+ (*it)->windowsChanged();
+ }
+ }
+ }
+ else
+ {
+ m_windows.remove(win);
+ return;
+ }
+
+}
+
+void KMiniPager::slotWindowChanged( WId win , unsigned int properties )
+{
+ if ((properties & (NET::WMState | NET::XAWMState | NET::WMDesktop)) == 0 &&
+ (!desktopPreview() || (properties & NET::WMGeometry) == 0) &&
+ !(desktopPreview() && windowIcons() &&
+ (properties & NET::WMIcon | NET::WMIconName | NET::WMVisibleIconName) == 0))
+ {
+ return;
+ }
+
+ if (desktopPreview())
+ {
+ KWin::WindowInfo* inf = m_windows[win];
+ bool skipPager = inf->hasState(NET::SkipPager);
+ QMemArray<bool> old_shouldPaintWindow(m_desktops.size());
+ QValueList<KMiniPagerButton*>::ConstIterator it;
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+ int i = 0;
+ for ( it = m_desktops.begin(); it != itEnd; ++it)
+ {
+ old_shouldPaintWindow[i++] = (*it)->shouldPaintWindow(inf);
+ }
+
+ m_windows.remove(win);
+ inf = info(win);
+
+ if (inf->hasState(NET::SkipPager) || skipPager)
+ {
+ return;
+ }
+
+ for ( i = 0, it = m_desktops.begin(); it != itEnd; ++it)
+ {
+ if ( old_shouldPaintWindow[i++] || (*it)->shouldPaintWindow(inf))
+ {
+ (*it)->windowsChanged();
+ }
+ }
+ }
+ else
+ {
+ m_windows.remove(win);
+ return;
+ }
+}
+
+KWin::WindowInfo* KMiniPager::info( WId win )
+{
+ if (!m_windows[win])
+ {
+ KWin::WindowInfo* info = new KWin::WindowInfo( win,
+ NET::WMWindowType | NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMGeometry | NET::WMKDEFrameStrut, 0 );
+
+ m_windows.insert(win, info);
+ return info;
+ }
+
+ return m_windows[win];
+}
+
+KTextShadowEngine* KMiniPager::shadowEngine()
+{
+ if (!m_shadowEngine)
+ m_shadowEngine = new KTextShadowEngine();
+
+ return m_shadowEngine;
+}
+
+void KMiniPager::refresh()
+{
+ QValueList<KMiniPagerButton*>::ConstIterator it;
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+ for ( it = m_desktops.begin(); it != itEnd; ++it)
+ {
+ (*it)->update();
+ }
+}
+
+void KMiniPager::aboutToShowContextMenu()
+{
+ m_contextMenu->clear();
+
+ m_contextMenu->insertItem(SmallIcon("kpager"), i18n("&Launch Pager"), LaunchExtPager);
+ m_contextMenu->insertSeparator();
+
+ m_contextMenu->insertItem(i18n("&Rename Desktop \"%1\"")
+ .arg(kwin()->desktopName(m_rmbDesk)), RenameDesktop);
+ m_contextMenu->insertSeparator();
+
+ KPopupMenu* showMenu = new KPopupMenu(m_contextMenu);
+ showMenu->setCheckable(true);
+ showMenu->insertTitle(i18n("Pager Layout"));
+
+ QPopupMenu* rowMenu = new QPopupMenu(showMenu);
+ rowMenu->setCheckable(true);
+ rowMenu->insertItem(i18n("&Automatic"), 0 + rowOffset);
+ rowMenu->insertItem(i18n("one row or column", "&1"), 1 + rowOffset);
+ rowMenu->insertItem(i18n("two rows or columns", "&2"), 2 + rowOffset);
+ rowMenu->insertItem( i18n("three rows or columns", "&3"), 3 + rowOffset);
+ connect(rowMenu, SIGNAL(activated(int)), SLOT(contextMenuActivated(int)));
+ showMenu->insertItem((orientation()==Horizontal) ? i18n("&Rows"):
+ i18n("&Columns"),
+ rowMenu);
+
+ showMenu->insertItem(i18n("&Window Thumbnails"), WindowThumbnails);
+ showMenu->insertItem(i18n("&Window Icons"), WindowIcons);
+
+ showMenu->insertTitle(i18n("Text Label"));
+ showMenu->insertItem(i18n("Desktop N&umber"),
+ PagerSettings::EnumLabelType::LabelNumber + labelOffset);
+ showMenu->insertItem(i18n("Desktop N&ame"),
+ PagerSettings::EnumLabelType::LabelName + labelOffset);
+ showMenu->insertItem(i18n("N&o Label"),
+ PagerSettings::EnumLabelType::LabelNone + labelOffset);
+
+ showMenu->insertTitle(i18n("Background"));
+ showMenu->insertItem(i18n("&Elegant"),
+ PagerSettings::EnumBackgroundType::BgPlain + bgOffset);
+ showMenu->insertItem(i18n("&Transparent"),
+ PagerSettings::EnumBackgroundType::BgTransparent + bgOffset);
+ showMenu->insertItem(i18n("&Desktop Wallpaper"),
+ PagerSettings::EnumBackgroundType::BgLive + bgOffset);
+ connect(showMenu, SIGNAL(activated(int)), SLOT(contextMenuActivated(int)));
+ m_contextMenu->insertItem(i18n("&Pager Options"),showMenu);
+
+ m_contextMenu->insertItem(SmallIcon("configure"),
+ i18n("&Configure Desktops..."),
+ ConfigureDesktops);
+
+ rowMenu->setItemChecked(m_settings->numberOfRows() + rowOffset, true);
+ m_contextMenu->setItemChecked(m_settings->labelType() + labelOffset, showMenu);
+ m_contextMenu->setItemChecked(m_settings->backgroundType() + bgOffset, showMenu);
+
+ m_contextMenu->setItemChecked(WindowThumbnails, m_settings->preview());
+ m_contextMenu->setItemChecked(WindowIcons, m_settings->icons());
+ m_contextMenu->setItemEnabled(WindowIcons, m_settings->preview());
+ m_contextMenu->setItemEnabled(RenameDesktop,
+ m_settings->labelType() ==
+ PagerSettings::EnumLabelType::LabelName);
+}
+
+void KMiniPager::slotShowMenu(const QPoint& pos, int desktop)
+{
+ if (!m_contextMenu)
+ {
+ return;
+ }
+
+ m_rmbDesk = desktop;
+ m_contextMenu->exec(pos);
+ m_rmbDesk = -1;
+}
+
+void KMiniPager::contextMenuActivated(int result)
+{
+ if (result < 1)
+ {
+ return;
+ }
+
+ switch (result)
+ {
+ case LaunchExtPager:
+ showPager();
+ return;
+
+ case ConfigureDesktops:
+ kapp->startServiceByDesktopName("desktop");
+ return;
+
+ case RenameDesktop:
+ m_desktops[(m_rmbDesk == -1) ? m_curDesk - 1 : m_rmbDesk - 1]->rename();
+ return;
+ }
+
+ if (result >= rowOffset)
+ {
+ m_settings->setNumberOfRows(result - rowOffset);
+ resizeEvent(0);
+ }
+
+ switch (result)
+ {
+ case WindowThumbnails:
+ m_settings->setPreview(!m_settings->preview());
+ TaskManager::the()->trackGeometry();
+ break;
+
+ case WindowIcons:
+ m_settings->setIcons(!m_settings->icons());
+ break;
+
+ case PagerSettings::EnumBackgroundType::BgPlain + bgOffset:
+ m_settings->setBackgroundType(PagerSettings::EnumBackgroundType::BgPlain);
+ break;
+ case PagerSettings::EnumBackgroundType::BgTransparent + bgOffset:
+ m_settings->setBackgroundType(PagerSettings::EnumBackgroundType::BgTransparent);
+ break;
+ case PagerSettings::EnumBackgroundType::BgLive + bgOffset:
+ {
+ m_settings->setBackgroundType(PagerSettings::EnumBackgroundType::BgLive);
+ QValueList<KMiniPagerButton*>::ConstIterator it;
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+ for( it = m_desktops.begin(); it != itEnd; ++it )
+ {
+ (*it)->backgroundChanged();
+ }
+ break;
+ }
+
+ case PagerSettings::EnumLabelType::LabelNone + labelOffset:
+ m_settings->setLabelType(PagerSettings::EnumLabelType::LabelNone);
+ break;
+ case PagerSettings::EnumLabelType::LabelNumber + labelOffset:
+ m_settings->setLabelType(PagerSettings::EnumLabelType::LabelNumber);
+ break;
+ case PagerSettings::EnumLabelType::LabelName + labelOffset:
+ m_settings->setLabelType(PagerSettings::EnumLabelType::LabelName);
+ break;
+ }
+
+ m_settings->writeConfig();
+ updateGeometry();
+ refresh();
+}
+
+void KMiniPager::slotDesktopNamesChanged()
+{
+ QValueList<KMiniPagerButton*>::ConstIterator it = m_desktops.begin();
+ QValueList<KMiniPagerButton*>::ConstIterator itEnd = m_desktops.end();
+
+ for (int i = 1; it != itEnd; ++it, ++i)
+ {
+ QString name = m_kwin->desktopName(i);
+ (*it)->setDesktopName(name);
+ (*it)->repaint();
+ QToolTip::remove((*it));
+ QToolTip::add((*it), name);
+ }
+
+ updateLayout();
+}
+
+void KMiniPager::showPager()
+{
+ DCOPClient *dcop=kapp->dcopClient();
+
+ if (dcop->isApplicationRegistered("kpager"))
+ {
+ showKPager(true);
+ }
+ else
+ {
+ // Let's run kpager if it isn't running
+ connect( dcop, SIGNAL( applicationRegistered(const QCString &) ), this, SLOT(applicationRegistered(const QCString &)) );
+ dcop->setNotifications(true);
+ QString strAppPath(locate("exe", "kpager"));
+ if (!strAppPath.isEmpty())
+ {
+ KProcess process;
+ process << strAppPath;
+ process << "--hidden";
+ process.start(KProcess::DontCare);
+ }
+ }
+}
+
+void KMiniPager::showKPager(bool toggleShow)
+{
+ QPoint pt;
+ switch ( position() )
+ {
+ case pTop:
+ pt = mapToGlobal( QPoint(x(), y() + height()) );
+ break;
+ case pLeft:
+ pt = mapToGlobal( QPoint(x() + width(), y()) );
+ break;
+ case pRight:
+ case pBottom:
+ default:
+ pt=mapToGlobal( QPoint(x(), y()) );
+ }
+
+ DCOPClient *dcop=kapp->dcopClient();
+
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << pt.x() << pt.y() ;
+ if (toggleShow)
+ {
+ dcop->send("kpager", "KPagerIface", "toggleShow(int,int)", data);
+ }
+ else
+ {
+ dcop->send("kpager", "KPagerIface", "showAt(int,int)", data);
+ }
+}
+
+void KMiniPager::applicationRegistered( const QCString & appName )
+{
+ if (appName == "kpager")
+ {
+ disconnect( kapp->dcopClient(), SIGNAL( applicationRegistered(const QCString &) ),
+ this, SLOT(applicationRegistered(const QCString &)) );
+ showKPager(false);
+ }
+}
+
diff --git a/kicker/applets/minipager/pagerapplet.h b/kicker/applets/minipager/pagerapplet.h
new file mode 100644
index 000000000..f47b0411d
--- /dev/null
+++ b/kicker/applets/minipager/pagerapplet.h
@@ -0,0 +1,138 @@
+/*****************************************************************
+
+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 __MINIPAGER_H
+#define __MINIPAGER_H
+
+#include <qvaluelist.h>
+#include <qintdict.h>
+
+#include <kpanelapplet.h>
+#include <kwin.h>
+
+#include "pagerbutton.h"
+#include "pagersettings.h"
+
+class QButtonGroup;
+class QGridLayout;
+class QTimer;
+
+class KProcess;
+class KWinModule;
+class KTextShadowEngine;
+class KSelectionOwner;
+
+class PagerSettings;
+
+class KMiniPager : public KPanelApplet
+{
+ Q_OBJECT
+
+public:
+ KMiniPager(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+
+ virtual ~KMiniPager();
+
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+
+ KWin::WindowInfo* info( WId win );
+ KWinModule* kwin() { return m_kwin; }
+ KTextShadowEngine* shadowEngine();
+
+ void setActive( WId active ) { m_activeWindow = active; }
+ WId activeWindow() { return m_activeWindow; }
+
+ enum ConfigOptions { LaunchExtPager = 96, WindowThumbnails,
+ WindowIcons, ConfigureDesktops, RenameDesktop };
+ int labelType() const { return m_settings->labelType(); }
+
+ int bgType() const { return m_settings->backgroundType(); }
+
+ bool desktopPreview() const { return m_settings->preview(); }
+ bool windowIcons() const { return m_settings->icons(); }
+
+ Orientation orientation() const { return KPanelApplet::orientation(); }
+ Direction popupDirection() { return KPanelApplet::popupDirection(); }
+
+ void emitRequestFocus() { emit requestFocus(); }
+
+ QPoint clickPos;
+
+public slots:
+ void slotSetDesktop(int desktop);
+ void slotSetDesktopViewport(int desktop, const QPoint& viewport);
+ void slotSetDesktopCount(int count);
+ void slotButtonSelected(int desk );
+ void slotActiveWindowChanged( WId win );
+ void slotWindowAdded( WId );
+ void slotWindowRemoved( WId );
+ void slotWindowChanged( WId, unsigned int );
+ void slotShowMenu( const QPoint&, int );
+ void slotDesktopNamesChanged();
+ void slotBackgroundChanged( int );
+
+ void refresh();
+
+protected:
+ void drawButtons();
+ void startDrag( const QPoint &point );
+
+ void updateDesktopLayout(int,int,int);
+ void resizeEvent(QResizeEvent*);
+ void wheelEvent( QWheelEvent* e );
+ void showKPager(bool toggleShow);
+
+protected slots:
+ void showPager();
+ void applicationRegistered(const QCString &appName);
+ void aboutToShowContextMenu();
+ void contextMenuActivated(int);
+
+private:
+ QValueList<KMiniPagerButton*> m_desktops;
+ int m_curDesk;
+ int m_rmbDesk;
+
+ QIntDict<KWin::WindowInfo> m_windows;
+ WId m_activeWindow;
+
+ QButtonGroup *m_group;
+
+ QGridLayout *m_layout;
+ bool m_useViewports;
+ int desktopLayoutOrientation;
+ int desktopLayoutX;
+ int desktopLayoutY;
+ KSelectionOwner* m_desktopLayoutOwner;
+
+ KWinModule *m_kwin;
+ KTextShadowEngine* m_shadowEngine;
+
+ QPopupMenu *m_contextMenu;
+ PagerSettings *m_settings;
+};
+
+#endif
+
diff --git a/kicker/applets/minipager/pagerbutton.cpp b/kicker/applets/minipager/pagerbutton.cpp
new file mode 100644
index 000000000..b4e268b8e
--- /dev/null
+++ b/kicker/applets/minipager/pagerbutton.cpp
@@ -0,0 +1,824 @@
+/*****************************************************************
+
+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 <qcursor.h>
+#include <qdrawutil.h>
+#include <qlineedit.h>
+#include <qpainter.h>
+#include <qpopupmenu.h>
+#include <qstylesheet.h>
+
+#include <netwm.h>
+#include <dcopclient.h>
+
+#include <kwinmodule.h>
+#include <ksharedpixmap.h>
+#include <kpixmapio.h>
+#include <kpixmapeffect.h>
+#include <kstringhandler.h>
+#include <kiconloader.h>
+
+#include "global.h"
+#include "kickertip.h"
+#include "kickerSettings.h"
+#include "kshadowengine.h"
+#include "paneldrag.h"
+
+#include "pagerapplet.h"
+#include "pagerbutton.h"
+#include "pagerbutton.moc"
+#include "pagersettings.h"
+
+#ifdef FocusOut
+#undef FocusOut
+#endif
+
+KSharedPixmap* KMiniPagerButton::s_commonSharedPixmap;
+KPixmap* KMiniPagerButton::s_commonBgPixmap;
+
+KMiniPagerButton::KMiniPagerButton(int desk, bool useViewPorts, const QPoint& viewport,
+ KMiniPager *parent, const char *name)
+ : QButton(parent, name),
+ m_pager(parent),
+ m_desktop(desk),
+ m_useViewports(useViewPorts),
+ m_viewport(viewport),
+ m_lineEdit(0),
+ m_sharedPixmap(0),
+ m_bgPixmap(0),
+ m_isCommon(false),
+ m_currentWindow(0),
+ m_inside(false)
+{
+ setToggleButton(true);
+ setAcceptDrops(true);
+ setWFlags(WNoAutoErase);
+
+ setBackgroundOrigin(AncestorOrigin);
+ installEventFilter(KickerTip::the());
+
+ m_desktopName = m_pager->kwin()->desktopName(m_desktop);
+
+ connect(this, SIGNAL(clicked()), SLOT(slotClicked()));
+ connect(this, SIGNAL(toggled(bool)), SLOT(slotToggled(bool)));
+ connect(&m_dragSwitchTimer, SIGNAL(timeout()), this, SLOT(slotDragSwitch()));
+ connect(&m_updateCompressor, SIGNAL(timeout()), this, SLOT(update()));
+
+ if (m_pager->desktopPreview())
+ {
+ setMouseTracking(true);
+ }
+ loadBgPixmap();
+}
+
+KMiniPagerButton::~KMiniPagerButton()
+{
+ delete m_sharedPixmap;
+ delete m_bgPixmap;
+}
+
+QRect KMiniPagerButton::mapGeometryToViewport(const KWin::WindowInfo& info) const
+{
+ if (!m_useViewports)
+ return info.frameGeometry();
+
+ // ### fix vertically layouted viewports
+ QRect _r(info.frameGeometry());
+ QPoint vx(m_pager->kwin()->currentViewport(m_pager->kwin()->currentDesktop()));
+
+ _r.moveBy( - (m_desktop - vx.x()) * QApplication::desktop()->width(),
+ 0);
+
+ if ((info.state() & NET::Sticky))
+ {
+ _r.moveTopLeft(QPoint(_r.x() % QApplication::desktop()->width(),
+ _r.y() % QApplication::desktop()->height()));
+
+ }
+
+ return _r;
+}
+
+QPoint KMiniPagerButton::mapPointToViewport(const QPoint& _p) const
+{
+ if (!m_useViewports) return _p;
+
+ QPoint vx(m_pager->kwin()->currentViewport(m_pager->kwin()->currentDesktop()));
+
+ // ### fix vertically layouted viewports
+ QPoint p(_p);
+ p.setX(p.x() + (m_desktop - vx.x()) * QApplication::desktop()->width());
+ return p;
+}
+
+bool KMiniPagerButton::shouldPaintWindow( KWin::WindowInfo *info ) const
+{
+ if (!info)
+ return false;
+
+// if (info->mappingState != NET::Visible)
+// return false;
+
+ NET::WindowType type = info->windowType( NET::NormalMask | NET::DesktopMask
+ | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
+ | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
+
+ if (type == NET::Desktop || type == NET::Dock || type == NET::TopMenu)
+ return false;
+
+ if (!m_useViewports && !info->isOnDesktop(m_desktop))
+ return false;
+
+ if (m_useViewports) {
+ QRect r = mapGeometryToViewport(*info);
+
+ if (!info->hasState(NET::Sticky) &&
+ !QApplication::desktop()->geometry().contains(r.topLeft()) &&
+ !QApplication::desktop()->geometry().contains(r.topRight()))
+ return false;
+ }
+
+ if (info->state() & NET::SkipPager || info->state() & NET::Shaded )
+ return false;
+
+ if (info->win() == m_pager->winId())
+ return false;
+
+ if ( info->isMinimized() )
+ return false;
+
+ return true;
+}
+
+void KMiniPagerButton::resizeEvent(QResizeEvent *ev)
+{
+ if (m_lineEdit)
+ {
+ m_lineEdit->setGeometry(rect());
+ }
+
+ delete m_bgPixmap;
+ m_bgPixmap = 0;
+
+ QButton::resizeEvent(ev);
+}
+
+void KMiniPagerButton::windowsChanged()
+{
+ m_currentWindow = 0;
+
+ if (!m_updateCompressor.isActive())
+ {
+ m_updateCompressor.start(50, true);
+ }
+}
+
+void KMiniPagerButton::backgroundChanged()
+{
+ delete s_commonSharedPixmap;
+ s_commonSharedPixmap = 0;
+ delete s_commonBgPixmap;
+ s_commonBgPixmap = 0;
+ loadBgPixmap();
+}
+
+void KMiniPagerButton::loadBgPixmap()
+{
+ if (m_pager->bgType() != PagerSettings::EnumBackgroundType::BgLive)
+ return; // not needed
+
+ DCOPClient *client = kapp->dcopClient();
+ if (!client->isAttached())
+ {
+ client->attach();
+ }
+
+ QCString kdesktop_name;
+ int screen_number = DefaultScreen(qt_xdisplay());
+ if (screen_number == 0)
+ kdesktop_name = "kdesktop";
+ else
+ kdesktop_name.sprintf("kdesktop-screen-%d", screen_number);
+
+ QByteArray data, replyData;
+ QCString replyType;
+ if (client->call(kdesktop_name, "KBackgroundIface", "isCommon()",
+ data, replyType, replyData))
+ {
+ if (replyType == "bool")
+ {
+ QDataStream reply(replyData, IO_ReadOnly);
+ reply >> m_isCommon;
+ }
+ }
+
+ if (m_isCommon)
+ {
+ if (s_commonBgPixmap)
+ { // pixmap is already ready, just use it
+ backgroundLoaded( true );
+ return;
+ }
+ else if (s_commonSharedPixmap)
+ { // other button is already fetching the pixmap
+ connect(s_commonSharedPixmap, SIGNAL(done(bool)),
+ SLOT(backgroundLoaded(bool)));
+ return;
+ }
+ }
+
+ QDataStream args( data, IO_WriteOnly );
+ args << 1;
+ client->send(kdesktop_name, "KBackgroundIface", "setExport(int)", data);
+
+ if (m_isCommon)
+ {
+ if (!s_commonSharedPixmap)
+ {
+ s_commonSharedPixmap = new KSharedPixmap;
+ connect(s_commonSharedPixmap, SIGNAL(done(bool)),
+ SLOT(backgroundLoaded(bool)));
+ }
+ s_commonSharedPixmap->loadFromShared(QString("DESKTOP1"));
+ }
+ else
+ {
+ if (!m_sharedPixmap)
+ {
+ m_sharedPixmap = new KSharedPixmap;
+ connect(m_sharedPixmap, SIGNAL(done(bool)),
+ SLOT(backgroundLoaded(bool)));
+ }
+ m_sharedPixmap->loadFromShared(QString("DESKTOP%1").arg(m_desktop));
+ }
+}
+
+static QPixmap scalePixmap(const QPixmap &pixmap, int width, int height)
+{
+ if (pixmap.width()>100)
+ {
+ KPixmapIO io;
+ QImage img( io.convertToImage( pixmap ) );
+ return io.convertToPixmap( img.smoothScale( width, height ) );
+ }
+
+ QImage img( pixmap.convertToImage().smoothScale( width, height ) );
+ QPixmap pix;
+ pix.convertFromImage( img );
+
+ return pix;
+}
+
+void KMiniPagerButton::backgroundLoaded( bool loaded )
+{
+ if (loaded)
+ {
+ if (!m_bgPixmap)
+ {
+ m_bgPixmap = new KPixmap;
+ }
+ if (m_isCommon)
+ {
+ if (!s_commonBgPixmap)
+ {
+ s_commonBgPixmap = new KPixmap;
+ *s_commonBgPixmap = scalePixmap(*s_commonSharedPixmap, width(), height());
+ s_commonSharedPixmap->deleteLater(); // let others get the signal too
+ s_commonSharedPixmap = 0;
+ }
+ *m_bgPixmap = *s_commonBgPixmap;
+ }
+ else
+ {
+ *m_bgPixmap = scalePixmap(*m_sharedPixmap, width(), height());
+ delete m_sharedPixmap;
+ m_sharedPixmap = 0L;
+ }
+
+ update();
+ }
+ else
+ {
+ kdWarning() << "Error getting the background\n";
+ }
+}
+
+void KMiniPagerButton::enterEvent(QEvent *)
+{
+ m_inside = true;
+ update();
+}
+
+void KMiniPagerButton::leaveEvent(QEvent *)
+{
+ m_inside = false;
+ update();
+}
+
+void KMiniPagerButton::drawButton(QPainter *bp)
+{
+ int w = width();
+ int h = height();
+ bool on = isOn();
+ bool down = isDown();
+
+ QBrush background;
+
+ bool liveBkgnd = m_pager->bgType() == PagerSettings::EnumBackgroundType::BgLive;
+ bool transparent = m_pager->bgType() == PagerSettings::EnumBackgroundType::BgTransparent;
+
+ // background
+
+ if (backgroundPixmap())
+ {
+ QPoint pt = backgroundOffset();
+ bp->drawTiledPixmap(0, 0, width(), height(), *backgroundPixmap(), pt.x(), pt.y());
+ }
+ else
+ {
+ bp->fillRect(0, 0, width(), height(), paletteBackgroundColor());
+ }
+
+
+ // desktop background
+
+ if (liveBkgnd)
+ {
+ if (m_bgPixmap && !m_bgPixmap->isNull())
+ {
+ if (on)
+ {
+ KPixmap tmp = *m_bgPixmap;
+ KPixmapEffect::intensity(tmp, 0.33);
+ bp->drawPixmap(0, 0, tmp);
+ }
+ else
+ {
+ bp->drawPixmap(0, 0, *m_bgPixmap);
+ }
+ }
+ else
+ {
+ liveBkgnd = false;
+ }
+ }
+
+ if (!liveBkgnd)
+ {
+ if (transparent)
+ {
+ // transparent windows get an 1 pixel frame...
+ if (on)
+ {
+ bp->setPen(colorGroup().midlight());
+ }
+ else if (down)
+ {
+ bp->setPen(KickerLib::blendColors(colorGroup().mid(),
+ colorGroup().midlight()));
+ }
+ else
+ {
+ bp->setPen(colorGroup().dark());
+ }
+
+ bp->drawRect(0, 0, w, h);
+ }
+ else
+ {
+ QBrush background;
+
+ if (on)
+ {
+ background = colorGroup().brush(QColorGroup::Midlight);
+ }
+ else if (down)
+ {
+ background = KickerLib::blendColors(colorGroup().mid(),
+ colorGroup().midlight());
+ }
+ else
+ {
+ background = colorGroup().brush(QColorGroup::Mid);
+ }
+
+ bp->fillRect(0, 0, w, h, background);
+ }
+ }
+
+ // window preview...
+ if (m_pager->desktopPreview())
+ {
+ KWinModule* kwin = m_pager->kwin();
+ KWin::WindowInfo *info = 0;
+ int dw = QApplication::desktop()->width();
+ int dh = QApplication::desktop()->height();
+
+ QValueList<WId> windows = kwin->stackingOrder();
+ QValueList<WId>::const_iterator itEnd = windows.constEnd();
+ for (QValueList<WId>::ConstIterator it = windows.constBegin(); it != itEnd; ++it)
+ {
+ info = m_pager->info(*it);
+
+ if (shouldPaintWindow(info))
+ {
+ QRect r = mapGeometryToViewport(*info);
+ r = QRect(r.x() * width() / dw, 2 + r.y() * height() / dh,
+ r.width() * width() / dw, r.height() * height() / dh);
+
+ if (kwin->activeWindow() == info->win())
+ {
+ QBrush brush = colorGroup().brush(QColorGroup::Highlight);
+ qDrawShadeRect(bp, r, colorGroup(), false, 1, 0, &brush);
+ }
+ else
+ {
+ QBrush brush = colorGroup().brush(QColorGroup::Button);
+
+ if (on)
+ {
+ brush.setColor(brush.color().light(120));
+ }
+
+ bp->fillRect(r, brush);
+ qDrawShadeRect(bp, r, colorGroup(), true, 1, 0);
+ }
+
+ if (m_pager->windowIcons() && r.width() > 15 && r.height() > 15)
+ {
+ QPixmap icon = KWin::icon(*it, 16, 16, true);
+ if (!icon.isNull())
+ {
+ bp->drawPixmap(r.left() + ((r.width() - 16) / 2),
+ r.top() + ((r.height() - 16) / 2),
+ icon);
+ }
+ }
+ }
+ }
+ }
+
+ if (liveBkgnd)
+ {
+ // draw a little border around the individual buttons
+ // makes it look a bit more finished.
+ if (on)
+ {
+ bp->setPen(colorGroup().midlight());
+ }
+ else
+ {
+ bp->setPen(colorGroup().mid());
+ }
+
+ bp->drawRect(0, 0, w, h);
+ }
+
+ if (m_pager->labelType() != PagerSettings::EnumLabelType::LabelNone)
+ {
+ QString label = (m_pager->labelType() == PagerSettings::EnumLabelType::LabelNumber) ?
+ QString::number(m_desktop) : m_desktopName;
+
+ if (transparent || liveBkgnd)
+ {
+ bp->setPen(on ? colorGroup().midlight() : colorGroup().buttonText());
+ m_pager->shadowEngine()->drawText(*bp, QRect(0, 0, w, h), AlignCenter, label, size());
+ }
+ else
+ bp->drawText(0, 0, w, h, AlignCenter, label);
+ }
+
+ if (m_inside)
+ KickerLib::drawBlendedRect(bp, QRect(1, 1, width() - 2, height() - 2), colorGroup().foreground());
+}
+
+void KMiniPagerButton::mousePressEvent(QMouseEvent * e)
+{
+ if (e->button() == RightButton)
+ {
+ // prevent LMB down -> RMB down -> LMB up sequence
+ if ((e->state() & MouseButtonMask ) == NoButton)
+ {
+ emit showMenu(e->globalPos(), m_desktop);
+ return;
+ }
+ }
+
+ if (m_pager->desktopPreview())
+ {
+ m_pager->clickPos = e->pos();
+ }
+
+ QButton::mousePressEvent(e);
+}
+
+void KMiniPagerButton::mouseReleaseEvent(QMouseEvent* e)
+{
+ m_pager->clickPos = QPoint();
+ QButton::mouseReleaseEvent(e);
+}
+
+void KMiniPagerButton::mouseMoveEvent(QMouseEvent* e)
+{
+ if (!m_pager->desktopPreview())
+ {
+ return;
+ }
+
+ int dw = QApplication::desktop()->width();
+ int dh = QApplication::desktop()->height();
+ int w = width();
+ int h = height();
+
+ QPoint pos(m_pager->clickPos.isNull() ? mapFromGlobal(QCursor::pos()) : m_pager->clickPos);
+ QPoint p = mapPointToViewport(QPoint(pos.x() * dw / w, pos.y() * dh / h));
+
+ Task::Ptr wasWindow = m_currentWindow;
+ m_currentWindow = TaskManager::the()->findTask(m_useViewports ? 1 : m_desktop, p);
+
+ if (wasWindow != m_currentWindow)
+ {
+ KickerTip::Client::updateKickerTip();
+ }
+
+ if (m_currentWindow && !m_pager->clickPos.isNull() &&
+ (m_pager->clickPos - e->pos()).manhattanLength() > KGlobalSettings::dndEventDelay())
+ {
+ QRect r = m_currentWindow->geometry();
+
+ // preview window height, window width
+ int ww = r.width() * w / dw;
+ int wh = r.height() * h / dh;
+ QPixmap windowImage(ww, wh);
+ QPainter bp(&windowImage, this);
+
+ bp.setPen(colorGroup().foreground());
+ bp.drawRect(0, 0, ww, wh);
+ bp.fillRect(1, 1, ww - 2, wh - 2, colorGroup().background());
+
+ Task::List tasklist;
+ tasklist.append(m_currentWindow);
+ TaskDrag* drag = new TaskDrag(tasklist, this);
+ QPoint offset(m_pager->clickPos.x() - (r.x() * w / dw),
+ m_pager->clickPos.y() - (r.y() * h / dh));
+ drag->setPixmap(windowImage, offset);
+ drag->dragMove();
+
+ if (isDown())
+ {
+ setDown(false);
+ }
+
+ m_pager->clickPos = QPoint();
+ }
+}
+
+void KMiniPagerButton::dragEnterEvent(QDragEnterEvent* e)
+{
+ if (PanelDrag::canDecode(e))
+ {
+ // ignore container drags
+ return;
+ }
+ else if (TaskDrag::canDecode(e))
+ {
+ // if it's a task drag don't switch the desktop, just accept it
+ e->accept();
+ setDown(true);
+ }
+ else
+ {
+ // if a dragitem is held for over a pager button for two seconds,
+ // activate corresponding desktop
+ m_dragSwitchTimer.start(1000, true);
+ QButton::dragEnterEvent(e);
+ }
+}
+
+void KMiniPagerButton::dropEvent(QDropEvent* e)
+{
+ if (TaskDrag::canDecode(e))
+ {
+ e->accept();
+ Task::List tasks(TaskDrag::decode(e));
+
+ if ((m_useViewports || e->source() == this) && tasks.count() == 1)
+ {
+ Task::Ptr task = tasks[0];
+ int dw = QApplication::desktop()->width();
+ int dh = QApplication::desktop()->height();
+ int w = width();
+ int h = height();
+ QRect location = mapGeometryToViewport(task->info());
+ QPoint pos = mapPointToViewport(e->pos());
+ int deltaX = pos.x() - m_pager->clickPos.x();
+ int deltaY = pos.y() - m_pager->clickPos.y();
+
+ if (abs(deltaX) < 3)
+ {
+ deltaX = 0;
+ }
+ else
+ {
+ deltaX = deltaX * dw / w;
+ }
+
+ if (abs(deltaY) < 3)
+ {
+ deltaY = 0;
+ }
+ else
+ {
+ deltaY = deltaY * dh / h;
+ }
+
+ location.moveBy(deltaX, deltaY);
+
+ XMoveWindow(x11Display(), task->window(), location.x(), location.y());
+ if ((e->source() != this || !task->isOnAllDesktops()) &&
+ task->desktop() != m_desktop)
+ {
+ task->toDesktop(m_desktop);
+ }
+ }
+ else
+ {
+ Task::List::iterator itEnd = tasks.end();
+ for (Task::List::iterator it = tasks.begin(); it != itEnd; ++it)
+ {
+ (*it)->toDesktop(m_desktop);
+ }
+ }
+
+ setDown(false);
+ }
+
+ QButton::dropEvent( e );
+}
+
+void KMiniPagerButton::enabledChange( bool oldEnabled )
+{
+ if (m_pager->bgType() == PagerSettings::EnumBackgroundType::BgLive)
+ {
+ m_pager->refresh();
+ }
+
+ QButton::enabledChange(oldEnabled);
+}
+
+void KMiniPagerButton::dragLeaveEvent( QDragLeaveEvent* e )
+{
+ m_dragSwitchTimer.stop();
+
+ if (m_pager->kwin()->currentDesktop() != m_desktop)
+ {
+ setDown(false);
+ }
+
+ QButton::dragLeaveEvent( e );
+}
+
+void KMiniPagerButton::slotDragSwitch()
+{
+ emit buttonSelected(m_desktop);
+}
+
+void KMiniPagerButton::slotClicked()
+{
+ emit buttonSelected(m_desktop);
+}
+
+void KMiniPagerButton::rename()
+{
+ if ( !m_lineEdit ) {
+ m_lineEdit = new QLineEdit( this );
+ connect( m_lineEdit, SIGNAL( returnPressed() ), m_lineEdit, SLOT( hide() ) );
+ m_lineEdit->installEventFilter( this );
+ }
+ m_lineEdit->setGeometry( rect() );
+ m_lineEdit->setText(m_desktopName);
+ m_lineEdit->show();
+ m_lineEdit->setFocus();
+ m_lineEdit->selectAll();
+ m_pager->emitRequestFocus();
+}
+
+void KMiniPagerButton::slotToggled( bool b )
+{
+ if ( !b && m_lineEdit )
+ {
+ m_lineEdit->hide();
+ }
+}
+
+bool KMiniPagerButton::eventFilter( QObject *o, QEvent * e)
+{
+ if (o && o == m_lineEdit &&
+ (e->type() == QEvent::FocusOut || e->type() == QEvent::Hide))
+ {
+ m_pager->kwin()->setDesktopName( m_desktop, m_lineEdit->text() );
+ m_desktopName = m_lineEdit->text();
+ QTimer::singleShot( 0, m_lineEdit, SLOT( deleteLater() ) );
+ m_lineEdit = 0;
+ return true;
+ }
+
+ return QButton::eventFilter(o, e);
+}
+
+void KMiniPagerButton::updateKickerTip(KickerTip::Data &data)
+{
+ Task::Dict tasks = TaskManager::the()->tasks();
+ Task::Dict::iterator taskEnd = tasks.end();
+ uint taskCounter = 0;
+ uint taskLimiter = 4;
+ QString lastWindow;
+
+ for (Task::Dict::iterator it = tasks.begin(); it != taskEnd; ++it)
+ {
+ if (it.data()->desktop() == m_desktop || it.data()->isOnAllDesktops())
+ {
+ taskCounter++;
+ if (taskCounter > taskLimiter)
+ {
+ lastWindow = it.data()->visibleName();
+ continue;
+ }
+
+ QPixmap winIcon = it.data()->pixmap();
+ QString bullet;
+
+ if (winIcon.isNull())
+ {
+ bullet = "&bull;";
+ }
+ else
+ {
+ data.mimeFactory->setPixmap(QString::number(taskCounter), winIcon);
+ bullet = QString("<img src=\"%1\" width=\"%2\" height=\"%3\">").arg(taskCounter).arg(16).arg(16);
+ }
+
+ QString name = KStringHandler::cPixelSqueeze(it.data()->visibleName(), fontMetrics(), 400);
+ name = QStyleSheet::escape(name);
+ if (it.data() == m_currentWindow)
+ {
+ data.subtext.append(QString("<br>%1&nbsp; <u>").arg(bullet));
+ data.subtext.append(name).append("</u>");
+ }
+ else
+ {
+ data.subtext.append(QString("<br>%1&nbsp; ").arg(bullet));
+ data.subtext.append(name);
+ }
+ }
+ }
+
+ if (taskCounter > taskLimiter)
+ {
+ if (taskCounter - taskLimiter == 1)
+ {
+ data.subtext.append("<br>&bull; ").append(lastWindow);
+ }
+ else
+ {
+ data.subtext.append("<br>&bull; <i>")
+ .append(i18n("and 1 other", "and %n others", taskCounter - taskLimiter))
+ .append("</i>");
+ }
+ }
+
+ if (taskCounter > 0)
+ {
+ data.subtext.prepend(i18n("One window:",
+ "%n windows:",
+ taskCounter));
+ }
+
+ data.duration = 4000;
+ data.icon = DesktopIcon("window_list", KIcon::SizeMedium);
+ data.message = QStyleSheet::escape(m_desktopName);
+ data.direction = m_pager->popupDirection();
+}
+
diff --git a/kicker/applets/minipager/pagerbutton.h b/kicker/applets/minipager/pagerbutton.h
new file mode 100644
index 000000000..1547201e0
--- /dev/null
+++ b/kicker/applets/minipager/pagerbutton.h
@@ -0,0 +1,111 @@
+/*****************************************************************
+
+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 __MINIPAGERBUTTON_H
+#define __MINIPAGERBUTTON_H
+
+#include <qbutton.h>
+
+#include "taskmanager.h"
+#include "kickertip.h"
+
+class KPixmap;
+class KWinModule;
+class KMiniPager;
+class KSharedPixmap;
+class QLineEdit;
+
+class KMiniPagerButton : public QButton, public KickerTip::Client
+{
+ Q_OBJECT
+public:
+ KMiniPagerButton(int desk, bool useViewports, const QPoint& viewport,
+ KMiniPager *parent=0, const char *name=0);
+ ~KMiniPagerButton();
+
+ int desktop() { return m_desktop; }
+
+ QString desktopName() { return m_desktopName; }
+ void setDesktopName( QString name ) { m_desktopName = name; }
+
+ void rename();
+ void backgroundChanged();
+ void windowsChanged();
+
+ bool shouldPaintWindow( KWin::WindowInfo *info ) const;
+
+signals:
+ void buttonSelected( int desk );
+ void showMenu( const QPoint&, int );
+
+protected:
+ void drawButton(QPainter *);
+ void enterEvent(QEvent*);
+ void leaveEvent(QEvent*);
+ void resizeEvent(QResizeEvent *ev);
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void dragEnterEvent(QDragEnterEvent* e);
+ void dragLeaveEvent(QDragLeaveEvent* e);
+ void enabledChange( bool oldEnabled );
+ void dropEvent(QDropEvent* e);
+
+ bool eventFilter(QObject*, QEvent*);
+ void updateKickerTip(KickerTip::Data &data);
+
+private slots:
+ void slotToggled(bool);
+ void slotClicked();
+ void slotDragSwitch();
+
+ void backgroundLoaded( bool loaded );
+
+private:
+ void loadBgPixmap();
+ QRect mapGeometryToViewport(const KWin::WindowInfo&) const;
+ QPoint mapPointToViewport(const QPoint&) const;
+
+ KMiniPager* m_pager;
+ int m_desktop;
+ bool m_useViewports;
+ QString m_desktopName;
+ QPoint m_viewport;
+
+ QTimer m_updateCompressor;
+ QTimer m_dragSwitchTimer;
+ Task::Ptr m_dragging;
+
+ QLineEdit* m_lineEdit;
+
+ KSharedPixmap *m_sharedPixmap;
+ KPixmap *m_bgPixmap;
+ static KSharedPixmap *s_commonSharedPixmap;
+ static KPixmap *s_commonBgPixmap;
+ bool m_isCommon;
+
+ Task::Ptr m_currentWindow;
+ bool m_inside;
+};
+
+#endif
diff --git a/kicker/applets/minipager/pagersettings.kcfg b/kicker/applets/minipager/pagersettings.kcfg
new file mode 100644
index 000000000..8a26bdc86
--- /dev/null
+++ b/kicker/applets/minipager/pagersettings.kcfg
@@ -0,0 +1,58 @@
+<?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" >
+
+ <kcfgfile arg="true"/>
+ <group name="General">
+ <entry key="LabelType" type="Enum">
+ <choices>
+ <choice name="LabelNone">
+ <label>None</label>
+ </choice>
+ <choice name="LabelName">
+ <label>Name</label>
+ </choice>
+ <choice name="LabelNumber">
+ <label>Number</label>
+ </choice>
+ </choices>
+ <default>LabelNumber</default>
+ <label>Virtual desktop label type</label>
+ </entry>
+
+ <entry key="BackgroundType" type="Enum">
+ <choices>
+ <choice name="BgPlain">
+ <label>Plain</label>
+ </choice>
+ <choice name="BgTransparent">
+ <label>Transparent</label>
+ </choice>
+ <choice name="BgLive">
+ <label>Live</label>
+ </choice>
+ </choices>
+ <default>BgPlain</default>
+ <label>Virtual desktop background type</label>
+ </entry>
+
+ <entry name="NumberOfRows" type="Int">
+ <label>Number of rows to arrange the desktop previews into</label>
+ <default>0</default>
+ <min>0</min>
+ <max>4</max>
+ </entry>
+
+ <entry name="Preview" type="Bool">
+ <label>Show desktop preview?</label>
+ <default>true</default>
+ </entry>
+
+ <entry name="Icons" type="Bool">
+ <label>Show window icons in previews?</label>
+ <default>true</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kicker/applets/minipager/pagersettings.kcfgc b/kicker/applets/minipager/pagersettings.kcfgc
new file mode 100644
index 000000000..47a1915f4
--- /dev/null
+++ b/kicker/applets/minipager/pagersettings.kcfgc
@@ -0,0 +1,4 @@
+File=pagersettings.kcfg
+Singleton=false
+ClassName=PagerSettings
+Mutators=true
diff --git a/kicker/applets/naughty/Makefile.am b/kicker/applets/naughty/Makefile.am
new file mode 100644
index 000000000..533df19c3
--- /dev/null
+++ b/kicker/applets/naughty/Makefile.am
@@ -0,0 +1,30 @@
+pic_DATA = naughty-happy.png naughty-sad.png
+picdir = $(kde_datadir)/naughtyapplet/pics
+
+INCLUDES = -I$(top_srcdir)/kicker/libkicker $(all_includes)
+
+kde_module_LTLIBRARIES = naughty_panelapplet.la
+
+naughty_panelapplet_la_SOURCES = \
+ NaughtyProcessMonitor.cpp \
+ NaughtyConfigDialog.cpp \
+ NaughtyApplet.cpp
+
+METASOURCES = AUTO
+
+noinst_HEADERS = \
+ NaughtyProcessMonitor.h \
+ NaughtyConfigDialog.h \
+ NaughtyApplet.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = naughtyapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+naughty_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+naughty_panelapplet_la_LIBADD = ../../libkicker/libkickermain.la $(LIB_KDEUI) $(LIB_KVM)
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/naughtyapplet.pot
+
diff --git a/kicker/applets/naughty/NaughtyApplet.cpp b/kicker/applets/naughty/NaughtyApplet.cpp
new file mode 100644
index 000000000..c256aa36f
--- /dev/null
+++ b/kicker/applets/naughty/NaughtyApplet.cpp
@@ -0,0 +1,223 @@
+/*
+ Naughty applet - Runaway process monitor for the KDE panel
+
+ Copyright 2000 Rik Hemsley (rikkus) <[email protected]>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "NaughtyApplet.h"
+#include "NaughtyProcessMonitor.h"
+#include "NaughtyConfigDialog.h"
+
+#include <qmessagebox.h>
+#include <qtoolbutton.h>
+#include <qlayout.h>
+
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kaboutapplication.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kmessagebox.h>
+#include <qpushbutton.h>
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget * parent, const QString & configFile)
+ {
+ KGlobal::locale()->insertCatalogue("naughtyapplet");
+
+ return new NaughtyApplet
+ (
+ configFile,
+ KPanelApplet::Normal,
+ KPanelApplet::About | KPanelApplet::Preferences,
+ parent,
+ "naughtyapplet"
+ );
+ }
+}
+
+NaughtyApplet::NaughtyApplet
+(
+ const QString & configFile,
+ Type t,
+ int actions,
+ QWidget * parent,
+ const char * name
+)
+ : KPanelApplet(configFile, t, actions, parent, name)
+{
+ KGlobal::iconLoader()->addAppDir("naughtyapplet");
+ setBackgroundOrigin( AncestorOrigin );
+
+ button_ = new SimpleButton(this);
+ button_->setFixedSize(20, 20);
+
+ QVBoxLayout * layout = new QVBoxLayout(this);
+ layout->addWidget(button_);
+
+ monitor_ = new NaughtyProcessMonitor(2, 20, this);
+
+ connect
+ (
+ button_, SIGNAL(clicked()),
+ this, SLOT(slotPreferences())
+ );
+
+ connect
+ (
+ monitor_, SIGNAL(runawayProcess(ulong, const QString &)),
+ this, SLOT(slotWarn(ulong, const QString &))
+ );
+
+ connect
+ (
+ monitor_, SIGNAL(load(uint)),
+ this, SLOT(slotLoad(uint))
+ );
+
+ loadSettings();
+
+ monitor_->start();
+}
+
+NaughtyApplet::~NaughtyApplet()
+{
+ KGlobal::locale()->removeCatalogue("naughtyapplet");
+}
+
+ void
+NaughtyApplet::slotWarn(ulong pid, const QString & name)
+{
+ if (ignoreList_.contains(name))
+ return;
+
+ QString s = i18n("A program called '%1' is slowing down the others "
+ "on your machine. It may have a bug that is causing "
+ "this, or it may just be busy.\n"
+ "Would you like to try to stop the program?");
+
+ int retval = KMessageBox::warningYesNo(this, s.arg(name), QString::null, i18n("Stop"), i18n("Keep Running"));
+
+ if (KMessageBox::Yes == retval)
+ monitor_->kill(pid);
+ else
+ {
+ s = i18n("In future, should busy programs called '%1' be ignored?");
+
+ retval = KMessageBox::questionYesNo(this, s.arg(name), QString::null, i18n("Ignore"), i18n("Do Not Ignore"));
+
+ if (KMessageBox::Yes == retval)
+ {
+ ignoreList_.append(name);
+ config()->writeEntry("IgnoreList", ignoreList_);
+ config()->sync();
+ }
+ }
+}
+
+ int
+NaughtyApplet::widthForHeight(int) const
+{
+ return 20;
+}
+
+ int
+NaughtyApplet::heightForWidth(int) const
+{
+ return 20;
+}
+
+ void
+NaughtyApplet::slotLoad(uint l)
+{
+ if (l > monitor_->triggerLevel())
+ button_->setPixmap(BarIcon("naughty-sad"));
+ else
+ button_->setPixmap(BarIcon("naughty-happy"));
+}
+
+ void
+NaughtyApplet::about()
+{
+ KAboutData about
+ (
+ "naughtyapplet",
+ I18N_NOOP("Naughty applet"),
+ "1.0",
+ I18N_NOOP("Runaway process catcher"),
+ KAboutData::License_GPL_V2,
+ "(C) 2000 Rik Hemsley (rikkus) <[email protected]>"
+ );
+
+ KAboutApplication a(&about, this);
+ a.exec();
+}
+
+ void
+NaughtyApplet::slotPreferences()
+{
+ preferences();
+}
+
+ void
+NaughtyApplet::preferences()
+{
+ NaughtyConfigDialog d
+ (
+ ignoreList_,
+ monitor_->interval(),
+ monitor_->triggerLevel(),
+ this
+ );
+
+ QDialog::DialogCode retval = QDialog::DialogCode(d.exec());
+
+ if (QDialog::Accepted == retval)
+ {
+ ignoreList_ = d.ignoreList();
+ monitor_->setInterval(d.updateInterval());
+ monitor_->setTriggerLevel(d.threshold());
+ saveSettings();
+ }
+}
+
+ void
+NaughtyApplet::loadSettings()
+{
+ ignoreList_ = config()->readListEntry("IgnoreList");
+ monitor_->setInterval(config()->readUnsignedNumEntry("UpdateInterval", 2));
+ monitor_->setTriggerLevel(config()->readUnsignedNumEntry("Threshold", 20));
+
+ // Add 'X' as a default.
+ if (ignoreList_.isEmpty() && !config()->hasKey("IgnoreList"))
+ ignoreList_.append("X");
+}
+
+ void
+NaughtyApplet::saveSettings()
+{
+ config()->writeEntry("IgnoreList", ignoreList_);
+ config()->writeEntry("UpdateInterval", monitor_->interval());
+ config()->writeEntry("Threshold", monitor_->triggerLevel());
+ config()->sync();
+}
+
+#include "NaughtyApplet.moc"
+
diff --git a/kicker/applets/naughty/NaughtyApplet.h b/kicker/applets/naughty/NaughtyApplet.h
new file mode 100644
index 000000000..00df51ec4
--- /dev/null
+++ b/kicker/applets/naughty/NaughtyApplet.h
@@ -0,0 +1,76 @@
+/*
+ Naughty applet - Runaway process monitor for the KDE panel
+
+ Copyright 2000 Rik Hemsley (rikkus) <[email protected]>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef NAUGHTY_H
+#define NAUGHTY_H
+
+#include <kpanelapplet.h>
+#include <qstringlist.h>
+
+#include "simplebutton.h"
+
+class NaughtyProcessMonitor;
+class QPushButton;
+
+class NaughtyApplet : public KPanelApplet
+{
+ Q_OBJECT
+
+ public:
+
+ NaughtyApplet
+ (
+ const QString & configFile,
+ Type t = Normal,
+ int actions = 0,
+ QWidget * parent = 0,
+ const char * name = 0
+ );
+
+ ~NaughtyApplet();
+
+ virtual int widthForHeight(int h) const;
+ virtual int heightForWidth(int w) const;
+
+ signals:
+
+ void layoutChanged();
+
+ protected slots:
+
+ void slotWarn(ulong pid, const QString & name);
+ void slotLoad(uint);
+ void slotPreferences();
+
+ protected:
+
+ virtual void about();
+ virtual void preferences();
+ virtual void loadSettings();
+ virtual void saveSettings();
+
+ private:
+
+ NaughtyProcessMonitor * monitor_;
+ SimpleButton * button_;
+ QStringList ignoreList_;
+};
+
+#endif
diff --git a/kicker/applets/naughty/NaughtyConfigDialog.cpp b/kicker/applets/naughty/NaughtyConfigDialog.cpp
new file mode 100644
index 000000000..e03a955cc
--- /dev/null
+++ b/kicker/applets/naughty/NaughtyConfigDialog.cpp
@@ -0,0 +1,98 @@
+/*
+ Naughty applet - Runaway process monitor for the KDE panel
+
+ Copyright 2000 Rik Hemsley (rikkus) <[email protected]>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <keditlistbox.h>
+#include <knuminput.h>
+#include <klocale.h>
+#include <qvbox.h>
+
+#include "NaughtyConfigDialog.h"
+#include "NaughtyConfigDialog.moc"
+
+NaughtyConfigDialog::NaughtyConfigDialog
+(
+ const QStringList & items,
+ uint updateInterval,
+ uint threshold,
+ QWidget * parent,
+ const char * name
+)
+ :
+ KDialogBase
+ (
+ parent,
+ name,
+ true,
+ i18n("Configuration"),
+ KDialogBase::Ok | KDialogBase::Cancel,
+ KDialogBase::Ok,
+ true
+ )
+{
+ QVBox * v = new QVBox(this);
+ setMainWidget(v);
+
+ kini_updateInterval_ = new KIntNumInput(updateInterval, v);
+ kini_threshold_ = new KIntNumInput(kini_updateInterval_, threshold, v);
+
+ kini_updateInterval_ ->setLabel(i18n("&Update interval:"));
+ kini_threshold_ ->setLabel(i18n("CPU &load threshold:"));
+
+ kini_updateInterval_ ->setRange(1, 20);
+ kini_threshold_ ->setRange(10, 1000);
+
+ listBox_ = new KEditListBox
+ (i18n("&Programs to Ignore"),
+ v,
+ "naughty config dialog ignore listbox",
+ false,
+ KEditListBox::Add | KEditListBox::Remove
+ );
+
+ listBox_->insertStringList(items);
+}
+
+NaughtyConfigDialog::~NaughtyConfigDialog()
+{
+}
+
+ uint
+NaughtyConfigDialog::updateInterval() const
+{
+ return uint(kini_updateInterval_->value());
+}
+
+ uint
+NaughtyConfigDialog::threshold() const
+{
+ return uint(kini_threshold_->value());
+}
+
+ QStringList
+NaughtyConfigDialog::ignoreList() const
+{
+ QStringList retval;
+
+ for (int i = 0; i < listBox_->count(); i++)
+ retval << listBox_->text(i);
+
+ return retval;
+}
+
diff --git a/kicker/applets/naughty/NaughtyConfigDialog.h b/kicker/applets/naughty/NaughtyConfigDialog.h
new file mode 100644
index 000000000..485cbf14f
--- /dev/null
+++ b/kicker/applets/naughty/NaughtyConfigDialog.h
@@ -0,0 +1,58 @@
+/*
+ Naughty applet - Runaway process monitor for the KDE panel
+
+ Copyright 2000 Rik Hemsley (rikkus) <[email protected]>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef NAUGHTY_CONFIG_DIALOG_H
+#define NAUGHTY_CONFIG_DIALOG_H
+
+#include <kdialogbase.h>
+
+class KEditListBox;
+class KIntNumInput;
+
+class NaughtyConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ NaughtyConfigDialog
+ (
+ const QStringList & items,
+ uint interval,
+ uint threshold,
+ QWidget * parent = 0,
+ const char * name = 0
+ );
+
+ ~NaughtyConfigDialog();
+
+ QStringList ignoreList() const;
+ uint updateInterval() const;
+ uint threshold() const;
+
+ private:
+
+ KEditListBox * listBox_;
+
+ KIntNumInput * kini_updateInterval_;
+ KIntNumInput * kini_threshold_;
+};
+
+#endif
diff --git a/kicker/applets/naughty/NaughtyProcessMonitor.cpp b/kicker/applets/naughty/NaughtyProcessMonitor.cpp
new file mode 100644
index 000000000..f9d352902
--- /dev/null
+++ b/kicker/applets/naughty/NaughtyProcessMonitor.cpp
@@ -0,0 +1,475 @@
+/*
+ Naughty applet - Runaway process monitor for the KDE panel
+
+ Copyright 2000 Rik Hemsley (rikkus) <[email protected]>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* OpenBSD support by Jean-Yves Burlett <[email protected]> */
+
+#ifdef __OpenBSD__
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/ucred.h>
+#include <sys/dkstat.h>
+#include <stdlib.h>
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <qfile.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+#include <qdir.h>
+#include <qtimer.h>
+#include <qmap.h>
+#include <qdatetime.h>
+
+#include <klocale.h>
+
+#include "NaughtyProcessMonitor.h"
+
+class NaughtyProcessMonitorPrivate
+{
+ public:
+
+ NaughtyProcessMonitorPrivate()
+ : interval_(0),
+ timer_(0),
+ oldLoad_(0),
+ triggerLevel_(0)
+ {
+ }
+
+ ~NaughtyProcessMonitorPrivate()
+ {
+ // Empty.
+ }
+
+ uint interval_;
+ QTimer * timer_;
+ QMap<ulong, uint> loadMap_;
+ QMap<ulong, uint> scoreMap_;
+#ifdef __OpenBSD__
+ QMap<ulong, uint> cacheLoadMap_;
+ QMap<ulong, uid_t> uidMap_;
+#endif
+ uint oldLoad_;
+ uint triggerLevel_;
+
+ private:
+
+ NaughtyProcessMonitorPrivate(const NaughtyProcessMonitorPrivate &);
+
+ NaughtyProcessMonitorPrivate & operator =
+ (const NaughtyProcessMonitorPrivate &);
+};
+
+NaughtyProcessMonitor::NaughtyProcessMonitor
+ (
+ uint interval,
+ uint triggerLevel,
+ QObject * parent,
+ const char * name
+ )
+ : QObject(parent, name)
+{
+ d = new NaughtyProcessMonitorPrivate;
+ d->interval_ = interval * 1000;
+ d->triggerLevel_ = triggerLevel;
+ d->timer_ = new QTimer(this);
+ connect(d->timer_, SIGNAL(timeout()), this, SLOT(slotTimeout()));
+}
+
+NaughtyProcessMonitor::~NaughtyProcessMonitor()
+{
+ delete d;
+}
+
+ void
+NaughtyProcessMonitor::start()
+{
+ d->timer_->start(d->interval_, true);
+}
+
+ void
+NaughtyProcessMonitor::stop()
+{
+ d->timer_->stop();
+}
+
+ uint
+NaughtyProcessMonitor::interval() const
+{
+ return d->interval_ / 1000;
+}
+
+ void
+NaughtyProcessMonitor::setInterval(uint i)
+{
+ stop();
+ d->interval_ = i * 1000;
+ start();
+}
+
+ uint
+NaughtyProcessMonitor::triggerLevel() const
+{
+ return d->triggerLevel_;
+}
+
+ void
+NaughtyProcessMonitor::setTriggerLevel(uint i)
+{
+ d->triggerLevel_ = i;
+}
+
+ void
+NaughtyProcessMonitor::slotTimeout()
+{
+ uint cpu = cpuLoad();
+
+ emit(load(cpu));
+
+ if (cpu > d->triggerLevel_ * (d->interval_ / 1000))
+ {
+ uint load;
+ QValueList<ulong> l(pidList());
+
+ for (QValueList<ulong>::ConstIterator it(l.begin()); it != l.end(); ++it)
+ if (getLoad(*it, load))
+ _process(*it, load);
+ }
+
+ d->timer_->start(d->interval_, true);
+}
+
+ void
+NaughtyProcessMonitor::_process(ulong pid, uint load)
+{
+ if (!d->loadMap_.contains(pid))
+ {
+ d->loadMap_.insert(pid, load);
+ return;
+ }
+
+ uint oldLoad = d->loadMap_[pid];
+ bool misbehaving = (load - oldLoad) > 40 * (d->interval_ / 1000);
+ bool wasMisbehaving = d->scoreMap_.contains(pid);
+
+ if (misbehaving)
+ if (wasMisbehaving)
+ {
+ d->scoreMap_.replace(pid, d->scoreMap_[pid] + 1);
+ if (canKill(pid))
+ emit(runawayProcess(pid, processName(pid)));
+ }
+ else
+ d->scoreMap_.insert(pid, 1);
+ else
+ if (wasMisbehaving)
+ d->scoreMap_.remove(pid);
+
+ d->loadMap_.replace(pid, load);
+}
+
+// Here begins the set of system-specific methods.
+
+ bool
+NaughtyProcessMonitor::canKill(ulong pid) const
+{
+#ifdef __linux__
+ QFile f("/proc/" + QString::number(pid) + "/status");
+
+ if (!f.open(IO_ReadOnly))
+ return false;
+
+ QTextStream t(&f);
+
+ QString s;
+
+ while (!t.atEnd() && s.left(4) != "Uid:")
+ s = t.readLine();
+
+ QStringList l(QStringList::split('\t', s));
+
+ uint a(l[1].toUInt());
+
+// What are these 3 fields for ? Would be nice if the Linux kernel docs
+// were complete, eh ?
+// uint b(l[2].toUInt());
+// uint c(l[3].toUInt());
+// uint d(l[4].toUInt());
+
+ return geteuid() == a;
+#elif defined(__OpenBSD__)
+ // simply check if entry exists in the uid map and use it
+ if (!d->uidMap_.contains(pid))
+ return false ;
+
+ return geteuid () == d->uidMap_[pid] ;
+#else
+ Q_UNUSED( pid );
+ return false;
+#endif
+}
+
+ QString
+NaughtyProcessMonitor::processName(ulong pid) const
+{
+#if defined(__linux__) || defined(__OpenBSD__)
+#ifdef __linux__
+ QFile f("/proc/" + QString::number(pid) + "/cmdline");
+
+ if (!f.open(IO_ReadOnly))
+ return i18n("Unknown");
+
+ QCString s;
+
+ while (true)
+ {
+ int c = f.getch();
+
+ // Stop at NUL
+ if (c == -1 || char(c) == '\0')
+ break;
+ else
+ s += char(c);
+ }
+
+ // Now strip 'kdeinit:' prefix.
+ QString unicode(QString::fromLocal8Bit(s));
+
+#elif defined(__OpenBSD__)
+ int mib[4] ;
+ size_t size ;
+ char **argv ;
+
+ // fetch argv for the process `pid'
+
+ mib[0] = CTL_KERN ;
+ mib[1] = KERN_PROC_ARGS ;
+ mib[2] = pid ;
+ mib[3] = KERN_PROC_ARGV ;
+
+ // we assume argv[0]'s size will be less than one page
+
+ size = getpagesize () ;
+ argv = (char **)calloc (size, sizeof (char)) ;
+ size-- ; // ensure argv is ended by 0
+ if (-1 == sysctl (mib, 4, argv, &size, NULL, 0)) {
+ free (argv) ;
+ return i18n("Unknown") ;
+ }
+
+ // Now strip 'kdeinit:' prefix.
+ QString unicode(QString::fromLocal8Bit(argv[0]));
+
+ free (argv) ;
+#endif
+
+ QStringList parts(QStringList::split(' ', unicode));
+
+ QString processName = parts[0] == "kdeinit:" ? parts[1] : parts[0];
+
+ int lastSlash = processName.findRev('/');
+
+ // Get basename, if there's a path.
+ if (-1 != lastSlash)
+ processName = processName.mid(lastSlash + 1);
+
+ return processName;
+
+#else
+ Q_UNUSED( pid );
+ return QString::null;
+#endif
+}
+
+ uint
+NaughtyProcessMonitor::cpuLoad() const
+{
+#ifdef __linux__
+ QFile f("/proc/stat");
+
+ if (!f.open(IO_ReadOnly))
+ return 0;
+
+ bool forgetThisOne = 0 == d->oldLoad_;
+
+ QTextStream t(&f);
+
+ QString s = t.readLine();
+
+ QStringList l(QStringList::split(' ', s));
+
+ uint user = l[1].toUInt();
+ uint sys = l[3].toUInt();
+
+ uint load = user + sys;
+ uint diff = load - d->oldLoad_;
+ d->oldLoad_ = load;
+
+ return (forgetThisOne ? 0 : diff);
+#elif defined(__OpenBSD__)
+ int mib[2] ;
+ long cp_time[CPUSTATES] ;
+ size_t size ;
+ uint load, diff ;
+ bool forgetThisOne = 0 == d->oldLoad_;
+
+ // fetch CPU time statistics
+
+ mib[0] = CTL_KERN ;
+ mib[1] = KERN_CPTIME ;
+
+ size = CPUSTATES * sizeof(long) ;
+
+ if (-1 == sysctl (mib, 2, cp_time, &size, NULL, 0))
+ return 0 ;
+
+ load = cp_time[CP_USER] + cp_time[CP_SYS] ;
+ diff = load - d->oldLoad_ ;
+ d->oldLoad_ = load ;
+
+ return (forgetThisOne ? 0 : diff);
+#else
+ return 0;
+#endif
+}
+
+ QValueList<ulong>
+NaughtyProcessMonitor::pidList() const
+{
+#ifdef __linux__
+ QStringList dl(QDir("/proc").entryList());
+
+ QValueList<ulong> pl;
+
+ for (QStringList::ConstIterator it(dl.begin()); it != dl.end(); ++it)
+ if (((*it)[0].isDigit()))
+ pl << (*it).toUInt();
+
+ return pl;
+#elif defined(__OpenBSD__)
+ int mib[3] ;
+ int nprocs = 0, nentries ;
+ size_t size ;
+ struct kinfo_proc *kp ;
+ int i ;
+ QValueList<ulong> l;
+
+ // fetch number of processes
+
+ mib[0] = CTL_KERN ;
+ mib[1] = KERN_NPROCS ;
+
+ if (-1 == sysctl (mib, 2, &nprocs, &size, NULL, 0))
+ return l ;
+
+ // magic size evaluation ripped from ps
+
+ size = (5 * nprocs * sizeof(struct kinfo_proc)) / 4 ;
+ kp = (struct kinfo_proc *)calloc (size, sizeof (char)) ;
+
+ // fetch process info
+
+ mib[0] = CTL_KERN ;
+ mib[1] = KERN_PROC ;
+ mib[2] = KERN_PROC_ALL ;
+
+ if (-1 == sysctl (mib, 3, kp, &size, NULL, 0)) {
+ free (kp) ;
+ return l ;
+ }
+
+ nentries = size / sizeof (struct kinfo_proc) ;
+
+ // time statistics and euid data are fetched only for processes in
+ // the pidList, so, instead of doing one sysctl per process for
+ // getLoad and canKill calls, simply cache the data we already have.
+
+ d->cacheLoadMap_.clear () ;
+ d->uidMap_.clear () ;
+ for (i = 0; i < nentries; i++) {
+ l << (unsigned long) kp[i].kp_proc.p_pid ;
+ d->cacheLoadMap_.insert (kp[i].kp_proc.p_pid,
+ (kp[i].kp_proc.p_uticks +
+ kp[i].kp_proc.p_sticks)) ;
+ d->uidMap_.insert (kp[i].kp_proc.p_pid,
+ kp[i].kp_eproc.e_ucred.cr_uid) ;
+ }
+
+ free (kp) ;
+
+ return l ;
+#else
+ QValueList<ulong> l;
+ return l;
+#endif
+}
+
+ bool
+NaughtyProcessMonitor::getLoad(ulong pid, uint & load) const
+{
+#ifdef __linux__
+ QFile f("/proc/" + QString::number(pid) + "/stat");
+
+ if (!f.open(IO_ReadOnly))
+ return false;
+
+ QTextStream t(&f);
+
+ QString line(t.readLine());
+
+ QStringList fields(QStringList::split(' ', line));
+
+ uint userTime (fields[13].toUInt());
+ uint sysTime (fields[14].toUInt());
+
+ load = userTime + sysTime;
+
+ return true;
+#elif defined(__OpenBSD__)
+ // use cache
+ if (!d->cacheLoadMap_.contains(pid))
+ return false ;
+
+ load = d->cacheLoadMap_[pid] ;
+ return true ;
+#else
+ Q_UNUSED( pid );
+ Q_UNUSED( load );
+ return false;
+#endif
+}
+
+ bool
+NaughtyProcessMonitor::kill(ulong pid) const
+{
+#if defined(__linux__) || defined(__OpenBSD__)
+ return 0 == ::kill(pid, SIGKILL);
+#else
+ Q_UNUSED( pid );
+ return false;
+#endif
+}
+
+#include "NaughtyProcessMonitor.moc"
diff --git a/kicker/applets/naughty/NaughtyProcessMonitor.h b/kicker/applets/naughty/NaughtyProcessMonitor.h
new file mode 100644
index 000000000..d7023dbd7
--- /dev/null
+++ b/kicker/applets/naughty/NaughtyProcessMonitor.h
@@ -0,0 +1,76 @@
+/*
+ Naughty applet - Runaway process monitor for the KDE panel
+
+ Copyright 2000 Rik Hemsley (rikkus) <[email protected]>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef NAUGHTY_PROCESS_MONITOR_H
+#define NAUGHTY_PROCESS_MONITOR_H
+
+#include <qobject.h>
+
+class NaughtyProcessMonitorPrivate;
+
+class NaughtyProcessMonitor : public QObject
+{
+ Q_OBJECT
+
+ public:
+
+ NaughtyProcessMonitor
+ (
+ uint interval,
+ uint triggerLevel,
+ QObject * parent = 0,
+ const char * name = 0
+ );
+
+ virtual ~NaughtyProcessMonitor();
+
+ void start();
+ void stop();
+
+ uint triggerLevel() const;
+ void setTriggerLevel(uint);
+ uint interval() const;
+ void setInterval(uint);
+
+ virtual uint cpuLoad() const;
+ virtual QValueList<ulong> pidList() const;
+ virtual bool getLoad(ulong pid, uint & load) const;
+ virtual QString processName(ulong pid) const;
+ virtual bool canKill(ulong pid) const;
+ virtual bool kill(ulong pid) const;
+
+ protected slots:
+
+ void slotTimeout();
+
+ signals:
+
+ void load(uint);
+ void runawayProcess(ulong pid, const QString & name);
+
+ private:
+
+ void _process(ulong pid, uint load);
+
+ NaughtyProcessMonitorPrivate * d;
+};
+
+#endif
+
diff --git a/kicker/applets/naughty/configure.in.in b/kicker/applets/naughty/configure.in.in
new file mode 100644
index 000000000..5847780f0
--- /dev/null
+++ b/kicker/applets/naughty/configure.in.in
@@ -0,0 +1,5 @@
+case "$host" in
+ *-*-freebsd*) LIB_KVM="-lkvm" ;;
+ *) LIB_KVM="" ;;
+esac
+AC_SUBST(LIB_KVM)
diff --git a/kicker/applets/naughty/naughty-happy.png b/kicker/applets/naughty/naughty-happy.png
new file mode 100644
index 000000000..3200b5270
--- /dev/null
+++ b/kicker/applets/naughty/naughty-happy.png
Binary files differ
diff --git a/kicker/applets/naughty/naughty-sad.png b/kicker/applets/naughty/naughty-sad.png
new file mode 100644
index 000000000..9b6541907
--- /dev/null
+++ b/kicker/applets/naughty/naughty-sad.png
Binary files differ
diff --git a/kicker/applets/naughty/naughtyapplet.desktop b/kicker/applets/naughty/naughtyapplet.desktop
new file mode 100644
index 000000000..f7cb6a35f
--- /dev/null
+++ b/kicker/applets/naughty/naughtyapplet.desktop
@@ -0,0 +1,131 @@
+[Desktop Entry]
+Type=Plugin
+Name=Runaway Process Catcher
+Name[af]=Weghardloop Proses Vanger
+Name[ar]=لاقط الإجرائات الهاربة
+Name[az]=İşıək Gedişat Yaxalayıcı
+Name[be]=Захоп завіснуўшых працэсаў
+Name[bg]=Неуправляеми процеси
+Name[bn]=অনিয়ন্ত্রিত প্রসেস প্রহরী
+Name[bs]=Hvatač odbjeglih procesa
+Name[ca]=Capturador de processos descontrolats
+Name[cs]=Odchytávač chybných procesů
+Name[csb]=Jachtôrz zagùbionëch procesów
+Name[cy]=Arhosydd Prosesau Di-derfyn
+Name[da]=Indfanger af løbsk-kørte processer
+Name[de]=Beenden unkontrollierter Prozesse
+Name[el]=Runaway Έλεγχος Διεργασιών
+Name[eo]=Kaptilo por eskapitaj procezoj
+Name[es]=Capturador de procesos desbocados
+Name[et]=Hanguvate protsesside püüdja
+Name[eu]=Ataza eroen harrapatzailea
+Name[fa]=گیرندۀ فرآیند فراری
+Name[fi]=Karanneiden prosessien kiinniottaja
+Name[fr]=Détecteur de processus fous
+Name[fy]=Processenmonitor
+Name[ga]=Sriantóir na bPróiseas Éalaitheach
+Name[gl]=Detector de Procesos Estragados
+Name[he]=תופס תהליכים נמלטים
+Name[hi]=रनअवे प्रॉसेस कैचर
+Name[hr]=Hvatač odbjeglih procesa
+Name[hu]=Folyamatszabályozó
+Name[is]=Ferlafangari
+Name[it]=Rilevatore di processi impazziti
+Name[ja]=手に負えないプロセスのキャッチャー
+Name[kk]=Жаңылыс процесстерді байқаушы
+Name[km]=ឧបករណ៍​ចាប់​យក​ដំណើរការ​ដែល​មិន​អាច​បញ្ជា​បាន
+Name[lo]=ດັກຈັບໂປຣເສດ
+Name[lt]=Pabėgusių procesų gaudyklė
+Name[lv]=Nevadāmu Procesu Savācējs
+Name[mk]=Фаќач на процеси бегалци
+Name[mn]=Удирдлагагүй процессуудыг төгсгөх
+Name[ms]=Penangkap Proses Luar Kawalan
+Name[mt]=Programm biex Jaqbad Proċessi Maħruba
+Name[nb]=Fanger løpske prosesser
+Name[nds]=Dörgahn Perzessen infangen
+Name[ne]=रन वे प्रोसेस क्याचर
+Name[nl]=Processenmonitor
+Name[nn]=Løpsk prosess-fangar
+Name[nso]=Moswari wa Tiragalo yeo e Tshabago
+Name[pa]=ਬੇਕਾਬੂ ਕਾਰਜ ਸ਼ਿਕਾਰੀ
+Name[pl]=Łowca zagubionych procesów
+Name[pt]=Colector de Processos em Fuga
+Name[pt_BR]=Captura de processos
+Name[ro]=Monitor de procese
+Name[ru]=Сторож сбойных процессов
+Name[rw]=Mufata Igikorwa Ntagenzura
+Name[se]=Báhtaran proseassaid dustejeaddji
+Name[sk]=Zachytenie chybných procesov
+Name[sl]=Prestrezovalnik pobeglih procesov
+Name[sr]=Хватач одбеглих процеса
+Name[sr@Latn]=Hvatač odbeglih procesa
+Name[sv]=Fånga bortsprungna processer
+Name[ta]=ஓடுபாதை செயல் பிடிப்பான்
+Name[tg]=Дастгиркунандаи протсессҳои қарорӣ
+Name[th]=ดักการจบโปรเซส
+Name[tr]=Sorunlu Süreç Yakalayıcı
+Name[tt]=Içqınğan Eşlänü Totqıç
+Name[uk]=Захоплювач процесів-дезертирів
+Name[ven]=TShitenwa tsha Catcher
+Name[vi]=Bắt Tiến trình Chạy trốn
+Name[wa]=Troûleu d' sot processus
+Name[zh_CN]=落跑进程捕捉器
+Name[zh_TW]=失控程式捕捉器
+Name[zu]=Umbambi wenqubo ebalekayo
+Comment=Detect and end broken processes which consume too much CPU time
+Comment[af]=Spoor stukkende prosesse op wat te veel CPU tyd opneem en stop hulle
+Comment[ar]=إكتشف و أنهي الإجرائات المقطوعة اللتي تستهلك الكثير من وقت تشغيل وحدة المعالجة المركزية
+Comment[be]=Вызначае і забівае зламаныя працэсы, якія выкарыстоўваюць працэсар надта моцна
+Comment[bg]=Намиране и прекратяване на процеси, които консумират твърде много ресурси
+Comment[bs]=Otkrij i završi neispravne procese koji zauzimaju previše CPU vremena
+Comment[ca]=Detecta i finalitza processos espatllats que consumeixen massa temps de CPU
+Comment[cs]=Zjištění a ukončení poškozených procesů ubírajících výkon
+Comment[csb]=Òdnajdiwô ë kùńczi niesprôwné procesë, jaczé brëkùją za wiele procesora
+Comment[da]=Detekterer og afslutter fejlagtige processer som bruger for meget processortid
+Comment[de]=Erkennen und Beenden fehlerhafter Prozesse, die zu viel Rechenzeit verbrauchen
+Comment[el]=Ανίχνευση και τερματισμός διεργασιών που καταναλώνουν μεγάλο χρόνο του επεξεργαστή
+Comment[eo]=Detekti kaj mortigi difektitajn procezojn konsumante tro da procezilo-tempon
+Comment[es]=Detectar procesos rotos que consumen demasiado tiempo del procesador
+Comment[et]=Liialt protsessoriaega kulutavate katkiste rakenduste avastamine ja nende töö lõpetamine
+Comment[eu]=Detektatu eta amaitu CPU gehiegi erabiltzen ari diren prozesuak
+Comment[fa]=آشکارسازی و پایان فرآیندهای قطع‌شده، که زمان خیلی زیاد واحد پردازش مرکزی را مصرف می‌کند.
+Comment[fi]=Tunnista ja lopeta rikkinäiset prosessit, jotka kuluttavat liikaa laskentatehoa.
+Comment[fr]=Détection et arrêt des programmes consommant trop de ressources du processeur
+Comment[fy]=Untdekke en stopje alle brutsen prosessen dy tefolle prosessortiid konsumearje
+Comment[gl]=Detecta e mata procesos estragados que consumen tempo de CPU
+Comment[he]=זהה וסגור תהליכים שצורכים יותר מדי זמן מעבד
+Comment[hr]=Otkrivanje i završavanje nedovršenih procesa koji troše previše procesorskog vremena
+Comment[hu]=A túl sok processzoridőt lefoglaló folyamatok meghatározása és bezárása
+Comment[is]=Uppgötvaðu og slökktu á rofnum ferlum sem taka of mikinn örgjörvatíma
+Comment[it]=Trova e termina i processi impazziti che consuma troppo processore
+Comment[ja]=CPU 時間を無駄に消費する壊れたプロセスを見つけて終了させる
+Comment[kk]=Проңессорды көп жұмсайтын процессарды табу және жою
+Comment[km]=រក និង​បញ្ចប់​ដំណើរការ​ខូច​ដែល​ប្រើ​ពេលវេលា CPU ច្រើន​ពេក
+Comment[lt]=Aptikti ir užbaigti sugadintus procesus, kurie suryja per daug CPU laiko
+Comment[mk]=Откривање и прекинување на нефункционални процеси што го трошат времето на процесорот
+Comment[nb]=Finn og avslutt løpske prosesser som tar for mye prosessorkraft
+Comment[nds]=Schaadhaftig Perzessen, de to veel Rekentiet bruukt, opdecken un beennen
+Comment[ne]=प्रसस्त CPU समय खपत गर्ने कमजोर प्रक्रिया पत्ता लगाउनुहोस् र अन्त्य गर्नुहोस्
+Comment[nl]=Detecteer en stop gebroken processen die teveel processortijd consumeren
+Comment[nn]=Finn og avslutt løpske prosessar som tek for myjke prosessorkraft.
+Comment[pl]=Wykrywa i kończy niesprawne procesy, które zużywają za dużo procesora
+Comment[pt]=Detectar e terminar os processos com problemas que estejam a consumir demasiado CPU
+Comment[pt_BR]=Detecta e finaliza processos quebrados que consomem muito tempo de CPU
+Comment[ro]=Detectează și termină procese defecte care consumă prea mult CPU
+Comment[ru]=Обнаружение и завершение процессов, требующим слишком много времени процессора
+Comment[se]=Gávnna jea heaittit reakčanan proseassaid mat geavahit menddo olu CPU-áiggi
+Comment[sk]=Zistenie a ukončenie procesov, ktoré spotrebúvajú priveľa času CPU
+Comment[sl]=Zaznavanje in pobijanje procesov, ki porabljajo preveč procesorskega časa
+Comment[sr]=Детектује и окончава покварене процесе који одузимају превише процесорског времена
+Comment[sr@Latn]=Detektuje i okončava pokvarene procese koji oduzimaju previše procesorskog vremena
+Comment[sv]=Detekterar och avslutar felaktiga processer som använder för mycket processortid
+Comment[th]=ตรวจจับและจบโปรเซสที่เสียหาย ซึ่งใช้เวลาของหน่วยประมวลผลมากเกินไป
+Comment[tr]=Sorunlu ve fazla işlemci gücü harcayan programları bulup yokeder
+Comment[uk]=Виявлення і припинення процесів, які споживають забагато часу процесора
+Comment[vi]=Phát hiện và ngừng các tiến trình gây lãng phí bộ vi xử lý
+Comment[wa]=Trove et arestêye les schetés processus k' eployèt trop di tins CPU
+Comment[zh_CN]=检测并结束占用太多 CPU 时间的进程
+Comment[zh_TW]=偵測並終結浪費多數 CPU 時間的破損程序
+Icon=runprocesscatcher
+X-KDE-Library=naughty_panelapplet
+X-KDE-UniqueApplet=true
diff --git a/kicker/applets/run/Makefile.am b/kicker/applets/run/Makefile.am
new file mode 100644
index 000000000..ec4de4984
--- /dev/null
+++ b/kicker/applets/run/Makefile.am
@@ -0,0 +1,19 @@
+INCLUDES = $(all_includes)
+
+kde_module_LTLIBRARIES = run_panelapplet.la
+
+run_panelapplet_la_SOURCES = runapplet.cpp
+
+METASOURCES = runapplet.moc
+noinst_HEADERS = runapplet.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = runapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+run_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+run_panelapplet_la_LIBADD = $(LIB_KSYCOCA) $(LIB_KDEUI)
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/krunapplet.pot
diff --git a/kicker/applets/run/runapplet.cpp b/kicker/applets/run/runapplet.cpp
new file mode 100644
index 000000000..93bb5d7ad
--- /dev/null
+++ b/kicker/applets/run/runapplet.cpp
@@ -0,0 +1,294 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <[email protected]>
+
+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 <qfont.h>
+#include <qstringlist.h>
+#include <qpushbutton.h>
+#include <qhbox.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kcombobox.h>
+#include <kurifilter.h>
+#include <kdialog.h>
+#include <krun.h>
+#include <kmessagebox.h>
+
+#include "runapplet.h"
+#include "runapplet.moc"
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("krunapplet");
+ return new RunApplet(configFile, KPanelApplet::Stretch, 0, parent, "krunapplet");
+ }
+}
+
+RunApplet::RunApplet(const QString& configFile, Type type, int actions,
+ QWidget *parent, const char *name)
+ : KPanelApplet(configFile, type, actions, parent, name)
+{
+ // setBackgroundMode(X11ParentRelative);
+ setBackgroundOrigin( AncestorOrigin );
+ // setup label
+ _label = new QLabel(i18n("Run command:"), this);
+ QFont f(_label->font());
+ f.setPixelSize(12);
+// _label->setBackgroundMode(X11ParentRelative);
+ _label->setBackgroundOrigin( AncestorOrigin );
+ _label->setFixedHeight(14);
+ _label->setFont(f);
+
+ // setup popup button
+ _btn = new QPushButton(this);
+ f = _btn->font();
+ f.setPixelSize(12);
+ _btn->setFont(f);
+ connect(_btn, SIGNAL(clicked()), SLOT(popup_combo()));
+
+ // setup history combo
+ _input = new KHistoryCombo(this);
+ _input->setFocus();
+ _input->clearEdit();
+ watchForFocus(_input->lineEdit());
+ connect(_input, SIGNAL(activated(const QString&)),
+ SLOT(run_command(const QString&)));
+
+ KConfig *c = config();
+ c->setGroup("General");
+
+ // restore history and completion list
+ QStringList list = c->readListEntry("Completion list");
+ _input->completionObject()->setItems(list);
+ list = c->readListEntry("History list");
+ _input->setHistoryItems(list);
+ int mode = c->readNumEntry( "CompletionMode", KGlobalSettings::completionMode() );
+ _input->setCompletionMode( (KGlobalSettings::Completion) mode );
+
+ _filterData = new KURIFilterData();
+
+ _hbox = new QHBox( 0, 0, WStyle_Customize | WType_Popup );
+ _hbox->setFixedSize(120, 22);
+}
+
+RunApplet::~RunApplet()
+{
+ KConfig *c = config();
+ c->setGroup("General");
+
+ // save history and completion list
+ QStringList list = _input->completionObject()->items();
+ c->writeEntry("Completion list", list);
+ list = _input->historyItems();
+ c->writeEntry("History list", list);
+ c->writeEntry( "CompletionMode", (int) _input->completionMode() );
+ c->sync();
+
+ delete _filterData;
+ KGlobal::locale()->removeCatalogue("krunapplet");
+}
+
+void RunApplet::resizeEvent(QResizeEvent*)
+{
+ if(orientation() == Horizontal)
+ {
+ _btn->hide();
+ _input->reparent(this, QPoint(0,0), true);
+ _label->setGeometry(0,0, width(), _label->height());
+
+ if(height() >= _input->sizeHint().height() + _label->height())
+ {
+ int inputVOffset = height() - _input->sizeHint().height() - 2;
+ int labelHeight = _label->sizeHint().height();
+ _label->setGeometry(0, inputVOffset - labelHeight,
+ width(), labelHeight);
+ _input->setGeometry(0, inputVOffset,
+ width(), _input->sizeHint().height());
+ _label->show();
+ }
+ else
+ {
+ _label->hide();
+
+ // make it as high as the combobox naturally wants to be
+ // but no taller than the panel is!
+ // don't forget to center it vertically either.
+ int newHeight = _input->sizeHint().height();
+ if (newHeight > height())
+ newHeight = height();
+ _input->setGeometry(0, (height() - newHeight) / 2,
+ width(), newHeight);
+ }
+ }
+ else
+ {
+ _btn->show();
+ _btn->setFixedSize(width(), 22);
+ _input->reparent( _hbox, QPoint(0, 0), false);
+ _label->hide();
+ }
+ setButtonText();
+}
+
+void RunApplet::positionChange(KPanelApplet::Position)
+{
+ setButtonText();
+}
+
+void RunApplet::setButtonText()
+{
+ QString t;
+
+ if (position() == pRight)
+ {
+ if (width() >= 42)
+ t = i18n("< Run");
+ else
+ t = "<";
+ }
+ else
+ {
+ if(width() >= 42)
+ t = i18n("Run >");
+ else
+ t = ">";
+ }
+
+ _btn->setText(t);
+}
+
+int RunApplet::widthForHeight(int ) const
+{
+ return _label->sizeHint().width();
+}
+
+int RunApplet::heightForWidth(int ) const
+{
+ return 22;
+}
+
+void RunApplet::popup_combo()
+{
+ QPoint p;
+ if (position() == pRight)
+ p = mapToGlobal(QPoint(-_input->width()-1, 0));
+ else
+ p = mapToGlobal(QPoint(width()+1, 0));
+ _hbox->move(p);
+ _hbox->show();
+ _input->setFocus();
+}
+
+void RunApplet::run_command(const QString& command)
+{
+ QString exec;
+ bool focusNeeded = false;
+
+ kapp->propagateSessionManager();
+
+ _filterData->setData( _input->currentText().stripWhiteSpace() );
+ QStringList filters;
+ filters << "kurisearchfilter" << "kshorturifilter";
+ KURIFilter::self()->filterURI( *(_filterData), filters );
+
+ _input->addToHistory(command);
+ _input->clearEdit();
+
+ QString cmd = (_filterData->uri().isLocalFile() ? _filterData->uri().path():_filterData->uri().url());
+
+ // Nothing interesting. Quit!
+ if ( cmd.isEmpty() ){
+ KMessageBox::sorry(0L, i18n("You have to enter a command to execute "
+ "or a URL to be opened first."));
+ focusNeeded = true;
+ goto hide;
+ }
+ else if (cmd == "logout")
+ {
+ bool shutdown = kapp->requestShutDown();
+ if( !shutdown )
+ {
+ // This i18n string is in kdesktop/desktop.cc as well. Maybe we should DCOP to kdesktop instead ?
+ KMessageBox::error( 0, i18n("Unable to log out properly.\nThe session manager cannot "
+ "be contacted. You can try to force a shutdown by pressing "
+ "Ctrl+Alt+Backspace. Note, however, that your current "
+ "session will not be saved with a forced shutdown." ) );
+ focusNeeded = true;
+ }
+ goto hide;
+ }
+ else
+ {
+ switch( _filterData->uriType() )
+ {
+ case KURIFilterData::LOCAL_FILE:
+ case KURIFilterData::LOCAL_DIR:
+ case KURIFilterData::NET_PROTOCOL:
+ case KURIFilterData::HELP:
+ {
+ (void) new KRun( _filterData->uri() );
+ goto hide;
+ }
+ case KURIFilterData::EXECUTABLE:
+ case KURIFilterData::SHELL:
+ {
+ exec = cmd;
+ if( _filterData->hasArgsAndOptions() )
+ cmd += _filterData->argsAndOptions();
+ break;
+ }
+ case KURIFilterData::UNKNOWN:
+ case KURIFilterData::ERROR:
+ default:
+ KMessageBox::sorry( 0, i18n("<qt>The program name or command <b>%1</b>\n"
+ "cannot be found. Please correct the command\n"
+ "or URL and try again</qt>").arg( cmd ) );
+ _input->removeFromHistory( _input->currentText() );
+ focusNeeded = true;
+ goto hide;
+ }
+ }
+ if (KRun::runCommand( cmd, exec, "" ))
+ goto hide;
+ else
+ {
+ KMessageBox::sorry( 0, i18n("<qt>Could not run <b>%1</b>.\nPlease correct"
+ " the command or URL and try again.</qt>").arg( cmd ) );
+ _input->removeFromHistory( _input->currentText() );
+ focusNeeded = true;
+ goto hide;
+ }
+
+ needsFocus(focusNeeded);
+ return;
+
+ hide:
+ if (orientation() == Vertical)
+ _hbox->hide();
+ needsFocus(focusNeeded);
+}
diff --git a/kicker/applets/run/runapplet.desktop b/kicker/applets/run/runapplet.desktop
new file mode 100644
index 000000000..66937ccae
--- /dev/null
+++ b/kicker/applets/run/runapplet.desktop
@@ -0,0 +1,130 @@
+[Desktop Entry]
+Type=Plugin
+Name=Run Command
+Name[af]=Hardloop Opdrag
+Name[ar]=تنفيذ الأمر
+Name[be]=Выканаць праграму
+Name[bg]=Изпълнение на команда
+Name[bn]=কমান্ড চালাও
+Name[br]=Seveniñ ur Goulev
+Name[bs]=Izvrši naredbu
+Name[ca]=Executa un comandament
+Name[cs]=Spustit příkaz
+Name[csb]=Zrëszënié pòlétu
+Name[cy]=Rhedeg Gorchymyn
+Name[da]=Kør kommando
+Name[de]=Befehl ausführen
+Name[el]=Εκτέλεση εντολής
+Name[eo]=Lanĉu komandon
+Name[es]=Ejecutar una orden
+Name[et]=Käsu käivitamine
+Name[eu]=Exekutatu komandoa
+Name[fa]=اجرای فرمان
+Name[fi]=Suorita komento
+Name[fr]=Lancer une commande
+Name[fy]=kommando útfiere
+Name[ga]=Rith Ordú
+Name[gl]=Executar Comando
+Name[he]=הפעלת פקודה
+Name[hi]=कमांड चलाएँ
+Name[hr]=Pokreni naredbu
+Name[hu]=Parancs végrehajtása
+Name[is]=Keyra skipun
+Name[it]=Esegui comando
+Name[ja]=コマンドを実行
+Name[ka]=ბრძანების შესრულება
+Name[kk]=Команданы орындау
+Name[km]=រត់​ពាក្យ​បញ្ជា
+Name[ko]=Penguin Command
+Name[lt]=Paleisti komandą
+Name[lv]=Darbināt komandu
+Name[mk]=Изврши команда
+Name[ms]=Arahan Laksana
+Name[nb]=Kjør kommando
+Name[nds]=Befehl utföhren
+Name[ne]=आदेश चलाउनुहोस्
+Name[nl]=Commando uitvoeren
+Name[nn]=Køyr kommando
+Name[pa]=ਕਮਾਂਡ ਚਲਾਓ
+Name[pl]=Uruchomienie polecenia
+Name[pt]=Executar um Comando
+Name[pt_BR]=Executar Comando
+Name[ro]=Execută comanda
+Name[ru]=Выполнить команду
+Name[rw]=Gutangiza Ibwiriza
+Name[se]=Vuoje gohččuma
+Name[sk]=Vykonať príkaz
+Name[sl]=Poženi ukaz
+Name[sr]=Покретање наредбе
+Name[sr@Latn]=Pokretanje naredbe
+Name[sv]=Kör kommando
+Name[ta]=இயக்க கட்டளை
+Name[tg]=Иҷрои фармон
+Name[th]=ใช้งานคำสั่ง
+Name[tr]=Komut Çalıştır
+Name[tt]=Boyırıq Eşlätü
+Name[uk]=Запуск команди
+Name[uz]=Buyruqni bajarish
+Name[uz@cyrillic]=Буйруқни бажариш
+Name[vi]=Gõ lệnh
+Name[wa]=Enonder ene comande
+Name[zh_CN]=运行命令
+Name[zh_TW]=執行命令
+Comment=Launch single commands without a terminal window
+Comment[af]=Lanseer enkel opdragte sonder 'n terminaal venster
+Comment[ar]=أطلق أوامر وحيدة بدون الحاجة إلى نافذة المطراف
+Comment[be]=Запускае асобныя каманды без тэрмінальнага акна
+Comment[bg]=Стартиране на команда без да има нужда от терминален прозорец
+Comment[bn]=টার্মিনাল উইণ্ডো ছাড়াই একটি কমান্ড চালান
+Comment[bs]=Izvršite pojedinačne naredbe bez prozora terminala
+Comment[ca]=Engega ordres sense una finestra de terminal
+Comment[cs]=Spouštění jednotlivých příkazů bez terminálového okna
+Comment[csb]=Zrëszanié pòjedińczëch pòlétów kònsolë bez òtmëkaniô òkna terminala
+Comment[da]=Start enkelte kommandoer uden et terminalvindue
+Comment[de]=Ausführen einzelner Kommandos ohne Terminalfenster
+Comment[el]=Εκτέλεση εντολών χωρίς ένα παράθυρο τερματικού
+Comment[eo]=Lanĉi unuopajn komandojn sen terminala fenestro
+Comment[es]=Lanzar órdenes individuales sin ventana de terminal
+Comment[et]=Üksikute käskude käivitamine terminali abita
+Comment[eu]=Abiarazi komandoak terminal leihorik gabe
+Comment[fa]=راه‌اندازی فرمانهای تک بدون پنجرۀ پایانه
+Comment[fi]=Käynnistä yksittäisiä komentoja ilman pääteikkunaa.
+Comment[fr]=Lancer des commandes simples sans fenêtre de terminal
+Comment[fy]=Fier losse kommando's út sûnder in terminalfinster
+Comment[ga]=Rith orduithe aonair gan fhuinneog theirminéil
+Comment[gl]=Executa comandos individuais sen usar unha terminal
+Comment[he]=הפעל פקודות פשוטות ללא חלון מסוף
+Comment[hr]=Pokretanje pojedinih naredbi bez terminalskog prozora
+Comment[hu]=Parancs kiadása parancsértelmező ablak nélkül
+Comment[is]=Keyrðu einstakar skipanir án skeljaglugga
+Comment[it]=Lancia singoli comandi senza una finestra di terminale
+Comment[ja]=ターミナルウィンドウを開かずに一つのコマンドを実行
+Comment[kk]=Болек командаларды терминал терезесінен тыс жегу
+Comment[km]=បើក​ពាក្យ​បញ្ជា​តែ​មួយ ដោយ​គ្មាន​បង្អួច​ស្ថានីយ
+Comment[lt]=Vykdykite pavienes komandas ne terminalo lange
+Comment[mk]=Стартување на единечни команди без терминалски прозорец
+Comment[nb]=Kjør en enkelt kommando uten et skall
+Comment[nds]=Enkel Befehlen ahn Terminalfinster starten
+Comment[ne]=टर्मिनल सञ्झ्याल बिना एकल आदेश सुरुआत गर्नुहोस्
+Comment[nl]=Voer losse commando's uit zonder een terminalvenster
+Comment[nn]=Køyr ein enkelt kommando utan eit skal.
+Comment[pl]=Uruchamianie pojedynczych poleceń konsoli bez otwierania okna terminala
+Comment[pt]=Lançar comandos simples sem uma janela de terminal
+Comment[pt_BR]=Abre comandos digitados sem a necessidade de uma janela de terminal
+Comment[ro]=Lansează comenzi fără o fereastră de terminal
+Comment[ru]=Выполнение отдельной команды без окна терминала
+Comment[se]=Vuoje oktonas gohččomiid terminálaláse haga
+Comment[sk]=Spustiť príkaz bez okna terminálu
+Comment[sl]=Poganjanje posameznih ukazov brez okna terminala
+Comment[sr]=Покрените једноструке наредбе без терминалског прозора
+Comment[sr@Latn]=Pokrenite jednostruke naredbe bez terminalskog prozora
+Comment[sv]=Starta enstaka kommandon utan ett terminalfönster
+Comment[th]=เรียกใช้งานคำสั่งเดี่ยวๆ โดยไม่ต้องเข้าหน้าต่างเทอร์มินัล
+Comment[uk]=Запуск окремих команд без вікна термінала
+Comment[vi]=Chạy một lệnh đơn mà không cần mở một thiết bị đầu cuối
+Comment[wa]=Lancî ene comande seule sins terminå
+Comment[zh_CN]=调用单条命令而无须使用终端窗口
+Comment[zh_TW]=不使用終端機視窗而送出單行指令
+Icon=exec
+X-KDE-Library=run_panelapplet
+X-KDE-UniqueApplet=true
diff --git a/kicker/applets/run/runapplet.h b/kicker/applets/run/runapplet.h
new file mode 100644
index 000000000..ded8fc398
--- /dev/null
+++ b/kicker/applets/run/runapplet.h
@@ -0,0 +1,65 @@
+/*****************************************************************
+
+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 __runapplet_h__
+#define __runapplet_h__
+
+#include <qstring.h>
+#include <kpanelapplet.h>
+
+class QLabel;
+class QHBox;
+class QPushButton;
+class KHistoryCombo;
+class KURIFilterData;
+
+class RunApplet : public KPanelApplet
+{
+ Q_OBJECT
+
+public:
+ RunApplet(const QString& configFile, Type t = Stretch, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ virtual ~RunApplet();
+
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+
+protected:
+ void resizeEvent(QResizeEvent*);
+ void positionChange(KPanelApplet::Position);
+
+protected slots:
+ void run_command(const QString&);
+ void popup_combo();
+ void setButtonText();
+
+private:
+ KHistoryCombo *_input;
+ KURIFilterData *_filterData;
+ QLabel *_label;
+ QPushButton *_btn;
+ QHBox *_hbox;
+};
+
+#endif
diff --git a/kicker/applets/swallow/Makefile.am b/kicker/applets/swallow/Makefile.am
new file mode 100644
index 000000000..1b88a0c10
--- /dev/null
+++ b/kicker/applets/swallow/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = $(all_includes)
+
+kde_module_LTLIBRARIES = swallow_panelapplet.la
+
+swallow_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+swallow_panelapplet_la_LIBADD = $(LIB_KDEUI) $(LIB_KIO)
+
+swallow_panelapplet_la_SOURCES = swallow.cpp prefwidgetbase.ui prefwidget.cpp
+
+noinst_HEADERS = swallow.h prefwidget.h prefwidgetbase.h
+
+swallow_panelapplet_la_METASOURCES = AUTO
+
+applnk_DATA = swallowapplet.desktop
+applnkdir = $(kde_datadir)/kicker/applets
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp -o $(podir)/swallowapplet.pot
diff --git a/kicker/applets/swallow/prefwidget.cpp b/kicker/applets/swallow/prefwidget.cpp
new file mode 100644
index 000000000..2e443a6b2
--- /dev/null
+++ b/kicker/applets/swallow/prefwidget.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2001 Daniel Molkentin <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ */
+
+#include <keditlistbox.h>
+
+#include "prefwidget.h"
+
+PreferencesWidget::PreferencesWidget( SwallowCommandList *swc, QWidget *parent )
+ : PreferencesWidgetBase(parent)
+{
+
+ SwallowCommandListIterator it( *swc );
+ SwallowCommand *currentCL;
+ while ( ( currentCL = it.current() ) != 0 )
+ {
+ ++it;
+ klebDockApps->insertItem( currentCL->title );
+ }
+}
+/*
+PreferencesWidget::~PreferencesWidget()
+{
+}
+*/
+#include "prefwidget.moc"
diff --git a/kicker/applets/swallow/prefwidget.h b/kicker/applets/swallow/prefwidget.h
new file mode 100644
index 000000000..76ecce35e
--- /dev/null
+++ b/kicker/applets/swallow/prefwidget.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2001 Daniel Molkentin <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ */
+
+#ifndef PREFWIDGET_H
+#define PREFWIDGET_H
+
+#include "prefwidgetbase.h"
+#include "swallow.h"
+
+class PreferencesWidget : public PreferencesWidgetBase
+{
+ Q_OBJECT
+
+public:
+ PreferencesWidget( SwallowCommandList* swc, QWidget* parent = 0 );
+// ~PreferencesWidget();
+
+};
+
+#endif
diff --git a/kicker/applets/swallow/prefwidgetbase.ui b/kicker/applets/swallow/prefwidgetbase.ui
new file mode 100644
index 000000000..bd2673efa
--- /dev/null
+++ b/kicker/applets/swallow/prefwidgetbase.ui
@@ -0,0 +1,134 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>PreferencesWidgetBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>PreferencesWidgetBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>409</width>
+ <height>366</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>AppDock Preferences</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="3" column="2">
+ <property name="name">
+ <cstring>PushButton1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="on">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KEditListBox" row="1" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>klebDockApps</cstring>
+ </property>
+ <property name="title">
+ <string>Applications to Dock</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox" row="2" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Entry Details</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>leName</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Command &amp;line:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>urlCommandLine</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>leName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Specify a short name for the application.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>urlCommandLine</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Specify a path to the application. This may include startup parameters. You can use the folder icon to select the application.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QPushButton" row="3" column="3">
+ <property name="name">
+ <cstring>PushButton2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<includes>
+ <include location="local" impldecl="in implementation">kdialog.h</include>
+</includes>
+<layoutdefaults spacing="3" margin="6"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>keditlistbox.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kicker/applets/swallow/swallow.cpp b/kicker/applets/swallow/swallow.cpp
new file mode 100644
index 000000000..b1224986b
--- /dev/null
+++ b/kicker/applets/swallow/swallow.cpp
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2000 Matthias Elter <[email protected]>
+ * 2000 Carsten Pfeiffer <[email protected]>
+ * based on keyes (C) 1999 by Jerome Tollet <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ */
+
+
+#include <stdlib.h>
+
+#include <qlayout.h>
+#include <qstringlist.h>
+
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kshell.h>
+#include <kwin.h>
+#include <kwinmodule.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "swallow.h"
+#include "prefwidget.h"
+
+template class QPtrList<SwallowApp>;
+typedef QPtrListIterator<SwallowApp> SwallowAppListIterator;
+template class QPtrList<SwallowCommand>;
+
+
+// init static variables
+SwallowAppList * SwallowApplet::appList = 0L;
+SwallowAppList * SwallowApplet::embeddedList = 0L;
+KWinModule * SwallowApplet::wModule = 0L;
+SwallowApplet * SwallowApplet::self = 0L;
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile) {
+ return new SwallowApplet(configFile, parent, "kswallow applet");
+ }
+}
+
+
+SwallowApplet::SwallowApplet( const QString& configFile,
+ QWidget *parent, const char *name )
+ : KPanelApplet( configFile, Normal, Preferences, parent, name )
+{
+ resize( 30, 30 );
+ kdDebug() << "**** constructing swallow applet (" << configFile << ") ****" << endl;
+ self = this;
+ m_swcList = new SwallowCommandList;
+ m_swcList->setAutoDelete( true );
+ wModule = new KWinModule(this);
+ embeddedList = new SwallowAppList;
+ embeddedList->setAutoDelete( false );
+ appList = new SwallowAppList;
+ appList->setAutoDelete( true );
+
+ QBoxLayout::Direction d = (orientation() == Horizontal) ?
+ QBoxLayout::LeftToRight : QBoxLayout::TopToBottom;
+ m_layout = new QBoxLayout( this, d, 0, 2 ); // make stretch configurable?
+ m_layout->setAutoAdd( false );
+
+ // read the config file and start all the configured apps
+ createApps( readConfig() );
+
+ if ( appList->count() == 0 ) {
+ if ( KMessageBox::questionYesNo(0L, i18n("There is no swallowed application, "
+ "do you want to configure or quit?"), i18n("No Swallowed Application"),
+ KGuiItem(i18n("Configure"),"configure"), KStdGuiItem::quit()) == KMessageBox::Yes )
+ preferences();
+ else {
+ delete this;
+ ::exit(0);
+ }
+ }
+
+ emit updateLayout();
+}
+
+SwallowApplet::~SwallowApplet()
+{
+ kdDebug() << "********************** DELETING ************************" << endl;
+
+ delete m_swcList;
+ delete embeddedList;
+ delete appList;
+ delete wModule;
+ wModule = 0L;
+}
+
+
+SwallowCommandList* SwallowApplet::readConfig()
+{
+ m_swcList->clear();
+ KConfig *kc = config();
+
+ kc->setGroup("General");
+ int count = kc->readNumEntry("Number of apps");
+ kdDebug() << "*** Registered " << count << " App(s) to be swallow'ed!" << endl;
+ QString group = "SwallowApp %1";
+ QString title, cmd;
+ ushort errors = 0;
+ SwallowCommand *swc = 0L;
+
+ for ( int i = 1; i <= count; i++ ) {
+ kc->setGroup( group.arg(i) );
+ cmd = kc->readPathEntry("Commandline");
+ title = kc->readEntry("Window title");
+ kdDebug() << "*** Found Entry: Cmd-Line: " << cmd << " Window-Title: " << title << endl;
+
+ if ( !cmd.isEmpty() && !title.isEmpty() ) {
+ swc = new SwallowCommand;
+ swc->cmdline = cmd;
+ swc->title = title;
+ m_swcList->append( swc );
+ }
+ // remember items with non-null cmdline or title,
+ // discard items with empty cmdline and empty title
+ else if ( !(cmd.isEmpty() && title.isEmpty()) )
+ errors++;
+ }
+
+ if ( errors > 0 ) {
+ QString entry = (errors == 1) ? i18n("entry") : i18n("entries");
+ if ( KMessageBox::questionYesNo(0L, i18n("I found %1 invalid/incomplete %2\nin the configuration file.\n\nBoth the window title and the commandline\n of the to be swallowed application\nare required.\n\n.Do you want to correct this?").arg(errors).arg(entry), i18n("Configuration Error"),i18n("Correct"),i18n("Ignore Error")) == KMessageBox::Yes)
+ preferences();
+ }
+
+ return m_swcList;
+}
+
+
+void SwallowApplet::createApps( SwallowCommandList* list )
+{
+ SwallowApp *app = 0L;
+
+ SwallowCommandListIterator it( *list );
+ while ( (it.current()) ) {
+ app = new SwallowApp( it.current(), this );
+ app->hide();
+ connect( app, SIGNAL( embedded(SwallowApp *)),
+ SLOT( embedded(SwallowApp *)));
+ appList->append( app );
+ ++it;
+ kapp->processEvents();
+ }
+
+ m_layout->activate();
+}
+
+
+void SwallowApplet::embedded( SwallowApp *app )
+{
+ kdDebug() << " -> embedding " << app << ", current size is: " << width() << ", " << height() << endl;
+ if ( orientation() == Horizontal )
+ app->resize(height() * app->sizeRatio(), height() );
+ else
+ app->resize(width(), width() * app->sizeRatio());
+
+ kdDebug() << "--> ratio: " << app->sizeRatio() << endl;
+ kdDebug() << "**** " << app << " is embedded now, with (" << app->width() << ", " << app->height() << ")" << endl;
+
+ disconnect( app, SIGNAL( embedded(SwallowApp *)),
+ this, SLOT( embedded(SwallowApp *)));
+
+ embeddedList->append( app );
+
+ if ( orientation() == Horizontal )
+ resize( widthForHeight( height() ), height() );
+ else
+ resize( width(), heightForWidth( width() ));
+
+ m_layout->addWidget( app );
+ app->show();
+ updateGeometry();
+ emit updateLayout();
+}
+
+void SwallowApplet::preferences()
+{
+ PreferencesWidget *prefs = new PreferencesWidget(m_swcList,this);
+ prefs->show();
+}
+
+
+int SwallowApplet::widthForHeight(int he)
+{
+ kdDebug() << "**** width for h: " << he << endl;
+ int w = embeddedList->isEmpty() ? 30 : 0;
+ layoutApps();
+ SwallowAppListIterator it( *embeddedList );
+ while ( it.current() ) {
+ kdDebug() << "current: " << it.current()->width() << endl;
+ w += (it.current())->width();
+ ++it;
+ }
+
+ kdDebug() << "**** wfh: " << w << " : count: " << embeddedList->count() << endl;
+ return w;
+}
+
+
+int SwallowApplet::heightForWidth(int)
+{
+ int h = embeddedList->isEmpty() ? 30 : 0;
+ layoutApps();
+ SwallowAppListIterator it( *embeddedList );
+ while ( it.current() ) {
+ h += (it.current())->height();
+ ++it;
+ }
+
+ kdDebug() << "**** hfw: " << h << endl;
+ return h;
+}
+
+void SwallowApplet::layoutApps()
+{
+ if ( KPanelApplet::orientation() == Horizontal )
+ m_layout->setDirection( QBoxLayout::LeftToRight );
+ else
+ m_layout->setDirection( QBoxLayout::TopToBottom );
+}
+
+
+void SwallowApplet::removeApplet( SwallowApp *app )
+{
+ embeddedList->removeRef( app );
+ appList->remove( app );
+ emit self->updateLayout();
+}
+
+
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+
+
+static void parseCommand(KProcess *proc, QString cmd)
+{
+ int pos;
+
+ cmd += " ";
+
+ pos = cmd.find(' ');
+ *proc << cmd.left(pos);
+ cmd.remove(0,pos);
+ cmd = cmd.stripWhiteSpace();
+ *proc << KShell::splitArgs(cmd, KShell::TildeExpand | KShell::AbortOnMeta);
+}
+
+
+SwallowApp::SwallowApp(const SwallowCommand *swc, QWidget* parent,
+ const char* /* name */)
+ : QXEmbed( parent )
+{
+ wh_ratio = 1;
+ setAutoDelete( false );
+ QXEmbed::initialize();
+
+ winTitle = swc->title;
+ connect(SwallowApplet::winModule(), SIGNAL(windowAdded(WId)),
+ this, SLOT(windowAdded(WId)));
+
+ if (!swc->cmdline.isEmpty()) {
+ KProcess *process = new KProcess;
+ parseCommand(process, swc->cmdline);
+
+ // move window out of sight
+ // *process << "-geometry";
+ // *process << QString("32x32+%1+%2").arg(kapp->desktop()->width()).arg(kapp->desktop()->height());
+
+ connect(process, SIGNAL(processExited(KProcess*)),
+ this, SLOT(processExited(KProcess*)));
+
+ process->start();
+ }
+}
+
+
+SwallowApp::~SwallowApp()
+{
+ delete process;
+}
+
+
+void SwallowApp::windowAdded(WId win)
+{
+ // determine title of newly mapped window
+ XTextProperty nameProp;
+ XGetWMName(qt_xdisplay(), win, &nameProp);
+ char **names;
+ int count;
+ XTextPropertyToStringList(&nameProp, &names, &count);
+ if (count < 1) {
+ XFreeStringList(names);
+ return;
+ }
+
+ // is this our client?
+ if (winTitle == names[0]) {
+ kdDebug()<< "embedding window with title: "<<winTitle.latin1() << endl;
+
+ QRect r = KWin::windowInfo(win).geometry();
+ int h = r.height();
+ if ( h == 0 ) h = 1;
+ wh_ratio = (float) r.width() / (float) h;
+ kdDebug() << " - - - win is: " << r.width() << ", " << r.height() << endl;
+ resize( r.width(), r.height() );
+
+ embed(win);
+ XReparentWindow(qt_xdisplay(), win, winId(), 0, 0);
+
+ disconnect(SwallowApplet::winModule(), SIGNAL(windowAdded(WId)),
+ this, SLOT(windowAdded(WId)));
+
+ emit embedded( this );
+ }
+
+ XFreeStringList(names);
+}
+
+
+void SwallowApp::processExited(KProcess *)
+{
+ SwallowApplet::removeApplet( this ); // also deletes this app
+}
+
+#include "swallow.moc"
diff --git a/kicker/applets/swallow/swallow.h b/kicker/applets/swallow/swallow.h
new file mode 100644
index 000000000..8e472f415
--- /dev/null
+++ b/kicker/applets/swallow/swallow.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2000 Matthias H�lzer-Kl�pfel <[email protected]>
+ 2000 Carsten Pfeiffer <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ */
+
+#ifndef __swallow_h__
+#define __swallow_h__
+
+
+#include <qevent.h>
+#include <qptrlist.h>
+#include <qxembed.h>
+
+#include <kpanelapplet.h>
+
+class QBoxLayout;
+class KConfig;
+class KProcess;
+class KWinModule;
+
+class SwallowApp;
+
+typedef struct _SwallowCommand {
+ QString cmdline;
+ QString title;
+} SwallowCommand;
+
+typedef QPtrList<SwallowCommand> SwallowCommandList;
+typedef QPtrListIterator<SwallowCommand> SwallowCommandListIterator;
+typedef QPtrList<SwallowApp> SwallowAppList;
+
+class SwallowApplet : public KPanelApplet
+{
+ Q_OBJECT
+
+public:
+ SwallowApplet( const QString& configFile, QWidget *parent,
+ const char *name = 0L );
+ ~SwallowApplet();
+
+ // returns 0L if we don't have a SwallowApplet object yet,
+ // but who cares
+ static KWinModule * winModule() { return wModule; }
+ static void removeApplet( SwallowApp * );
+
+public: // for KPanelApplet
+ int widthForHeight( int w );
+ int heightForWidth( int h );
+
+ void windowAdded(WId win);
+ void processExited(KProcess *proc);
+
+public slots:
+ virtual void preferences();
+
+private slots:
+ void embedded( SwallowApp * );
+
+private:
+ void layoutApps();
+ SwallowCommandList* readConfig();
+ void createApps( SwallowCommandList * );
+
+
+ static SwallowApplet *self;
+ static SwallowAppList *appList;
+ static SwallowAppList *embeddedList;
+ static KWinModule *wModule;
+
+ SwallowCommandList * m_swcList;
+ QBoxLayout *m_layout;
+
+};
+
+
+class SwallowApp : public QXEmbed
+{
+ Q_OBJECT
+
+public:
+ SwallowApp( const SwallowCommand * swc, QWidget* parent = 0,
+ const char* name = 0);
+ ~SwallowApp();
+
+ float sizeRatio() const { return wh_ratio; }
+
+signals:
+ void embedded( SwallowApp * );
+
+protected slots:
+ void windowAdded(WId win);
+ void processExited(KProcess *proc);
+
+private:
+ KProcess *process;
+ QString winTitle;
+ float wh_ratio;
+
+};
+
+#endif // __swallow_h__
diff --git a/kicker/applets/swallow/swallowapplet.desktop b/kicker/applets/swallow/swallowapplet.desktop
new file mode 100644
index 000000000..2ea055461
--- /dev/null
+++ b/kicker/applets/swallow/swallowapplet.desktop
@@ -0,0 +1,142 @@
+[Desktop Entry]
+Type=Plugin
+Name=Swallow Applet
+Name[af]=Sluk Miniprogram
+Name[ar]=بريمج Swallow
+Name[az]=Batıq Proqramcıq
+Name[be]=Аплет праглынання
+Name[bn]=সোয়্যালো অ্যাপলেট
+Name[bs]=Applet - gutač
+Name[ca]=Applet contenidor
+Name[cs]=Pohlcovací applet
+Name[csb]=Aplet do zanurzaniô jinszëch
+Name[cy]=Rhaglennig Llyncu
+Name[da]=Swallow-panelprogram
+Name[de]=Einbettungsprogramm
+Name[el]=Ενσωμάτωση μικροεφαρμογής
+Name[eo]=Sistemaplikaĵetejo
+Name[es]=Miniaplicación contenedora
+Name[et]=Põimimise aplett
+Name[eu]=Swallow appleta
+Name[fa]=برنامک Swallow
+Name[fi]=Upotussovelma
+Name[fr]=Applet englobante
+Name[fy]=Ynslúte applet
+Name[gl]=Applet Swallow
+Name[he]=יישומון מעגן
+Name[hi]=स्वालो ऐपलेट
+Name[hr]=Progutaj aplet
+Name[hu]=Elnyelő kisalkalmazás
+Name[is]=Gleypi smáforrit
+Name[it]=Applet che ingloba
+Name[ja]=Swallow アプレット
+Name[ka]=მშთანთქავი აპლეტი
+Name[kk]=Сіңіру апплеті
+Name[km]=អាប់ភ្លេត Swallow
+Name[lt]=Swallow priemonė
+Name[mk]=Аплет „Голтни“
+Name[mn]=Шигтгэгч-програм
+Name[ms]=Aplet Lelayang
+Name[mt]=Applet "Swallow"
+Name[nb]=Svelge-panelprogram
+Name[nds]=Lüttprogramm för't Inbetten
+Name[ne]=स्वालो एप्लेट
+Name[nl]=Inbeddingsapplet
+Name[nn]=Svelge-applet
+Name[nso]=Applet ya Mometso
+Name[pa]=ਸਵਾਲੋਓ ਐਪਲਿਟ
+Name[pl]=Programik do zanurzania innych
+Name[pt]='Applet' Swallow
+Name[pt_BR]=Mini-aplicativo de integração
+Name[ro]=Miniaplicație de înglobare
+Name[ru]=Аплет поглощения
+Name[rw]=Kwemera Apuleti
+Name[se]=Njeallan-prográmmaš
+Name[sk]=Pohlcovací applet
+Name[sl]=Vstavek z lastovko
+Name[sr]=Аплет за гутање
+Name[sr@Latn]=Aplet za gutanje
+Name[sv]=Uppslukande miniprogram
+Name[ta]=உள்வாங்கும் சிறுநிரல்
+Name[te]=స్వాలొ అప్లేట్
+Name[tg]=Барномаи қурт доданӣ
+Name[tr]=Batık Programcık
+Name[tt]=Yotu Applete
+Name[uk]=Аплет Swallow
+Name[ven]=Apulete ya Swallow
+Name[vi]=Tiểu ứng dụng Chim nhạn
+Name[wa]=Aplikete avaleuse
+Name[zh_CN]=Swallow 小程序
+Name[zh_TW]=Swallow 面板小程式
+Name[zu]=I-Applet yokugwinya
+Comment=The swallow panel applet
+Comment[af]=Die sluk paneel miniprogram
+Comment[az]=Batıq panel
+Comment[be]=Аплет праглынання для панэлі
+Comment[bn]=সোয়্যালো প্যানেল অ্যাপলেট
+Comment[bs]=Applet koji "guta" aplikacije u panel
+Comment[ca]=L'applet contenidor del plafó
+Comment[cs]=Pohlcovací applet pro panel
+Comment[csb]=Aplet dlô panelu jaczi ùsôdzô òbéńdã do zanurzaniô jinszëch
+Comment[cy]=Rhaglennig llyncu i'r panel
+Comment[da]=Swallow-panelprogrammet
+Comment[de]=Leiste zum Einbetten von X-Anwendungen
+Comment[el]=Μικροεφαρμογή του πίνακα που "καταπίνει"
+Comment[eo]=La panelaplikaĵeto enhavanta la dokitajn programojn
+Comment[es]=La miniaplicación del panel contenedora
+Comment[et]=Paneelil töötav põimimise aplett
+Comment[eu]=Swallow paneleko appleta
+Comment[fa]=برنامک تابلوی Swallow
+Comment[fi]=Paneelin upotussovelma
+Comment[fr]=L'applet englobante du tableau de bord
+Comment[fy]=Applet foar it ynlúte fan X-toepassingen
+Comment[gl]=O applet swallow para o painel
+Comment[he]=יישומון מעגן עבור הלוח
+Comment[hi]=स्वालो फलक ऐपलेट
+Comment[hr]=Gutač apleta za ploču
+Comment[hu]=Egy elnyelő panel-kisalkalmazás
+Comment[id]=Aplet panel swallow
+Comment[is]=Gleypispjalds smáforritið
+Comment[it]=Applet per inglobare le applicazioni nel pannello
+Comment[ja]=swallow パネルアプレット
+Comment[ka]=პანელის მშთანთქავი აპლეტი
+Comment[kk]=Сіңіру панель апплеті
+Comment[km]=អាប់ភ្លេត​បន្ទះ swallow
+Comment[lt]=Swallow pulto priemonė
+Comment[mk]=Аплетот „Голтни“ од панелот
+Comment[mn]=X-програмуудыг холбогч програм
+Comment[ms]=Aplet panel lelayang
+Comment[mt]=Applet għall-pannell "swallow"
+Comment[nb]=Et panelprogram som svelger andre panelprogrammer
+Comment[nds]=Paneel för't Inbetten vun X-Programmen
+Comment[ne]=स्वालो प्यानल एप्लेट
+Comment[nl]=Applet voor het inbedden van X-toepassingen
+Comment[nn]=Svelge-panelappleten
+Comment[nso]=Applet ya panel ya mometso
+Comment[pa]=ਸਵਾਲੋਓ ਪੈਨਲ ਐਪਲਿਟ
+Comment[pl]=Programik dla panelu tworzący przestrzeń do zanurzania innych
+Comment[pt]=A 'applet' do painel swallow
+Comment[pt_BR]=Mini-aplicativo de integração para o painel
+Comment[ro]=Miniaplicație de panou pentru înglobare altor programe
+Comment[ru]=Аплет панели поглощения
+Comment[rw]=Apuleti y'umwanya kumira
+Comment[se]=Njeallan-panelprográmmaš
+Comment[sk]=Pohlcovací applet pre panel
+Comment[sl]=Vstavek lastovke za na pult
+Comment[sr]=Аплет панела за гутање
+Comment[sr@Latn]=Aplet panela za gutanje
+Comment[sv]=Uppslukande miniprogram för panelen
+Comment[ta]=உள்வாங்கும் பலக சிறுநிரல்
+Comment[tg]=Барномаи қурт додани сафҳа
+Comment[th]=แอพเพล็ต swallow
+Comment[tr]=Batık panel
+Comment[tt]=Yotuçı taqta applete
+Comment[uk]=Аплет панелі swallow
+Comment[vi]=Tiểu ứng dụng chạy bảng điều khiển chim nhạn
+Comment[wa]=L' aplikete avaleuse do scriftôr
+Comment[xh]=I window eneenkcukacha ye swallow applet
+Comment[zh_CN]=Swallow 面板小程序
+Comment[zh_TW]=swallow 面板小程式
+Comment[zu]=I-applet lewindi lemininingwane lokugwinya
+X-KDE-Library=swallow_panelapplet
+X-KDE-UniqueApplet=true
diff --git a/kicker/applets/systemtray/Makefile.am b/kicker/applets/systemtray/Makefile.am
new file mode 100644
index 000000000..849795a9e
--- /dev/null
+++ b/kicker/applets/systemtray/Makefile.am
@@ -0,0 +1,24 @@
+
+INCLUDES = -I$(top_srcdir)/kicker/libkicker $(all_includes)
+
+kde_module_LTLIBRARIES = systemtray_panelapplet.la
+
+systemtray_panelapplet_la_SOURCES = systemtrayapplet.cpp systemtrayapplet.skel
+
+systemtray_panelapplet_la_METASOURCES = AUTO
+noinst_HEADERS = systemtrayapplet.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = systemtrayapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+systemtray_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+systemtray_panelapplet_la_LIBADD = ../../libkicker/libkickermain.la $(LIB_KDEUI) $(LIB_KIO)
+
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/ksystemtrayapplet.pot
+
+srcdoc:
+ kdoc -a -p -H -d $$HOME/web/src/ksystemtrayapplet ksystemtrayapplet *.h -lqt -lkdecore -lkdeui -lkfile
diff --git a/kicker/applets/systemtray/systemtrayapplet.cpp b/kicker/applets/systemtray/systemtrayapplet.cpp
new file mode 100644
index 000000000..8ae502fb4
--- /dev/null
+++ b/kicker/applets/systemtray/systemtrayapplet.cpp
@@ -0,0 +1,1013 @@
+/*****************************************************************
+
+Copyright (c) 2000-2001 Matthias Ettrich <[email protected]>
+ 2000-2001 Matthias Elter <[email protected]>
+ 2001 Carsten Pfeiffer <[email protected]>
+ 2001 Martijn Klingens <[email protected]>
+ 2004 Aaron J. Seigo <[email protected]>
+
+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 <qpopupmenu.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qevent.h>
+#include <qstyle.h>
+#include <qpainter.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <krun.h>
+#include <kwinmodule.h>
+#include <kdialogbase.h>
+#include <kactionselector.h>
+#include <kiconloader.h>
+#include <kwin.h>
+
+#include "simplebutton.h"
+
+#include "systemtrayapplet.h"
+#include "systemtrayapplet.moc"
+
+#include <X11/Xlib.h>
+
+#define ICON_MARGIN 1
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("ksystemtrayapplet");
+ return new SystemTrayApplet(configFile, KPanelApplet::Normal,
+ KPanelApplet::Preferences, parent, "ksystemtrayapplet");
+ }
+}
+
+SystemTrayApplet::SystemTrayApplet(const QString& configFile, Type type, int actions,
+ QWidget *parent, const char *name)
+ : KPanelApplet(configFile, type, actions, parent, name),
+ m_showFrame(false),
+ m_showHidden(false),
+ m_expandButton(0),
+ m_settingsDialog(0),
+ m_iconSelector(0),
+ m_autoRetractTimer(0),
+ m_autoRetract(false),
+ m_iconSize(24),
+ m_layout(0)
+{
+ loadSettings();
+
+ setBackgroundOrigin(AncestorOrigin);
+
+ kwin_module = new KWinModule(this);
+
+ // kApplication notifies us of settings changes. added to support
+ // disabling of frame effect on mouse hover
+ kapp->dcopClient()->setNotifications(true);
+ connectDCOPSignal("kicker", "kicker", "configurationChanged()", "loadSettings()", false);
+
+ QTimer::singleShot(0, this, SLOT(initialize()));
+}
+
+void SystemTrayApplet::initialize()
+{
+ // register existing tray windows
+ const QValueList<WId> systemTrayWindows = kwin_module->systemTrayWindows();
+ bool existing = false;
+ for (QValueList<WId>::ConstIterator it = systemTrayWindows.begin();
+ it != systemTrayWindows.end(); ++it )
+ {
+ embedWindow(*it, true);
+ existing = true;
+ }
+
+ showExpandButton(!m_hiddenWins.isEmpty());
+
+ if (existing)
+ {
+ updateVisibleWins();
+ layoutTray();
+ }
+
+ // the KWinModule notifies us when tray windows are added or removed
+ connect( kwin_module, SIGNAL( systemTrayWindowAdded(WId) ),
+ this, SLOT( systemTrayWindowAdded(WId) ) );
+ connect( kwin_module, SIGNAL( systemTrayWindowRemoved(WId) ),
+ this, SLOT( updateTrayWindows() ) );
+
+ QCString screenstr;
+ screenstr.setNum(qt_xscreen());
+ QCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr;
+
+ Display *display = qt_xdisplay();
+
+ net_system_tray_selection = XInternAtom(display, trayatom, false);
+ net_system_tray_opcode = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", false);
+
+ // Acquire system tray
+ XSetSelectionOwner(display,
+ net_system_tray_selection,
+ winId(),
+ CurrentTime);
+
+ WId root = qt_xrootwin();
+
+ if (XGetSelectionOwner (display, net_system_tray_selection) == winId())
+ {
+ XClientMessageEvent xev;
+
+ xev.type = ClientMessage;
+ xev.window = root;
+
+ xev.message_type = XInternAtom (display, "MANAGER", False);
+ xev.format = 32;
+ xev.data.l[0] = CurrentTime;
+ xev.data.l[1] = net_system_tray_selection;
+ xev.data.l[2] = winId();
+ xev.data.l[3] = 0; /* manager specific data */
+ xev.data.l[4] = 0; /* manager specific data */
+
+ XSendEvent (display, root, False, StructureNotifyMask, (XEvent *)&xev);
+ }
+
+ setBackground();
+}
+
+SystemTrayApplet::~SystemTrayApplet()
+{
+ for (TrayEmbedList::const_iterator it = m_hiddenWins.constBegin();
+ it != m_hiddenWins.constEnd();
+ ++it)
+ {
+ delete *it;
+ }
+
+ for (TrayEmbedList::const_iterator it = m_shownWins.constBegin();
+ it != m_shownWins.constEnd();
+ ++it)
+ {
+ delete *it;
+ }
+
+ KGlobal::locale()->removeCatalogue("ksystemtrayapplet");
+}
+
+bool SystemTrayApplet::x11Event( XEvent *e )
+{
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+ if ( e->type == ClientMessage ) {
+ if ( e->xclient.message_type == net_system_tray_opcode &&
+ e->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
+ if( isWinManaged( (WId)e->xclient.data.l[2] ) ) // we already manage it
+ return true;
+ embedWindow( e->xclient.data.l[2], false );
+ layoutTray();
+ return true;
+ }
+ }
+ return KPanelApplet::x11Event( e ) ;
+}
+
+void SystemTrayApplet::preferences()
+{
+ if (m_settingsDialog)
+ {
+ m_settingsDialog->show();
+ m_settingsDialog->raise();
+ return;
+ }
+
+ m_settingsDialog = new KDialogBase(0, "systrayconfig",
+ false, i18n("Configure System Tray"),
+ KDialogBase::Ok | KDialogBase::Apply | KDialogBase::Cancel,
+ KDialogBase::Ok, true);
+ m_settingsDialog->resize(450, 400);
+ connect(m_settingsDialog, SIGNAL(applyClicked()), this, SLOT(applySettings()));
+ connect(m_settingsDialog, SIGNAL(okClicked()), this, SLOT(applySettings()));
+ connect(m_settingsDialog, SIGNAL(finished()), this, SLOT(settingsDialogFinished()));
+
+ m_iconSelector = new KActionSelector(m_settingsDialog);
+ m_iconSelector->setAvailableLabel(i18n("Visible icons:"));
+ m_iconSelector->setSelectedLabel(i18n("Hidden icons:"));
+ m_iconSelector->setShowUpDownButtons(false);
+ m_settingsDialog->setMainWidget(m_iconSelector);
+
+ QListBox *shownListBox = m_iconSelector->availableListBox();
+ QListBox *hiddenListBox = m_iconSelector->selectedListBox();
+
+ TrayEmbedList::const_iterator it = m_shownWins.begin();
+ TrayEmbedList::const_iterator itEnd = m_shownWins.end();
+ for (; it != itEnd; ++it)
+ {
+ QString name = KWin::windowInfo((*it)->embeddedWinId()).name();
+ if(!shownListBox->findItem(name, Qt::ExactMatch | Qt::CaseSensitive))
+ {
+ shownListBox->insertItem(KWin::icon((*it)->embeddedWinId(), 22, 22, true), name);
+ }
+ }
+
+ it = m_hiddenWins.begin();
+ itEnd = m_hiddenWins.end();
+ for (; it != itEnd; ++it)
+ {
+ QString name = KWin::windowInfo((*it)->embeddedWinId()).name();
+ if(!hiddenListBox->findItem(name, Qt::ExactMatch | Qt::CaseSensitive))
+ {
+ hiddenListBox->insertItem(KWin::icon((*it)->embeddedWinId(), 22, 22, true), name);
+ }
+ }
+
+ m_settingsDialog->show();
+}
+
+void SystemTrayApplet::settingsDialogFinished()
+{
+ m_settingsDialog->delayedDestruct();
+ m_settingsDialog = 0;
+ m_iconSelector = 0;
+}
+
+void SystemTrayApplet::applySettings()
+{
+ if (!m_iconSelector)
+ {
+ return;
+ }
+
+ KConfig *conf = config();
+ conf->setGroup("HiddenTrayIcons");
+ QString name;
+
+ // use the following snippet of code someday to implement ordering
+ // of icons
+ /*
+ m_visibleIconList.clear();
+ QListBoxItem* item = m_iconSelector->availableListBox()->firstItem();
+ for (; item; item = item->next())
+ {
+ m_visibleIconList.append(item->text());
+ }
+ conf->writeEntry("Visible", m_visibleIconList);
+ selection.clear();*/
+
+ m_hiddenIconList.clear();
+ QListBoxItem* item = m_iconSelector->selectedListBox()->firstItem();
+ for (; item; item = item->next())
+ {
+ m_hiddenIconList.append(item->text());
+ }
+ conf->writeEntry("Hidden", m_hiddenIconList);
+ conf->sync();
+
+ TrayEmbedList::iterator it = m_shownWins.begin();
+ while (it != m_shownWins.end())
+ {
+ if (shouldHide((*it)->embeddedWinId()))
+ {
+ m_hiddenWins.append(*it);
+ it = m_shownWins.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ it = m_hiddenWins.begin();
+ while (it != m_hiddenWins.end())
+ {
+ if (!shouldHide((*it)->embeddedWinId()))
+ {
+ m_shownWins.append(*it);
+ it = m_hiddenWins.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ showExpandButton(!m_hiddenWins.isEmpty());
+
+ updateVisibleWins();
+ layoutTray();
+}
+
+void SystemTrayApplet::checkAutoRetract()
+{
+ if (!m_autoRetractTimer)
+ {
+ return;
+ }
+
+ if (!geometry().contains(mapFromGlobal(QCursor::pos())))
+ {
+ m_autoRetractTimer->stop();
+ if (m_autoRetract)
+ {
+ m_autoRetract = false;
+
+ if (m_showHidden)
+ {
+ retract();
+ }
+ }
+ else
+ {
+ m_autoRetract = true;
+ m_autoRetractTimer->start(2000, true);
+ }
+
+ }
+ else
+ {
+ m_autoRetract = false;
+ m_autoRetractTimer->start(250, true);
+ }
+}
+
+void SystemTrayApplet::showExpandButton(bool show)
+{
+ if (show)
+ {
+ if (!m_expandButton)
+ {
+ m_expandButton = new SimpleArrowButton(this);
+ m_expandButton->installEventFilter(this);
+ refreshExpandButton();
+
+ if (orientation() == Vertical)
+ {
+ m_expandButton->setFixedSize(width() - 4,
+ m_expandButton->sizeHint()
+ .height());
+ }
+ else
+ {
+ m_expandButton->setFixedSize(m_expandButton->sizeHint()
+ .width(),
+ height() - 4);
+ }
+ connect(m_expandButton, SIGNAL(clicked()),
+ this, SLOT(toggleExpanded()));
+
+ m_autoRetractTimer = new QTimer(this);
+ connect(m_autoRetractTimer, SIGNAL(timeout()),
+ this, SLOT(checkAutoRetract()));
+ }
+ else
+ {
+ refreshExpandButton();
+ }
+
+ m_expandButton->show();
+ }
+ else if (m_expandButton)
+ {
+ m_expandButton->hide();
+ }
+}
+
+void SystemTrayApplet::orientationChange( Orientation /*orientation*/ )
+{
+ refreshExpandButton();
+}
+
+void SystemTrayApplet::loadSettings()
+{
+ // set our defaults
+ setFrameStyle(NoFrame);
+ m_showFrame = false;
+
+ KConfig *conf = config();
+ conf->setGroup("General");
+
+ if (conf->readBoolEntry("ShowPanelFrame", false))
+ {
+ setFrameStyle(Panel | Sunken);
+ }
+
+ conf->setGroup("HiddenTrayIcons");
+ m_hiddenIconList = conf->readListEntry("Hidden");
+
+ //Note This setting comes from kdeglobal.
+ conf->setGroup("System Tray");
+ m_iconSize = conf->readNumEntry("systrayIconWidth", 22);
+}
+
+void SystemTrayApplet::systemTrayWindowAdded( WId w )
+{
+ if (isWinManaged(w))
+ {
+ // we already manage it
+ return;
+ }
+
+ embedWindow(w, true);
+ updateVisibleWins();
+ layoutTray();
+
+ if (m_showFrame && frameStyle() == NoFrame)
+ {
+ setFrameStyle(Panel|Sunken);
+ }
+}
+
+void SystemTrayApplet::embedWindow( WId w, bool kde_tray )
+{
+ TrayEmbed* emb = new TrayEmbed(kde_tray, this);
+ emb->setAutoDelete(false);
+
+ if (kde_tray)
+ {
+ static Atom hack_atom = XInternAtom( qt_xdisplay(), "_KDE_SYSTEM_TRAY_EMBEDDING", False );
+ XChangeProperty( qt_xdisplay(), w, hack_atom, hack_atom, 32, PropModeReplace, NULL, 0 );
+ emb->embed(w);
+ XDeleteProperty( qt_xdisplay(), w, hack_atom );
+ }
+ else
+ {
+ emb->embed(w);
+ }
+
+ if (emb->embeddedWinId() == 0) // error embedding
+ {
+ delete emb;
+ return;
+ }
+
+ connect(emb, SIGNAL(embeddedWindowDestroyed()), SLOT(updateTrayWindows()));
+ emb->getIconSize(m_iconSize);
+
+ if (shouldHide(w))
+ {
+ emb->hide();
+ m_hiddenWins.append(emb);
+ showExpandButton(true);
+ }
+ else
+ {
+ //emb->hide();
+ emb->setBackground();
+ emb->show();
+ m_shownWins.append(emb);
+ }
+}
+
+bool SystemTrayApplet::isWinManaged(WId w)
+{
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != lastEmb; ++emb)
+ {
+ if ((*emb)->embeddedWinId() == w) // we already manage it
+ {
+ return true;
+ }
+ }
+
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ {
+ if ((*emb)->embeddedWinId() == w) // we already manage it
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SystemTrayApplet::shouldHide(WId w)
+{
+ return m_hiddenIconList.find(KWin::windowInfo(w).name()) != m_hiddenIconList.end();
+}
+
+void SystemTrayApplet::updateVisibleWins()
+{
+ TrayEmbedList::const_iterator lastEmb = m_hiddenWins.end();
+ TrayEmbedList::const_iterator emb = m_hiddenWins.begin();
+
+ if (m_showHidden)
+ {
+ for (; emb != lastEmb; ++emb)
+ {
+ //(*emb)->hide();
+ (*emb)->setBackground();
+ (*emb)->show();
+ }
+ }
+ else
+ {
+ for (; emb != lastEmb; ++emb)
+ {
+ (*emb)->hide();
+ }
+ }
+}
+
+void SystemTrayApplet::toggleExpanded()
+{
+ if (m_showHidden)
+ {
+ retract();
+ }
+ else
+ {
+ expand();
+ }
+}
+
+void SystemTrayApplet::refreshExpandButton()
+{
+ if (!m_expandButton)
+ {
+ return;
+ }
+
+ Qt::ArrowType a;
+
+ if (orientation() == Vertical)
+ a = m_showHidden ? Qt::DownArrow : Qt::UpArrow;
+ else
+ a = (m_showHidden ^ kapp->reverseLayout()) ? Qt::RightArrow : Qt::LeftArrow;
+
+ m_expandButton->setArrowType(a);
+}
+
+void SystemTrayApplet::expand()
+{
+ m_showHidden = true;
+ refreshExpandButton();
+
+ updateVisibleWins();
+ layoutTray();
+
+ if (m_autoRetractTimer)
+ {
+ m_autoRetractTimer->start(250, true);
+ }
+}
+
+void SystemTrayApplet::retract()
+{
+ if (m_autoRetractTimer)
+ {
+ m_autoRetractTimer->stop();
+ }
+
+ m_showHidden = false;
+ refreshExpandButton();
+
+ updateVisibleWins();
+ layoutTray();
+}
+
+void SystemTrayApplet::updateTrayWindows()
+{
+ TrayEmbedList::iterator emb = m_shownWins.begin();
+ while (emb != m_shownWins.end())
+ {
+ WId wid = (*emb)->embeddedWinId();
+ if ((wid == 0) ||
+ ((*emb)->kdeTray() &&
+ !kwin_module->systemTrayWindows().contains(wid)))
+ {
+ (*emb)->deleteLater();
+ emb = m_shownWins.erase(emb);
+ }
+ else
+ {
+ ++emb;
+ }
+ }
+
+ emb = m_hiddenWins.begin();
+ while (emb != m_hiddenWins.end())
+ {
+ WId wid = (*emb)->embeddedWinId();
+ if ((wid == 0) ||
+ ((*emb)->kdeTray() &&
+ !kwin_module->systemTrayWindows().contains(wid)))
+ {
+ (*emb)->deleteLater();
+ emb = m_hiddenWins.erase(emb);
+ }
+ else
+ {
+ ++emb;
+ }
+ }
+
+ showExpandButton(!m_hiddenWins.isEmpty());
+ updateVisibleWins();
+ layoutTray();
+}
+
+int SystemTrayApplet::maxIconWidth() const
+{
+ int largest = m_iconSize;
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != lastEmb; ++emb)
+ {
+ if (*emb == 0)
+ {
+ continue;
+ }
+
+ int width = (*emb)->width();
+ if (width > largest)
+ {
+ largest = width;
+ }
+ }
+
+ if (m_showHidden)
+ {
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ {
+ int width = (*emb)->width();
+ if (width > largest)
+ {
+ largest = width;
+ }
+ }
+ }
+
+ return largest;
+}
+
+int SystemTrayApplet::maxIconHeight() const
+{
+ int largest = m_iconSize;
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != m_shownWins.end(); ++emb)
+ {
+ if (*emb == 0)
+ {
+ continue;
+ }
+
+ int height = (*emb)->height();
+ if (height > largest)
+ {
+ largest = height;
+ }
+ }
+
+ if (m_showHidden)
+ {
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != m_hiddenWins.end(); ++emb)
+ {
+ if (*emb == 0)
+ {
+ continue;
+ }
+
+ int height = (*emb)->height();
+ if (height > largest)
+ {
+ largest = height;
+ }
+ }
+ }
+
+ return largest;
+}
+
+bool SystemTrayApplet::eventFilter(QObject* watched, QEvent* e)
+{
+ if (watched == m_expandButton)
+ {
+ QPoint p;
+ if (e->type() == QEvent::ContextMenu)
+ {
+ p = static_cast<QContextMenuEvent*>(e)->globalPos();
+ }
+ else if (e->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ if (me->button() == Qt::RightButton)
+ {
+ p = me->globalPos();
+ }
+ }
+
+ if (!p.isNull())
+ {
+ QPopupMenu* contextMenu = new QPopupMenu(this);
+ contextMenu->insertItem(SmallIcon("configure"), i18n("Configure System Tray..."),
+ this, SLOT(configure()));
+
+ contextMenu->exec(static_cast<QContextMenuEvent*>(e)->globalPos());
+
+ delete contextMenu;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int SystemTrayApplet::widthForHeight(int h) const
+{
+ if (orientation() == Qt::Vertical)
+ {
+ return width();
+ }
+
+ int currentHeight = height();
+ if (currentHeight != h)
+ {
+ SystemTrayApplet* me = const_cast<SystemTrayApplet*>(this);
+ me->setMinimumSize(0, 0);
+ me->setMaximumSize(32767, 32767);
+ me->setFixedHeight(h);
+ }
+
+ return sizeHint().width();
+}
+
+int SystemTrayApplet::heightForWidth(int w) const
+{
+ if (orientation() == Qt::Horizontal)
+ {
+ return height();
+ }
+
+ int currentWidth = width();
+ if (currentWidth != w)
+ {
+ SystemTrayApplet* me = const_cast<SystemTrayApplet*>(this);
+ me->setMinimumSize(0, 0);
+ me->setMaximumSize(32767, 32767);
+ me->setFixedWidth(w);
+ }
+
+ return sizeHint().height();
+}
+
+void SystemTrayApplet::moveEvent( QMoveEvent* )
+{
+ setBackground();
+}
+
+
+void SystemTrayApplet::resizeEvent( QResizeEvent* )
+{
+ layoutTray();
+ // we need to give ourselves a chance to adjust our size before calling this
+ QTimer::singleShot(0, this, SIGNAL(updateLayout()));
+}
+
+void SystemTrayApplet::layoutTray()
+{
+ setUpdatesEnabled(false);
+
+ int iconCount = m_shownWins.count();
+
+ if (m_showHidden)
+ {
+ iconCount += m_hiddenWins.count();
+ }
+
+ /* heightWidth = height or width in pixels (depends on orientation())
+ * nbrOfLines = number of rows or cols (depends on orientation())
+ * line = what line to draw an icon in */
+ int i = 0, line, nbrOfLines, heightWidth;
+ bool showExpandButton = m_expandButton && m_expandButton->isVisibleTo(this);
+ delete m_layout;
+ m_layout = new QGridLayout(this, 1, 1, ICON_MARGIN, ICON_MARGIN);
+
+ if (m_expandButton)
+ {
+ if (orientation() == Vertical)
+ {
+ m_expandButton->setFixedSize(width() - 4, m_expandButton->sizeHint().height());
+ }
+ else
+ {
+ m_expandButton->setFixedSize(m_expandButton->sizeHint().width(), height() - 4);
+ }
+ }
+
+ // col = column or row, depends on orientation(),
+ // the opposite direction of line
+ int col = 0;
+
+ //
+ // The margin and spacing specified in the layout implies that:
+ // [-- ICON_MARGIN pixels --] [-- first icon --] [-- ICON_MARGIN pixels --] ... [-- ICON_MARGIN pixels --] [-- last icon --] [-- ICON_MARGIN pixels --]
+ //
+ // So, if we say that iconWidth is the icon width plus the ICON_MARGIN pixels spacing, then the available width for the icons
+ // is the widget width minus ICON_MARGIN pixels margin. Forgetting these ICON_MARGIN pixels broke the layout algorithm in KDE <= 3.5.9.
+ //
+ // This fix makes the workarounds in the heightForWidth() and widthForHeight() methods unneeded.
+ //
+
+ if (orientation() == Vertical)
+ {
+ int iconWidth = maxIconWidth() + ICON_MARGIN; // +2 for the margins that implied by the layout
+ heightWidth = width() - ICON_MARGIN;
+ // to avoid nbrOfLines=0 we ensure heightWidth >= iconWidth!
+ heightWidth = heightWidth < iconWidth ? iconWidth : heightWidth;
+ nbrOfLines = heightWidth / iconWidth;
+
+ if (showExpandButton)
+ {
+ m_layout->addMultiCellWidget(m_expandButton,
+ 0, 0,
+ 0, nbrOfLines - 1,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+ col = 1;
+ }
+
+ if (m_showHidden)
+ {
+ TrayEmbedList::const_iterator lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin();
+ emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, col, line,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin();
+ emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, col, line,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+ else // horizontal
+ {
+ int iconHeight = maxIconHeight() + ICON_MARGIN; // +2 for the margins that implied by the layout
+ heightWidth = height() - ICON_MARGIN;
+ heightWidth = heightWidth < iconHeight ? iconHeight : heightWidth; // to avoid nbrOfLines=0
+ nbrOfLines = heightWidth / iconHeight;
+
+ if (showExpandButton)
+ {
+ m_layout->addMultiCellWidget(m_expandButton,
+ 0, nbrOfLines - 1,
+ 0, 0,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+ col = 1;
+ }
+
+ if (m_showHidden)
+ {
+ TrayEmbedList::const_iterator lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, line, col,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin();
+ emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, line, col,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+
+ setUpdatesEnabled(true);
+ updateGeometry();
+ setBackground();
+}
+
+void SystemTrayApplet::paletteChange(const QPalette & /* oldPalette */)
+{
+ setBackground();
+}
+
+void SystemTrayApplet::setBackground()
+{
+ TrayEmbedList::const_iterator lastEmb;
+
+ lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != lastEmb; ++emb)
+ (*emb)->setBackground();
+
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ (*emb)->setBackground();
+}
+
+
+TrayEmbed::TrayEmbed( bool kdeTray, QWidget* parent )
+ : QXEmbed( parent ), kde_tray( kdeTray )
+{
+ hide();
+}
+
+void TrayEmbed::getIconSize(int defaultIconSize)
+{
+ QSize minSize = minimumSizeHint();
+
+ int width = minSize.width();
+ int height = minSize.height();
+
+ if (width < 1 || width > defaultIconSize)
+ width = defaultIconSize;
+ if (height < 1 || height > defaultIconSize)
+ height = defaultIconSize;
+
+ setFixedSize(width, height);
+ setBackground();
+}
+
+void TrayEmbed::setBackground()
+{
+ const QPixmap *pbg = parentWidget()->backgroundPixmap();
+
+ if (pbg)
+ {
+ QPixmap bg(width(), height());
+ bg.fill(parentWidget(), pos());
+ setPaletteBackgroundPixmap(bg);
+ setBackgroundOrigin(WidgetOrigin);
+ }
+ else
+ unsetPalette();
+
+ if (!isHidden())
+ {
+ XClearArea(x11Display(), embeddedWinId(), 0, 0, 0, 0, True);
+ }
+}
+
diff --git a/kicker/applets/systemtray/systemtrayapplet.desktop b/kicker/applets/systemtray/systemtrayapplet.desktop
new file mode 100644
index 000000000..ab737d83c
--- /dev/null
+++ b/kicker/applets/systemtray/systemtrayapplet.desktop
@@ -0,0 +1,158 @@
+[Desktop Entry]
+Type=Plugin
+Name=System Tray
+Name[af]=Stelsel Laai
+Name[ar]=لوحة النظام
+Name[az]=Sistem Rəfi
+Name[be]=Сістэмны латок
+Name[bg]=Системен панел
+Name[bn]=সিস্টেম ট্রে
+Name[br]=Barlenn ar reizhiad
+Name[ca]=Safata del sistema
+Name[cs]=Systémová část panelu
+Name[csb]=Systemòwi zabiérnik
+Name[cy]=Bar Tasgau
+Name[da]=Statusfelt
+Name[de]=Systemabschnitt der Kontrollleiste
+Name[el]=Πλαίσιο συστήματος
+Name[eo]=Sistempleto
+Name[es]=Bandeja del sistema
+Name[et]=Süsteemne dokk
+Name[eu]=Sistemaren azpila
+Name[fa]=سینی سیستم
+Name[fi]=Ilmoitusalue
+Name[fr]=Boîte à miniatures
+Name[fy]=Systeemfak
+Name[ga]=Tráidire an Chórais
+Name[gl]=Bandexa do Sistema
+Name[he]=מגש מערכת
+Name[hi]=तंत्र तश्तरी
+Name[hr]=Sistemska traka
+Name[hu]=Rendszertálca
+Name[id]=Tray Sistem
+Name[is]=Smáforritabakki
+Name[it]=Vassoio di sistema
+Name[ja]=システムトレイ
+Name[ka]=სისტემური პანელი
+Name[kk]=Жүйелік сөре
+Name[km]=ថាស​ប្រព័ន្ធ
+Name[ko]=시스템 트레이
+Name[lo]=ຖາດຂອງລະບົບ
+Name[lt]=Sistemos dėklas
+Name[lv]=Sistēmas Tekne
+Name[mk]=Системска лента
+Name[mn]=Удирдах самбарын системийн хэсэг
+Name[ms]=Dulang Sistem
+Name[mt]=Tray tas-Sistema
+Name[nb]=Systemkurv
+Name[nds]=Systeemafsnitt vun't Paneel
+Name[ne]=प्रणाली ट्रे
+Name[nl]=Systeemvak
+Name[nn]=Systemtrau
+Name[nso]=Tray ya System
+Name[oc]=Safata dèu sistemo
+Name[pa]=ਸਿਸਟਮ ਟਰੇ
+Name[pl]=Tacka systemowa
+Name[pt]=Bandeja do Painel
+Name[pt_BR]=Ícones do sistema
+Name[ro]=Tavă de sistem
+Name[ru]=Системный лоток
+Name[rw]=Igitwara cya Sisitemu
+Name[se]=Vuogádatgárcu
+Name[sk]=Systémová lišta
+Name[sl]=Sistemska vrstica
+Name[sr]=Системска касета
+Name[sr@Latn]=Sistemska kaseta
+Name[sv]=Systembricka
+Name[ta]=சாதன தட்டு
+Name[te]=వ్యవస్థ ట్రె
+Name[tg]=Сафҳаи идоракунии система
+Name[th]=ถาดของระบบ
+Name[tr]=Sistem Çekmecesi
+Name[tt]=Sistem Tiräse
+Name[uk]=Системний лоток
+Name[ven]=Thirei ya sistemu
+Name[vi]=Khay Hệ thống
+Name[wa]=Boesse ås imådjetes sistinme
+Name[xh]=Itreyi Yendlela yokusebenza
+Name[zh_CN]=系统托盘
+Name[zh_TW]=系統匣
+Name[zu]=Itreyi lesistimu
+
+Comment=The system tray panel applet
+Comment[af]=Die stelsel laai paneel miniprogram
+Comment[ar]=بريمج لوحة النظام
+Comment[az]=Bildiriş sahəsi panel appleti
+Comment[be]=Аплет сістэмнага латка
+Comment[bg]=Системен аплет за регистрация на програми и поддържане на иконите им
+Comment[bn]=সিস্টেম ট্রে প্যানেল অ্যাপলেট
+Comment[br]=Arloadig banell barlenn ar reizhiad
+Comment[bs]=Applet za system tray
+Comment[ca]=L'applet per al plafó de la safata del sistema
+Comment[cs]=Systémová část panelu určená pro applety
+Comment[csb]=Aplet systemòwégò zabiérnika dlô panelu
+Comment[cy]=Rhaglennig bar tasgau i'r panel
+Comment[da]=Statusfelt-panelprogrammet
+Comment[de]=Systemabschnitt der Kontrollleiste
+Comment[el]=Μικροεφαρμογή του πίνακα για το πλαίσιο συστήματος
+Comment[eo]=La sistempleta panelaplikaĵeto
+Comment[es]=La bandeja del sistema (miniaplicación del panel)
+Comment[et]=Paneelil töötav süsteemse doki aplett
+Comment[eu]=Sistemaren azpila (paneleko appleta)
+Comment[fa]=برنامک تابلوی سینی سیستم
+Comment[fi]=Paneelin ilmoitusalue
+Comment[fr]=L'applet de boîte à miniatures du tableau de bord
+Comment[fy]=It systeemfak panielapplet
+Comment[gl]=A applet do painel coa bandexa do sistema
+Comment[he]=יישומון מגש המערכת ללוח
+Comment[hi]=तंत्र तश्तरी फलक ऐपलेट
+Comment[hr]=Aplet ploče za sistemsku traku
+Comment[hu]=A rendszertálca alkalmazás
+Comment[id]=Applet panel tray sistem
+Comment[is]=Íforrit sem birtir lista yfir forrit sem eru í gangi
+Comment[it]=Applet del pannello per il vassoio di sistema
+Comment[ja]=システムトレイパネルアプレット
+Comment[ka]=სისტემური პანელის აპლეტი
+Comment[kk]=Жүйелік сөре панель апплеті
+Comment[km]=អាប់ភ្លេត​បន្ទះ​ថាស​ប្រព័ន្ធ
+Comment[lo]=ແອບແພັດຖາດຂອງລະບົບພາເນລ
+Comment[lt]=Sistemos dėklo pulto priemonė
+Comment[lv]=Sistēmas teknes paneļa aplets
+Comment[mk]=Панелски аплет од системската лента
+Comment[mn]=Удирдах самбарын системийн хэсэг
+Comment[ms]=Aplet panel dulang sistem
+Comment[mt]=Applet għat-tray tas-sistema
+Comment[nb]=Panelprogram for systemkurven
+Comment[nds]=Lüttprogramm för den Systeemafsnitt vun't Paneel
+Comment[ne]=प्रणाली ट्रे प्यानल एप्लेट
+Comment[nl]=De systeemvak paneelapplet
+Comment[nn]=Systemtrau-panelapplet
+Comment[nso]=Applet ya panel ya tray ya system
+Comment[oc]=L'aplet de plafon de la safata dèu sistemo
+Comment[pa]=ਸਿਸਟਮ ਟਰੇ ਪੈਨਲ ਐਪਲਿਟ
+Comment[pl]=Programik tacki systemowej dla panelu
+Comment[pt]=Uma 'applet' com a bandeja do painel
+Comment[pt_BR]=Mini-aplicativo de ícones do sistema
+Comment[ro]=Miniaplicația tavă de sistem pentru panou
+Comment[ru]=Аплет панели системного лотка
+Comment[rw]=Apuleti y'umwanya w'igitwara sisitemu
+Comment[se]=Vuogádatgárcu-panelprográmmaš
+Comment[sk]=Applet Systémová lišta
+Comment[sl]=Vstavek za sistemsko vrstico v pultu
+Comment[sr]=Аплет системске касете за панел
+Comment[sr@Latn]=Aplet sistemske kasete za panel
+Comment[sv]=Panelminiprogram för systembricka
+Comment[ta]=சாதன தட்டு பலக சிறுநிரல்
+Comment[tg]=Барномаи сафҳаи идоракунии системаи сафҳа
+Comment[th]=แอพเพล็ตถาดของระบบบนพาเนล
+Comment[tr]=Sistem çekmece paneli
+Comment[uk]=Аплет системного лотку панелі
+Comment[vi]=Tiểu ứng dụng có bảng điều khiển chứa khay hệ thống
+Comment[wa]=L' aplikete boesse ås imådjetes sistinme do scriftôr
+Comment[xh]=I applet yeqela lenjongo ethile yendlela yetreyi yokusebenza
+Comment[zh_CN]=系统托盘小程序
+Comment[zh_TW]=系統匣 (system tray) 面板小程式
+Comment[zu]=I-applet yewindi lemininingwane yetreyi lesistimu
+Icon=systemtray
+X-KDE-Library=systemtray_panelapplet
+X-KDE-UniqueApplet=true
diff --git a/kicker/applets/systemtray/systemtrayapplet.h b/kicker/applets/systemtray/systemtrayapplet.h
new file mode 100644
index 000000000..7afc18bf9
--- /dev/null
+++ b/kicker/applets/systemtray/systemtrayapplet.h
@@ -0,0 +1,126 @@
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+#ifndef __systemtrayapplet_h__
+#define __systemtrayapplet_h__
+
+#include <qvaluevector.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qxembed.h>
+
+#include <dcopobject.h>
+#include <kapplication.h>
+#include <kpanelapplet.h>
+
+#include "simplebutton.h"
+
+class QGridLayout;
+class QTimer;
+class KWinModule;
+class TrayEmbed;
+class KDialogBase;
+class KActionSelector;
+
+class SystemTrayApplet : public KPanelApplet, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+ typedef QValueVector<TrayEmbed*> TrayEmbedList;
+
+public:
+
+ SystemTrayApplet(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ ~SystemTrayApplet();
+
+ int widthForHeight(int h) const;
+ int heightForWidth(int w) const;
+ int maxIconWidth() const;
+ int maxIconHeight() const;
+
+ bool eventFilter(QObject* watched, QEvent* e);
+
+k_dcop:
+ void loadSettings();
+
+protected:
+ void resizeEvent(QResizeEvent*);
+ void moveEvent(QMoveEvent *);
+ bool x11Event( XEvent *e );
+ void preferences();
+ void orientationChange( Orientation );
+
+protected slots:
+ void initialize();
+ void systemTrayWindowAdded( WId );
+ void updateTrayWindows();
+ void layoutTray();
+ void paletteChange(const QPalette & /* oldPalette */);
+ void toggleExpanded();
+ void settingsDialogFinished();
+ void applySettings();
+ void checkAutoRetract();
+ void configure() { preferences(); }
+ void setBackground();
+
+private:
+ void embedWindow( WId w, bool kde_tray );
+ bool isWinManaged( WId w);
+ bool shouldHide( WId w);
+ void updateVisibleWins();
+ void expand();
+ void retract();
+ void showExpandButton(bool show);
+ void refreshExpandButton();
+
+ TrayEmbedList m_shownWins;
+ TrayEmbedList m_hiddenWins;
+ QStringList m_hiddenIconList;
+ KWinModule *kwin_module;
+ Atom net_system_tray_selection;
+ Atom net_system_tray_opcode;
+ bool m_showFrame;
+ bool m_showHidden;
+ SimpleArrowButton *m_expandButton;
+ KDialogBase* m_settingsDialog;
+ KActionSelector* m_iconSelector;
+ QTimer* m_autoRetractTimer;
+ bool m_autoRetract;
+ int m_iconSize;
+ QGridLayout* m_layout;
+};
+
+class TrayEmbed : public QXEmbed
+{
+ Q_OBJECT
+public:
+ TrayEmbed( bool kdeTray, QWidget* parent = NULL );
+ bool kdeTray() const { return kde_tray; }
+ void setBackground();
+ void getIconSize(int defaultIconSize);
+private:
+ bool kde_tray;
+};
+
+#endif
diff --git a/kicker/applets/taskbar/Makefile.am b/kicker/applets/taskbar/Makefile.am
new file mode 100644
index 000000000..35cb337e6
--- /dev/null
+++ b/kicker/applets/taskbar/Makefile.am
@@ -0,0 +1,22 @@
+INCLUDES = -I$(srcdir)/../../taskbar -I$(srcdir)/../../taskmanager -I$(srcdir)/../../libkicker $(all_includes)
+
+kde_module_LTLIBRARIES = taskbar_panelapplet.la
+
+taskbar_panelapplet_la_SOURCES = taskbarapplet.cpp
+
+taskbar_panelapplet_la_METASOURCES = AUTO
+taskbar_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+taskbar_panelapplet_la_LIBADD = $(LIB_KDEUI) ../../taskbar/libtaskbar.la ../../libkicker/libkickermain.la
+
+noinst_HEADERS = taskbarapplet.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = taskbarapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/ktaskbarapplet.pot
+
+srcdoc:
+ kdoc -a -p -H -d $$HOME/web/src/ktaskbarapplet ktaskbarapplet *.h -lqt -lkdecore -lkdeui -lkfile
diff --git a/kicker/applets/taskbar/taskbarapplet.cpp b/kicker/applets/taskbar/taskbarapplet.cpp
new file mode 100644
index 000000000..dc3428bf8
--- /dev/null
+++ b/kicker/applets/taskbar/taskbarapplet.cpp
@@ -0,0 +1,126 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <[email protected]>
+
+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 <qlayout.h>
+#include <qpalette.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "global.h"
+
+#include "taskbarcontainer.h"
+
+#include "taskbarapplet.h"
+#include "taskbarapplet.moc"
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init( QWidget *parent, const QString& configFile )
+ {
+ // FIXME: what about two taskbars? perhaps this should be inserted just once
+ KGlobal::locale()->insertCatalogue( "ktaskbarapplet" );
+ int options = 0;
+ if (kapp->authorizeControlModule("kde-kcmtaskbar.desktop"))
+ options = KPanelApplet::Preferences;
+ TaskbarApplet *taskbar = new TaskbarApplet( configFile, KPanelApplet::Stretch,
+ options, parent, "ktaskbarapplet" );
+ return taskbar;
+ }
+}
+
+TaskbarApplet::TaskbarApplet( const QString& configFile, Type type, int actions,
+ QWidget *parent, const char *name )
+ : KPanelApplet( configFile, type, actions, parent, name )
+{
+ setBackgroundOrigin( AncestorOrigin );
+ QHBoxLayout* layout = new QHBoxLayout( this );
+ container = new TaskBarContainer( false, this );
+ container->setBackgroundOrigin( AncestorOrigin );
+ connect(container, SIGNAL(containerCountChanged()), this, SIGNAL(updateLayout()));
+ layout->addWidget( container, 1 );
+ container->popupDirectionChange(popupDirection());
+}
+
+TaskbarApplet::~TaskbarApplet()
+{
+ // FIXME: what about TWO taskbars?
+ KGlobal::locale()->removeCatalogue( "ktaskbarapplet" );
+}
+
+int TaskbarApplet::widthForHeight(int h) const
+{
+ if (orientation() == Qt::Vertical)
+ {
+ return width();
+ }
+
+ // FIXME KDE4: when either TaskBarContainer or Applet smartens up
+ // simplify this
+ KPanelExtension::Position d = orientation() == Qt::Horizontal ?
+ KPanelExtension::Top :
+ KPanelExtension::Left;
+ return container->sizeHint(d, QSize(200, h)).width();
+}
+
+int TaskbarApplet::heightForWidth(int w) const
+{
+ if (orientation() == Qt::Horizontal)
+ {
+ return height();
+ }
+
+ // FIXME KDE4: when either TaskBarContainer or Applet smartens up
+ // simplify this
+ KPanelExtension::Position d = orientation() == Qt::Horizontal ?
+ KPanelExtension::Top :
+ KPanelExtension::Left;
+ return container->sizeHint(d, QSize(w, 200)).height();
+}
+
+void TaskbarApplet::preferences()
+{
+ container->preferences();
+}
+
+void TaskbarApplet::orientationChange( Orientation o )
+{
+ container->orientationChange( o );
+}
+
+void TaskbarApplet::popupDirectionChange( Direction d )
+{
+ container->popupDirectionChange( d );
+}
+
+void TaskbarApplet::moveEvent(QMoveEvent *)
+{
+ container->setBackground();
+}
+
+void TaskbarApplet::paletteChange(const QPalette &)
+{
+ container->setBackground();
+}
diff --git a/kicker/applets/taskbar/taskbarapplet.desktop b/kicker/applets/taskbar/taskbarapplet.desktop
new file mode 100644
index 000000000..d54e39832
--- /dev/null
+++ b/kicker/applets/taskbar/taskbarapplet.desktop
@@ -0,0 +1,138 @@
+[Desktop Entry]
+Type=Plugin
+Name=Taskbar
+Name[af]=Kasbar
+Name[ar]=شريط المهام
+Name[az]=Vəzifə Çubuğu
+Name[be]=Панэль заданняў
+Name[bg]=Панел за задачи
+Name[bn]=টাস্কবার
+Name[br]=Barrenn dleadoù
+Name[ca]=Barra de tasques
+Name[cs]=Pruh úloh
+Name[csb]=Lëstew dzejaniów
+Name[cy]=Bar tasgau
+Name[da]=Opgavelinje
+Name[de]=Fensterleiste
+Name[el]=Γραμμή εργασιών
+Name[eo]=Taskostrio
+Name[es]=Barra de tareas
+Name[et]=Tegumiriba
+Name[eu]=Ataza-barra
+Name[fa]=میله تکلیف
+Name[fi]=Tehtäväpalkki
+Name[fr]=Barre des tâches
+Name[fy]=Taakbalke
+Name[ga]=Tascbharra
+Name[gl]=Barra de tarefas
+Name[he]=שורת המשימות
+Name[hi]=कार्यपट्टी
+Name[hr]=Traka zadataka
+Name[hu]=Feladatlista
+Name[is]=Verkefnaslá
+Name[it]=Barra delle applicazioni
+Name[ja]=タスクバー
+Name[ka]=ამოცანათა პანელი
+Name[kk]=Тапсырмалар панелі
+Name[km]=របារ​ភារកិច្ច
+Name[ko]=작업 표시줄
+Name[lo]=ແຖບຫນ້າຕ່າງງານ
+Name[lt]=Užduočių juosta
+Name[lv]=Uzdevumjosla
+Name[mk]=Лента со програми
+Name[mn]=Цонхны самбар
+Name[nb]=Oppgavelinje
+Name[nds]=Programmbalken
+Name[ne]=कार्यपट्टी
+Name[nl]=Taakbalk
+Name[nn]=Oppgåvelinje
+Name[nso]=Bar ya Mosongwana
+Name[oc]=Barra de tasques
+Name[pa]=ਸੰਦਪੱਟੀ
+Name[pl]=Pasek zadań
+Name[pt]=Barra de Tarefas
+Name[pt_BR]=Barra de tarefas
+Name[ro]=Bara de procese
+Name[ru]=Панель задач
+Name[rw]=Umurongoibikorwa
+Name[se]=Bargoholga
+Name[sk]=Panel úloh
+Name[sl]=Opravilna vrstica
+Name[sr]=Трака задатака
+Name[sr@Latn]=Traka zadataka
+Name[ss]=Ibar yemsebenti
+Name[sv]=Aktivitetsfält
+Name[ta]=பணிப்பட்டி
+Name[tg]=Пайраҳаи вазифа
+Name[th]=แถบหน้าต่างงาน
+Name[tr]=Görev Çubuğu
+Name[tt]=Qoraltirä
+Name[uk]=Смужка задач
+Name[uz]=Vazifalar paneli
+Name[uz@cyrillic]=Вазифалар панели
+Name[ven]=Bara ya mushumo
+Name[vi]=Thanh tác vụ
+Name[wa]=Bår des bouyes
+Name[xh]=Ibar yomsebenzi
+Name[zh_CN]=任务条
+Name[zh_TW]=工作列
+Name[zu]=Ibha yemisebenzi
+
+Comment=The default task bar for window management
+Comment[af]=Die standaard taak balk vir venster bestuur
+Comment[be]=Стандартная панэль заданняў для кіравання вокнамі
+Comment[bg]=Системен панел за лентата със задачите
+Comment[bn]=উইণ্ডো ব্যবস্থাপনার জন্য ডিফল্ট টাস্ক বার
+Comment[bs]=Osnovni taskbar za upravljanje prozorima
+Comment[ca]=La barra de tasques per omissió per a la gestió de finestres
+Comment[cs]=Výchozí pruh úloh pro správu oken
+Comment[csb]=Domëslnô lëstew dzejaniów do sprôwianiô òknama
+Comment[da]=Standard-opgavelinje for vindueshåndtering
+Comment[de]=Standardmäßiger Bereich für offene Fenster in der Kontrollleiste
+Comment[el]=Η προκαθορισμένη γραμμή εργασιών για τη διαχείριση των παραθύρων
+Comment[eo]=La defaŭlta taskostrio por fenestroadministrado.
+Comment[es]=La barra de tareas predeterminada para gestionar las ventanas
+Comment[et]=Vaikimisi kasutatav tegumiriba akende halduseks
+Comment[eu]=Ataza-barra lehenetsia leihoen kudeaketarako
+Comment[fa]=میله تکلیف پیش‌فرض برای مدیریت پنجره
+Comment[fi]=Oletustyökalupalkki ikkunoiden hallintaan
+Comment[fr]=La barre des tâches gérant les fenêtres
+Comment[fy]=De standert taakbalke foar finsterbehear
+Comment[gl]=A barra de tarefas por defeito para xestión de fiestras.
+Comment[he]=ברירת מחדל של יישומון שורת משימות ללוח
+Comment[hr]=Zadana traka zadataka za upravljanje prozorima
+Comment[hu]=Az alapértelmezett feladatlista ablakkezeléshez
+Comment[is]=Sjálfgefna verkefnasláin fyrir gluggastjórnun
+Comment[it]=La barra delle applicazioni per la gestione delle finestre
+Comment[ja]=ウィンドウマネージャ用のデフォルトのタスクバー
+Comment[ka]=ფანჯრის მართვის ძირითადი პულტი
+Comment[kk]=Терезелерді басқару әдетті тапсырмалар панелі
+Comment[km]=របារ​ភារកិច្ច​លំនាំដើម សម្រាប់​គ្រប់គ្រង​បង្អួច
+Comment[lt]=Numatyta užduočių juostos langų tvarkymo priemonė
+Comment[mk]=Стандардната линија со задачи за менаџмент на прозорци
+Comment[nb]=Den vanlige oppgavelinja for å behandle vinduer
+Comment[nds]=Standard-Programmbalken för de Finsterpleeg
+Comment[ne]=सञ्झ्याल व्यवस्थापनका लागि पूर्वनिर्धारित उपकरणपट्टी
+Comment[nl]=De standaard taakbalk voor vensterbeheer
+Comment[nn]=Den vanlege oppgåvelinja for å handsama vindauge
+Comment[pa]=ਮੂਲ ਵੇਹੜੇ ਲਈ ਮੂਲ ਕੰਮ ਪੱਟੀ
+Comment[pl]=Domyślny pasek zadań do zarządzania oknami
+Comment[pt]=A barra de tarefas por omissão para a gestão de janelas
+Comment[pt_BR]=A barra de tarefas padrão para o gerenciamento de janelas.
+Comment[ro]=Bara de procese implicită pentru managementul ferestrelor
+Comment[ru]=Панель списка задач по умолчанию для управления окнами
+Comment[se]=Standárda bargoholga lásegieđaheami várás
+Comment[sk]=Prednastavený panel úloh pre správcu okien
+Comment[sl]=Privzeta opravilna vrstica za upravljanje z okni
+Comment[sr]=Подразумевана трака задатака за управљање прозорима
+Comment[sr@Latn]=Podrazumevana traka zadataka za upravljanje prozorima
+Comment[sv]=Det förvalda aktivitetsfältet för fönsterhantering
+Comment[th]=แอพเพล็ตถาดงานโดยปริยายของพาเนลสำหรับการจัดการหน้าต่าง
+Comment[tr]=Pencere yönetimi için öntanımlı görev çubuğu
+Comment[uk]=Типова панель задач для керування вікнами
+Comment[vi]=Thanh tác vụ mặc định cho trình quản lý cửa sổ
+Comment[wa]=Li prémetowe bår di bouyes do manaedjmint d' purnea
+Comment[zh_CN]=窗口管理的默认任务栏
+Comment[zh_TW]=預設的視窗管理工作列
+Icon=taskbar
+X-KDE-Library=taskbar_panelapplet
diff --git a/kicker/applets/taskbar/taskbarapplet.h b/kicker/applets/taskbar/taskbarapplet.h
new file mode 100644
index 000000000..f0842baca
--- /dev/null
+++ b/kicker/applets/taskbar/taskbarapplet.h
@@ -0,0 +1,56 @@
+/*****************************************************************
+
+Copyright (c) 2001 Matthias Elter <[email protected]>
+
+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 __taskbarapplet_h__
+#define __taskbarapplet_h__
+
+#include <kpanelapplet.h>
+
+class TaskBarContainer;
+class QPalette;
+
+class TaskbarApplet : public KPanelApplet
+{
+ Q_OBJECT
+
+public:
+ TaskbarApplet( const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0 );
+ ~TaskbarApplet();
+
+ int widthForHeight( int h ) const;
+ int heightForWidth( int w ) const;
+
+ void preferences();
+
+protected:
+ void moveEvent(QMoveEvent *);
+ void popupDirectionChange( Direction );
+ void orientationChange( Orientation );
+ void paletteChange(const QPalette &);
+
+private:
+ TaskBarContainer* container;
+};
+
+#endif
diff --git a/kicker/applets/trash/Makefile.am b/kicker/applets/trash/Makefile.am
new file mode 100644
index 000000000..a34f87d1c
--- /dev/null
+++ b/kicker/applets/trash/Makefile.am
@@ -0,0 +1,21 @@
+INCLUDES = -I$(top_srcdir)/libkonq -I$(top_srcdir)/kicker/libkicker $(all_includes)
+
+kde_module_LTLIBRARIES = trash_panelapplet.la
+trash_panelapplet_la_SOURCES = trashbutton.cpp trashapplet.cpp
+
+METASOURCES = AUTO
+
+noinst_HEADERS = \
+ trashapplet.h trashbutton.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = trashapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+trash_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+trash_panelapplet_la_LIBADD = ../../libkicker/libkickermain.la ../../../libkonq/libkonq.la $(LIB_KDEUI) $(LIB_KIO) $(LIB_KUTILS)
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/trashapplet.pot
+
diff --git a/kicker/applets/trash/trashapplet.cpp b/kicker/applets/trash/trashapplet.cpp
new file mode 100644
index 000000000..c27c4e281
--- /dev/null
+++ b/kicker/applets/trash/trashapplet.cpp
@@ -0,0 +1,165 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kaboutapplication.h>
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+
+#include "trashapplet.h"
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init( QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("trashapplet");
+ return new TrashApplet(configFile, KPanelApplet::Normal,
+ KPanelApplet::About, parent, "trashapplet");
+ }
+}
+
+TrashApplet::TrashApplet(const QString& configFile, Type type, int actions, QWidget *parent, const char *name)
+ : KPanelApplet(configFile, type, actions, parent, name), mButton(0)
+{
+ mButton = new TrashButton(this);
+
+ if (!parent)
+ setBackgroundMode(X11ParentRelative);
+
+ mButton->setPanelPosition(position());
+
+ setAcceptDrops(true);
+
+ mpDirLister = new KDirLister();
+
+ connect( mpDirLister, SIGNAL( clear() ),
+ this, SLOT( slotClear() ) );
+ connect( mpDirLister, SIGNAL( completed() ),
+ this, SLOT( slotCompleted() ) );
+ connect( mpDirLister, SIGNAL( deleteItem( KFileItem * ) ),
+ this, SLOT( slotDeleteItem( KFileItem * ) ) );
+
+ mpDirLister->openURL("trash:/");
+}
+
+TrashApplet::~TrashApplet()
+{
+ // disconnect the dir lister before quitting so as not to crash
+ // on kicker exit
+ disconnect( mpDirLister, SIGNAL( clear() ),
+ this, SLOT( slotClear() ) );
+ delete mpDirLister;
+ KGlobal::locale()->removeCatalogue("trashapplet");
+}
+
+void TrashApplet::about()
+{
+ KAboutData data("trashapplet",
+ I18N_NOOP("Trash Applet"),
+ "1.0",
+ I18N_NOOP("\"trash:/\" ioslave frontend applet"),
+ KAboutData::License_GPL_V2,
+ "(c) 2004, Kevin Ottens");
+
+ data.addAuthor("Kevin \'ervin\' Ottens",
+ I18N_NOOP("Maintainer"),
+ "ervin ipsquad net",
+ "http://ervin.ipsquad.net");
+
+ KAboutApplication dialog(&data);
+ dialog.exec();
+}
+
+int TrashApplet::widthForHeight( int height ) const
+{
+ if ( !mButton )
+ {
+ return height;
+ }
+
+ return mButton->widthForHeight( height );
+}
+
+int TrashApplet::heightForWidth( int width ) const
+{
+ if ( !mButton )
+ {
+ return width;
+ }
+
+ return mButton->heightForWidth( width );
+}
+
+void TrashApplet::resizeEvent( QResizeEvent * )
+{
+ if (!mButton)
+ {
+ return;
+ }
+
+ int size = 1;
+
+ size = std::max( size,
+ orientation() == Qt::Vertical ?
+ mButton->heightForWidth( width() ) :
+ mButton->widthForHeight( height() ) );
+
+
+ if(orientation() == Vertical)
+ {
+ mButton->resize( width(), size );
+ }
+ else
+ {
+ mButton->resize( size, height() );
+ }
+}
+
+void TrashApplet::slotClear()
+{
+ kdDebug()<<"MediaApplet::slotClear"<<endl;
+
+ mButton->setItemCount(0);
+}
+
+void TrashApplet::slotCompleted()
+{
+ mCount = mpDirLister->items(KDirLister::AllItems).count();
+ mButton->setItemCount( mCount );
+}
+
+void TrashApplet::slotDeleteItem(KFileItem *)
+{
+ mCount--;
+ mButton->setItemCount( mCount );
+}
+
+
+void TrashApplet::positionChange(Position p)
+{
+ mButton->setPanelPosition(p);
+}
+
+
+#include "trashapplet.moc"
diff --git a/kicker/applets/trash/trashapplet.desktop b/kicker/applets/trash/trashapplet.desktop
new file mode 100644
index 000000000..f1c1eff0a
--- /dev/null
+++ b/kicker/applets/trash/trashapplet.desktop
@@ -0,0 +1,138 @@
+[Desktop Entry]
+Type=Plugin
+Comment=Displays the trashcan and allows files to be dropped onto it
+Comment[af]=Vertoon die asblik en laat toe dat lêers in dit gegooi mag word
+Comment[ar]=يظهر سلّة المهملات و يسمح بإسقاط الملفات فيها
+Comment[be]=Паказвае сметніцу і дазваляе кідаць файлы ў яе
+Comment[bg]=Показване на кошчето и възможност за преместване на файлове в него
+Comment[bn]=আবর্জনার বাক্স দেখায়, যাতে ফাইল ড্রপ করা যায়
+Comment[bs]=Prikazuje kantu za smeće i omogućuje da se u nju bacaju datoteke
+Comment[ca]=Mostra la paperera i permet amollar-hi fitxers
+Comment[cs]=Zobrazuje koš a umožňuje do něj odhazovat soubory
+Comment[csb]=Wëskrzëniwô zamkłósc kòsza ë zezwôlô przecygac do niegò lopczi
+Comment[da]=Viser affaldsspanden og tillader at filer droppes på den
+Comment[de]=Mülleimerfunktion in der Kontrollleiste
+Comment[el]=Εμφανίζει τον Κάδο Απορριμμάτων και επιτρέπει την απόθεση αρχείων πάνω του
+Comment[en_GB]=Displays the wastebin and allows files to be dropped onto it
+Comment[eo]=Montras rubujon kaj ebligas dosiero-alfaligon
+Comment[es]=Muestra la papelera y permite tirar archivos en ella
+Comment[et]=Näitab prügikasti ning lubab faile sellesse visata
+Comment[eu]=Zakarontzia bistaratzen du, fitxategiak jauregitea lagunduz
+Comment[fa]=زباله‌دان را نمایش داده و به پرونده‌ها اجازه می‌دهد در آن بیفتند
+Comment[fi]=Näyttää roskakorin ja sallii tiedostojen pudottamisen siihen
+Comment[fr]=Affiche la corbeille et permet d'y déposer des fichiers
+Comment[fy]=Lit it jiskefet sjen en stiet ta dat triemmen fuortsmiten wurde troch se nei it byldkaike ta te slepen
+Comment[gl]=Mostra a papeleira e permite deitar ficheiros nela
+Comment[he]=מציג את פח האשפה ומאפשר לך לזרוק אליו קבצים
+Comment[hr]=Prikazuje kantu za otpad i omogućuje ispuštanje datoteka u nju
+Comment[hu]=Megjeleníti a szemétkosarat, lehetővé téve fájlok belehelyezését
+Comment[is]=Sýnir ruslakörfuna og leyfir að skrám sé sleppt á hana
+Comment[it]=Mostra il cestino e permette di trascinarci sopra i file
+Comment[ja]=ごみ箱を表示し、ごみ箱へのファイルのドロップを可能にします
+Comment[kk]=Өшірілгендер шелегін керсетіп, оған файлдарды тастауға мүмкіндік береді
+Comment[km]=បង្ហាញ​ធុង​សំរាម និង​អនុញ្ញាត​ឲ្យ​ទម្លាក់​ឯកសារ​លើ​វា
+Comment[lt]=Rodo šiukšliadėžę ir leidžia į ją tempiant numesti bylas
+Comment[mk]=Ја прикажува корпата и овозможува пуштање датотеки врз неа
+Comment[nb]=Viser papirkurven og lar deg legge filer i den
+Comment[nds]=Wiest de Affalltünn, Dateien köönt dor op droppt warrn.
+Comment[ne]=रद्दीटोकरी प्रदर्शन गर्छ र यसमा फाइलहरू राख्न अनुमति दिन्छ
+Comment[nl]=Toont de prullenbak en maakt het mogelijk bestanden weg te gooien door ze naar het pictogram te slepen
+Comment[nn]=Viser papirkorga og lèt deg leggja filer i henne
+Comment[pl]=Pokazuje kosz i pozwala przeciągać do niego pliki
+Comment[pt]=Mostra o caixote do lixo e permite largar ficheiros nele
+Comment[pt_BR]=Mostra a lixeira e permite que arquivos sejam arrastados até ela
+Comment[ro]=Afișează coșul de gunoi și permite aruncare fișierelor în acesta
+Comment[ru]=Показать на рабочем столе корзину для ненужных файлов
+Comment[sk]=Zobrazí odpadkový kôš a povolí vhodenie súborov do neho
+Comment[sl]=Prikaz ikone za Smeti, na katero lahko odvržete datoteke
+Comment[sr]=Приказује канту за смеће и омогућава испуштање фајлова на њу
+Comment[sr@Latn]=Prikazuje kantu za smeće i omogućava ispuštanje fajlova na nju
+Comment[sv]=Visar papperskorgen och tillåter att filer släpps på den
+Comment[th]=แสดงถังขยะและอนุญาตให้มีการปล่อยแฟ้มลงไปได้
+Comment[tr]=Çöp kutusunu gösterir ve dosyaların üzerine taşınmasına izin verir
+Comment[uk]=Показує смітник і дає змогу вкидати в нього файли
+Comment[vi]=Hiển thị thùng rác và cho phép thả các tập tin vào đó
+Comment[wa]=Håyneye l' batch et permete di mete des fitchîs å dvins
+Comment[zh_CN]=显示回收站,并允许您将文件拖至其上
+Comment[zh_TW]=顯示垃圾筒並且允許將檔案丟到其中
+Name=Trash
+Name[af]=Gemors
+Name[ar]=سلة النفايات
+Name[az]=Zibil
+Name[be]=Сметніца
+Name[bg]=Кошче
+Name[bn]=আবর্জনা
+Name[br]=Pod-lastez
+Name[bs]=Smeće
+Name[ca]=Paperera
+Name[cs]=Koš
+Name[csb]=Kòsz
+Name[cy]=Sbwriel
+Name[da]=Affald
+Name[de]=Mülleimer
+Name[el]=Κάδος απορριμμάτων
+Name[en_GB]=Wastebin
+Name[eo]=Rubujo
+Name[es]=Papelera
+Name[et]=Prügikast
+Name[eu]=Zaborra
+Name[fa]=زباله
+Name[fi]=Roskakori
+Name[fr]=Corbeille
+Name[fy]=Jiskefet
+Name[ga]=Bruscar
+Name[gl]=Lixo
+Name[he]=אשפה
+Name[hi]=रद्दी
+Name[hr]=Otpad
+Name[hsb]=Papjernik
+Name[hu]=Szemétkosár
+Name[is]=Rusl
+Name[it]=Cestino
+Name[ja]=ごみ箱
+Name[ka]=ურნა
+Name[kk]=Өшірілгендер
+Name[km]=ធុងសំរាម
+Name[lo]=ຖັງຂີ້ເຫຍື່ອ
+Name[lt]=Šiukšliadėžė
+Name[lv]=Miskaste
+Name[mk]=Корпа
+Name[mn]=Хогийн сав
+Name[ms]=Sampah
+Name[mt]=Skart
+Name[nb]=Papirkurv
+Name[nds]=Affalltünn
+Name[ne]=रद्दीटोकरी
+Name[nl]=Prullenbak
+Name[nn]=Papirkorg
+Name[nso]=Seswaraditlakala
+Name[pa]=ਰੱਦੀ
+Name[pl]=Kosz
+Name[pt]=Lixo
+Name[pt_BR]=Lixo
+Name[ro]=Gunoi
+Name[ru]=Корзина
+Name[se]=Ruskalihtti
+Name[sk]=Kôš
+Name[sl]=Smeti
+Name[sr]=Смеће
+Name[sr@Latn]=Smeće
+Name[sv]=Skräp
+Name[ta]=குப்பை
+Name[te]=చెత్త బుట్ట
+Name[tg]=Ахлотдон
+Name[th]=ถังขยะ
+Name[tr]=Çöp
+Name[tt]=Çüplek
+Name[uk]=Смітник
+Name[uz]=Chiqindilar qutisi
+Name[uz@cyrillic]=Чиқиндилар қутиси
+Name[ven]=Tshikha
+Name[vi]=Thùng rác
+Name[wa]=Batch
+Name[xh]=Inkukumo
+Name[zh_CN]=回收站
+Name[zh_TW]=資源回收桶
+Name[zu]=Izibi
+Icon=trashcan_empty
+X-KDE-Library=trash_panelapplet
diff --git a/kicker/applets/trash/trashapplet.h b/kicker/applets/trash/trashapplet.h
new file mode 100644
index 000000000..bc9662af4
--- /dev/null
+++ b/kicker/applets/trash/trashapplet.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TRASHAPPLET_H
+#define TRASHAPPLET_H
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#include <kpanelapplet.h>
+#include <qstring.h>
+#include <kurl.h>
+#include <kdirlister.h>
+
+#include "trashbutton.h"
+
+class TrashApplet : public KPanelApplet
+{
+Q_OBJECT
+
+public:
+ TrashApplet(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ ~TrashApplet();
+
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+ void about();
+
+protected:
+ void resizeEvent(QResizeEvent *e);
+ void positionChange(Position p);
+
+protected slots:
+ void slotClear();
+ void slotCompleted();
+ void slotDeleteItem(KFileItem *);
+
+private:
+ KDirLister *mpDirLister;
+ TrashButton *mButton;
+ int mCount;
+};
+
+#endif
diff --git a/kicker/applets/trash/trashbutton.cpp b/kicker/applets/trash/trashbutton.cpp
new file mode 100644
index 000000000..e6934a983
--- /dev/null
+++ b/kicker/applets/trash/trashbutton.cpp
@@ -0,0 +1,154 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "trashbutton.h"
+
+#include <qpopupmenu.h>
+#include <qtooltip.h>
+
+#include <klocale.h>
+#include <krun.h>
+#include <kpopupmenu.h>
+
+#include <kio/netaccess.h>
+
+#include <konq_operations.h>
+#include <konq_popupmenu.h>
+
+TrashButton::TrashButton(QWidget *parent)
+ : PanelPopupButton(parent), mActions(this, this),
+ mFileItem(KFileItem::Unknown, KFileItem::Unknown, "trash:/")
+{
+ KIO::UDSEntry entry;
+ KIO::NetAccess::stat("trash:/", entry, 0L);
+ mFileItem.assign(KFileItem(entry, "trash:/"));
+
+ KAction *a = KStdAction::paste(this, SLOT(slotPaste()),
+ &mActions, "paste");
+ a->setShortcut(0);
+
+ move(0, 0);
+ resize(20, 20);
+
+ setTitle(i18n("Trash"));
+ setIcon( "trashcan_empty" );
+
+ setAcceptDrops(true);
+
+ // Activate this code only if we find a way to have both an
+ // action and a popup menu for the same kicker button
+ //connect(this, SIGNAL(clicked()), this, SLOT(slotClicked()));
+
+ setPopup(new QPopupMenu());
+}
+
+TrashButton::~TrashButton()
+{
+}
+
+void TrashButton::setItemCount(int count)
+{
+ if (count==0)
+ {
+ setIcon( "trashcan_empty" );
+ QToolTip::add(this, i18n("Empty"));
+ }
+ else
+ {
+ setIcon( "trashcan_full" );
+ QToolTip::add(this, i18n("One item", "%n items", count));
+ }
+}
+
+void TrashButton::initPopup()
+{
+ QPopupMenu *old_popup = popup();
+
+ KFileItemList items;
+ items.append(&mFileItem);
+
+ KonqPopupMenu::KonqPopupFlags kpf =
+ KonqPopupMenu::ShowProperties
+ | KonqPopupMenu::ShowNewWindow;
+
+ KParts::BrowserExtension::PopupFlags bef =
+ KParts::BrowserExtension::DefaultPopupItems;
+
+ KonqPopupMenu *new_popup = new KonqPopupMenu(0L, items,
+ KURL("trash:/"), mActions, 0L,
+ this, kpf, bef);
+ KPopupTitle *title = new KPopupTitle(new_popup);
+ title->setTitle(i18n("Trash"));
+
+ new_popup->insertItem(title, -1, 0);
+
+ setPopup(new_popup);
+
+ if (old_popup!=0L) delete old_popup;
+}
+
+// Activate this code only if we find a way to have both an
+// action and a popup menu for the same kicker button
+/*
+void TrashButton::slotClicked()
+{
+ mFileItem.run();
+}
+*/
+
+void TrashButton::slotPaste()
+{
+ KonqOperations::doPaste(this, mFileItem.url());
+}
+
+void TrashButton::dragEnterEvent(QDragEnterEvent* e)
+{
+ e->accept(true);
+}
+
+void TrashButton::dropEvent(QDropEvent *e)
+{
+ KonqOperations::doDrop(0L, mFileItem.url(), e, this);
+}
+
+QString TrashButton::tileName()
+{
+ return mFileItem.name();
+}
+
+void TrashButton::setPanelPosition(KPanelApplet::Position position)
+{
+ switch(position)
+ {
+ case KPanelApplet::pBottom:
+ setPopupDirection(KPanelApplet::Up);
+ break;
+ case KPanelApplet::pTop:
+ setPopupDirection(KPanelApplet::Down);
+ break;
+ case KPanelApplet::pRight:
+ setPopupDirection(KPanelApplet::Left);
+ break;
+ case KPanelApplet::pLeft:
+ setPopupDirection(KPanelApplet::Right);
+ break;
+ }
+}
+
+#include "trashbutton.moc"
diff --git a/kicker/applets/trash/trashbutton.h b/kicker/applets/trash/trashbutton.h
new file mode 100644
index 000000000..7a5d8b59f
--- /dev/null
+++ b/kicker/applets/trash/trashbutton.h
@@ -0,0 +1,60 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TRASHBUTTON_H
+#define TRASHBUTTON_H
+
+#include <panelbutton.h>
+#include <qpoint.h>
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qtimer.h>
+#include <kfileitem.h>
+#include <kpanelapplet.h>
+#include <kactioncollection.h>
+
+class TrashButton : public PanelPopupButton
+{
+Q_OBJECT
+
+public:
+ TrashButton(QWidget *parent);
+ ~TrashButton();
+ void setItemCount(int count);
+ void setPanelPosition(KPanelApplet::Position position);
+
+protected:
+ QString tileName();
+ void initPopup();
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dropEvent(QDropEvent *e);
+
+protected slots:
+ // Activate this code only if we find a way to have both an
+ // action and a popup menu for the same kicker button
+ //void slotClicked();
+ void slotPaste();
+
+private:
+ KActionCollection mActions;
+ KFileItem mFileItem;
+};
+
+#endif