summaryrefslogtreecommitdiffstats
path: root/kicker/libkicker
diff options
context:
space:
mode:
Diffstat (limited to 'kicker/libkicker')
-rw-r--r--kicker/libkicker/Makefile.am19
-rw-r--r--kicker/libkicker/appletinfo.cpp112
-rw-r--r--kicker/libkicker/appletinfo.h92
-rw-r--r--kicker/libkicker/global.cpp477
-rw-r--r--kicker/libkicker/global.h112
-rw-r--r--kicker/libkicker/kickerSettings.kcfg342
-rw-r--r--kicker/libkicker/kickerSettings.kcfgc8
-rw-r--r--kicker/libkicker/kickertip.cpp557
-rw-r--r--kicker/libkicker/kickertip.h121
-rw-r--r--kicker/libkicker/kshadowengine.cpp251
-rw-r--r--kicker/libkicker/kshadowengine.h123
-rw-r--r--kicker/libkicker/kshadowsettings.cpp182
-rw-r--r--kicker/libkicker/kshadowsettings.h236
-rw-r--r--kicker/libkicker/menuinfo.cpp68
-rw-r--r--kicker/libkicker/menuinfo.h52
-rw-r--r--kicker/libkicker/panelbutton.cpp985
-rw-r--r--kicker/libkicker/panelbutton.h471
-rw-r--r--kicker/libkicker/paneldrag.cpp180
-rw-r--r--kicker/libkicker/paneldrag.h68
-rw-r--r--kicker/libkicker/panner.cpp396
-rw-r--r--kicker/libkicker/panner.h115
-rw-r--r--kicker/libkicker/simplebutton.cpp258
-rw-r--r--kicker/libkicker/simplebutton.h89
23 files changed, 5314 insertions, 0 deletions
diff --git a/kicker/libkicker/Makefile.am b/kicker/libkicker/Makefile.am
new file mode 100644
index 000000000..5ec65be46
--- /dev/null
+++ b/kicker/libkicker/Makefile.am
@@ -0,0 +1,19 @@
+INCLUDES = $(all_includes)
+
+lib_LTLIBRARIES = libkickermain.la
+
+libkickermain_la_SOURCES = appletinfo.cpp global.cpp kickertip.cpp \
+ menuinfo.cpp panelbutton.cpp panner.cpp \
+ kickerSettings.kcfgc kshadowsettings.cpp \
+ kshadowengine.cpp paneldrag.cpp \
+ simplebutton.cpp
+
+libkickermain_la_METASOURCES = AUTO
+
+libkickermain_la_LDFLAGS = $(all_libraries) -version-info 1:0:0 -no-undefined
+libkickermain_la_LIBADD = $(LIB_KIO)
+
+kde_kcfg_DATA = kickerSettings.kcfg
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/libkicker.pot
diff --git a/kicker/libkicker/appletinfo.cpp b/kicker/libkicker/appletinfo.cpp
new file mode 100644
index 000000000..cfb626fac
--- /dev/null
+++ b/kicker/libkicker/appletinfo.cpp
@@ -0,0 +1,112 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qfileinfo.h>
+#include <kdesktopfile.h>
+#include <kapplication.h>
+
+#include "appletinfo.h"
+
+AppletInfo::AppletInfo( const QString& deskFile, const QString& configFile, const AppletInfo::AppletType type)
+ : m_type (type),
+ m_unique(true),
+ m_hidden(false)
+{
+ QFileInfo fi(deskFile);
+ m_desktopFile = fi.fileName();
+
+ const char* resource = "applets";
+ switch (type)
+ {
+ case Extension:
+ resource = "extensions";
+ break;
+ case BuiltinButton:
+ resource = "builtinbuttons";
+ break;
+ case SpecialButton:
+ resource = "specialbuttons";
+ break;
+ case Undefined:
+ case Applet:
+ default:
+ break;
+ }
+
+ KDesktopFile df(m_desktopFile, true, resource);
+
+ // set the appletssimple attributes
+ setName(df.readName());
+ setComment(df.readComment());
+ setIcon(df.readIcon());
+
+ // library
+ setLibrary(df.readEntry("X-KDE-Library"));
+
+ // is it a unique applet?
+ setIsUnique(df.readBoolEntry("X-KDE-UniqueApplet", false));
+
+ // should it be shown in the gui?
+ m_hidden = df.readBoolEntry("Hidden", false);
+
+ if (configFile.isEmpty())
+ {
+ // generate a config file base name from the library name
+ m_configFile = m_lib.lower();
+
+ if (m_unique)
+ {
+ m_configFile.append("rc");
+ }
+ else
+ {
+ m_configFile.append("_")
+ .append(kapp->randomString(20).lower())
+ .append("_rc");
+ }
+ }
+ else
+ {
+ m_configFile = configFile;
+ }
+}
+
+bool AppletInfo::operator!=( const AppletInfo& rhs) const
+{
+ return configFile() != rhs.configFile();
+}
+
+bool AppletInfo::operator<( const AppletInfo& rhs ) const
+{
+ return ( QString::localeAwareCompare( name(), rhs.name() ) < 0 );
+}
+
+bool AppletInfo::operator> ( const AppletInfo& rhs ) const
+{
+ return ( QString::localeAwareCompare( name(), rhs.name() ) > 0 );
+}
+
+bool AppletInfo::operator<= ( const AppletInfo& rhs ) const
+{
+ return ( QString::localeAwareCompare( name(), rhs.name() ) <= 0 );
+}
diff --git a/kicker/libkicker/appletinfo.h b/kicker/libkicker/appletinfo.h
new file mode 100644
index 000000000..b9ab187ba
--- /dev/null
+++ b/kicker/libkicker/appletinfo.h
@@ -0,0 +1,92 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __appletinfo_h__
+#define __appletinfo_h__
+
+#include <qmap.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qvaluevector.h>
+
+#include <kdemacros.h>
+
+class KDE_EXPORT AppletInfo
+{
+ public:
+ typedef QValueVector<AppletInfo> List;
+ typedef QMap<QObject*, AppletInfo*> Dict;
+
+ enum AppletType { Undefined = 0,
+ Applet = 1,
+ BuiltinButton = 2,
+ SpecialButton = 4,
+ Extension = 8,
+ Button = BuiltinButton | SpecialButton };
+
+ AppletInfo(const QString& desktopFile = QString::null,
+ const QString& configFile = QString::null,
+ const AppletType type = Undefined);
+
+ QString name() const { return m_name; }
+ QString comment() const { return m_comment; }
+ QString icon() const { return m_icon; }
+
+ AppletType type() const { return m_type; }
+
+ QString library() const { return m_lib; }
+ QString desktopFile() const { return m_desktopFile; }
+ QString configFile() const { return m_configFile; }
+
+ bool isUniqueApplet() const { return m_unique; }
+ bool isHidden() const { return m_hidden; }
+
+ void setConfigFile(QString cf) { m_configFile = cf; }
+
+ bool operator<(const AppletInfo& rhs) const;
+ bool operator>(const AppletInfo& rhs) const;
+ bool operator<=(const AppletInfo& rhs) const;
+ bool operator!=(const AppletInfo& rhs) const;
+
+ void setType(AppletType type) { m_type = type; }
+
+ protected:
+ void setName(QString name) { m_name = name; }
+ void setComment(QString comment) { m_comment = comment; }
+ void setIcon(QString icon) { m_icon = icon; }
+ void setLibrary(QString lib) { m_lib = lib; }
+ void setIsUnique(bool u) { m_unique = u; }
+
+ private:
+ QString m_name;
+ QString m_comment;
+ QString m_icon;
+ QString m_lib;
+ QString m_desktopFile;
+ QString m_configFile;
+ AppletType m_type;
+ bool m_unique;
+ bool m_hidden;
+};
+
+#endif
diff --git a/kicker/libkicker/global.cpp b/kicker/libkicker/global.cpp
new file mode 100644
index 000000000..1f393616d
--- /dev/null
+++ b/kicker/libkicker/global.cpp
@@ -0,0 +1,477 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qfile.h>
+#include <qpopupmenu.h>
+#include <qregexp.h>
+#include <qpainter.h>
+
+#include <kiconeffect.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <kservice.h>
+
+#include "global.h"
+#include "kickerSettings.h"
+
+namespace KickerLib
+{
+
+KPanelExtension::Position directionToPosition(KPanelApplet::Direction d )
+{
+ switch (d)
+ {
+ case KPanelApplet::Down:
+ return KPanelExtension::Top;
+ break;
+
+ case KPanelApplet::Left:
+ return KPanelExtension::Right;
+ break;
+
+ case KPanelApplet::Right:
+ return KPanelExtension::Left;
+ break;
+
+ case KPanelApplet::Up:
+ default:
+ return KPanelExtension::Bottom;
+ break;
+ }
+}
+
+KPanelExtension::Position directionToPopupPosition(KPanelApplet::Direction d)
+{
+ switch (d)
+ {
+ case KPanelApplet::Up:
+ return KPanelExtension::Top;
+ break;
+
+ case KPanelApplet::Down:
+ return KPanelExtension::Bottom;
+ break;
+
+ case KPanelApplet::Left:
+ return KPanelExtension::Left;
+ break;
+
+ case KPanelApplet::Right:
+ default:
+ return KPanelExtension::Right;
+ break;
+ }
+}
+
+KPanelApplet::Direction positionToDirection(KPanelExtension::Position p)
+{
+ switch (p)
+ {
+ case KPanelExtension::Top:
+ return KPanelApplet::Down;
+ break;
+
+ case KPanelExtension::Right:
+ return KPanelApplet::Left;
+ break;
+
+ case KPanelExtension::Left:
+ return KPanelApplet::Right;
+ break;
+
+ case KPanelExtension::Bottom:
+ default:
+ return KPanelApplet::Up;
+ break;
+ }
+}
+
+KPanelApplet::Direction arrowToDirection(Qt::ArrowType p)
+{
+ switch (p)
+ {
+ case Qt::DownArrow:
+ return KPanelApplet::Down;
+ break;
+
+ case Qt::LeftArrow:
+ return KPanelApplet::Left;
+ break;
+
+ case Qt::RightArrow:
+ return KPanelApplet::Right;
+ break;
+
+ case Qt::UpArrow:
+ default:
+ return KPanelApplet::Up;
+ break;
+ }
+}
+
+int sizeValue(KPanelExtension::Size s)
+{
+ switch (s)
+ {
+ case KPanelExtension::SizeTiny:
+ return 24;
+ break;
+
+ case KPanelExtension::SizeSmall:
+ return 30;
+ break;
+
+ case KPanelExtension::SizeNormal:
+ return 46;
+ break;
+
+ case KPanelExtension::SizeLarge:
+ default:
+ return 58;
+ break;
+ }
+}
+
+int maxButtonDim()
+{
+ return (2 * KickerSettings::iconMargin()) + KIcon::SizeLarge;
+}
+
+QString newDesktopFile(const KURL& url)
+{
+ QString base = url.fileName();
+ if (base.endsWith(".desktop"))
+ base.truncate(base.length()-8);
+ QRegExp r("(.*)(?=-\\d+)");
+ if (r.search(base) > -1)
+ base = r.cap(1);
+
+ QString file = base + ".desktop";
+
+ for(int n = 1; ++n; )
+ {
+ QString path = locate("appdata", file);
+ if (path.isEmpty())
+ break;
+
+ file = QString("%2-%1.desktop").arg(n).arg(base);
+ }
+ file = locateLocal("appdata", file);
+ return file;
+}
+
+QString copyDesktopFile(const KURL& url)
+{
+ QString file = newDesktopFile(url);
+ KURL dest;
+ dest.setPath(file);
+ KIO::NetAccess::upload(url.path(), dest, 0);
+ return file;
+}
+
+QPopupMenu* reduceMenu(QPopupMenu *menu)
+{
+ if (menu->count() != 1)
+ {
+ return menu;
+ }
+
+ QMenuItem *item = menu->findItem(menu->idAt(0));
+
+ if (item->popup())
+ {
+ return reduceMenu(item->popup());
+ }
+
+ return menu;
+}
+
+QPoint popupPosition(KPanelApplet::Direction d,
+ const QWidget* popup,
+ const QWidget* source,
+ const QPoint& offset)
+{
+ QRect r;
+ if (source->isTopLevel())
+ {
+ r = source->geometry();
+ }
+ else
+ {
+ r = QRect(source->mapToGlobal(QPoint(0, 0)),
+ source->mapToGlobal(QPoint(source->width(), source->height())));
+
+ switch (d)
+ {
+ case KPanelApplet::Left:
+ case KPanelApplet::Right:
+ r.setLeft( source->topLevelWidget()->x() );
+ r.setWidth( source->topLevelWidget()->width() );
+ break;
+ case KPanelApplet::Up:
+ case KPanelApplet::Down:
+ r.setTop( source->topLevelWidget()->y() );
+ r.setHeight( source->topLevelWidget()->height() );
+ break;
+ }
+ }
+
+ switch (d)
+ {
+ case KPanelApplet::Left:
+ case KPanelApplet::Right:
+ {
+ QDesktopWidget* desktop = QApplication::desktop();
+ QRect screen = desktop->screenGeometry(desktop->screenNumber(const_cast<QWidget*>(source)));
+ int x = (d == KPanelApplet::Left) ? r.left() - popup->width() :
+ r.right() + 1;
+ int y = r.top() + offset.y();
+
+ // try to keep this on screen
+ if (y + popup->height() > screen.bottom())
+ {
+ y = r.bottom() - popup->height() + offset.y();
+
+ if (y < screen.top())
+ {
+ y = screen.bottom() - popup->height();
+
+ if (y < screen.top())
+ {
+ y = screen.top();
+ }
+ }
+ }
+
+ return QPoint(x, y);
+ }
+ case KPanelApplet::Up:
+ case KPanelApplet::Down:
+ default:
+ {
+ int x = 0;
+ int y = (d == KPanelApplet::Up) ? r.top() - popup->height() :
+ r.bottom() + 1;
+
+ if (QApplication::reverseLayout())
+ {
+ x = r.right() - popup->width() + 1;
+
+ if (offset.x() > 0)
+ {
+ x -= r.width() - offset.x();
+ }
+
+ // try to keep this on the screen
+ if (x - popup->width() < 0)
+ {
+ x = r.left();
+ }
+
+ return QPoint(x, y);
+ }
+ else
+ {
+ QDesktopWidget* desktop = QApplication::desktop();
+ QRect screen = desktop->screenGeometry(desktop->screenNumber(const_cast<QWidget*>(source)));
+ x = r.left() + offset.x();
+
+ // try to keep this on the screen
+ if (x + popup->width() > screen.right())
+ {
+ x = r.right() - popup->width() + 1 + offset.x();
+
+ if (x < screen.left())
+ {
+ x = screen.left();
+ }
+ }
+ }
+
+ return QPoint(x, y);
+ }
+ }
+}
+
+void colorize(QImage& image)
+{
+ KConfig *config = KGlobal::config();
+ config->setGroup("WM");
+ QColor color = QApplication::palette().active().highlight();
+ QColor activeTitle = config->readColorEntry("activeBackground", &color);
+ QColor inactiveTitle = config->readColorEntry("inactiveBackground", &color);
+
+ // figure out which color is most suitable for recoloring to
+ int h1, s1, v1, h2, s2, v2, h3, s3, v3;
+ activeTitle.hsv(&h1, &s1, &v1);
+ inactiveTitle.hsv(&h2, &s2, &v2);
+ QApplication::palette().active().background().hsv(&h3, &s3, &v3);
+
+ if ( (kAbs(h1-h3)+kAbs(s1-s3)+kAbs(v1-v3) < kAbs(h2-h3)+kAbs(s2-s3)+kAbs(v2-v3)) &&
+ ((kAbs(h1-h3)+kAbs(s1-s3)+kAbs(v1-v3) < 32) || (s1 < 32)) && (s2 > s1))
+ color = inactiveTitle;
+ else
+ color = activeTitle;
+
+ // limit max/min brightness
+ int r, g, b;
+ color.rgb(&r, &g, &b);
+ int gray = qGray(r, g, b);
+ if (gray > 180) {
+ r = (r - (gray - 180) < 0 ? 0 : r - (gray - 180));
+ g = (g - (gray - 180) < 0 ? 0 : g - (gray - 180));
+ b = (b - (gray - 180) < 0 ? 0 : b - (gray - 180));
+ } else if (gray < 76) {
+ r = (r + (76 - gray) > 255 ? 255 : r + (76 - gray));
+ g = (g + (76 - gray) > 255 ? 255 : g + (76 - gray));
+ b = (b + (76 - gray) > 255 ? 255 : b + (76 - gray));
+ }
+ color.setRgb(r, g, b);
+ KIconEffect::colorize(image, color, 1.0);
+}
+
+QColor blendColors(const QColor& c1, const QColor& c2)
+{
+ int r1, g1, b1;
+ int r2, g2, b2;
+
+ c1.rgb(&r1, &g1, &b1);
+ c2.rgb(&r2, &g2, &b2);
+
+ r1 += (int) (.5 * (r2 - r1));
+ g1 += (int) (.5 * (g2 - g1));
+ b1 += (int) (.5 * (b2 - b1));
+
+ return QColor(r1, g1, b1);
+}
+
+QColor shadowColor(const QColor& c)
+{
+ int r = c.red();
+ int g = c.green();
+ int b = c.blue();
+
+ if ( r < 128 )
+ r = 255;
+ else
+ r = 0;
+
+ if ( g < 128 )
+ g = 255;
+ else
+ g = 0;
+
+ if ( b < 128 )
+ b = 255;
+ else
+ b = 0;
+
+ return QColor( r, g, b );
+}
+
+QIconSet menuIconSet(const QString& icon)
+{
+ QIconSet iconset;
+ int iconSize = KickerSettings::menuEntryHeight();
+
+ if (iconSize < 0)
+ {
+ return iconset;
+ }
+
+ if (icon != "unknown")
+ {
+ if (iconSize > 0)
+ {
+ iconset = KGlobal::iconLoader()->loadIconSet(icon,
+ KIcon::NoGroup,
+ iconSize, true);
+ }
+ else if (iconSize == 0)
+ {
+ QPixmap normal = KGlobal::iconLoader()->loadIcon(icon,
+ KIcon::Small,
+ 0,
+ KIcon::DefaultState,
+ 0,
+ true);
+
+ QPixmap active = KGlobal::iconLoader()->loadIcon(icon,
+ KIcon::Small,
+ 0,
+ KIcon::ActiveState,
+ 0,
+ true);
+
+ // make sure they are not larger than 20x20
+ if (normal.width() > 20 || normal.height() > 20)
+ {
+ normal.convertFromImage(normal.convertToImage().smoothScale(20,20));
+ }
+
+ if (active.width() > 20 || active.height() > 20)
+ {
+ active.convertFromImage(active.convertToImage().smoothScale(20,20));
+ }
+
+ iconset.setPixmap(normal, QIconSet::Small, QIconSet::Normal);
+ iconset.setPixmap(active, QIconSet::Small, QIconSet::Active);
+ }
+ }
+
+ if (iconset.isNull())
+ {
+ QPixmap pix(iconSize, iconSize);
+ QBitmap map(iconSize, iconSize, true);
+ pix.setMask(map);
+ iconset = QIconSet(pix, pix);
+ }
+
+ return iconset;
+}
+
+void drawBlendedRect(QPainter *p, const QRect &r, const QColor &color, int alpha)
+{
+ static QPixmap pix;
+ static QColor last_color = Qt::black;
+ static int last_alpha = 0;
+
+ if (pix.isNull() || last_color != color || last_alpha != alpha)
+ {
+ QImage img(16, 16, 32);
+ img.setAlphaBuffer(false);
+ img.fill(((uint)(alpha & 0xFF) << 24) | (color.rgb() & 0xFFFFFF));
+ img.setAlphaBuffer(true);
+ pix.convertFromImage(img);
+ last_color = color;
+ last_alpha = alpha;
+ }
+
+ p->drawTiledPixmap(r, pix);
+}
+
+} // namespace
+
diff --git a/kicker/libkicker/global.h b/kicker/libkicker/global.h
new file mode 100644
index 000000000..2b9449584
--- /dev/null
+++ b/kicker/libkicker/global.h
@@ -0,0 +1,112 @@
+/*****************************************************************
+
+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 __pglobal_h__
+#define __pglobal_h__
+
+#include <qiconset.h>
+#include <qmap.h>
+
+#include <kpanelapplet.h>
+#include <kpanelextension.h>
+#include <kurl.h>
+
+namespace KickerLib
+{
+
+/*
+ * Functions to convert between various enums
+ */
+KDE_EXPORT KPanelExtension::Position directionToPosition(KPanelApplet::Direction d);
+KDE_EXPORT KPanelExtension::Position directionToPopupPosition(KPanelApplet::Direction d);
+KDE_EXPORT KPanelApplet::Direction positionToDirection(KPanelExtension::Position p);
+KDE_EXPORT KPanelApplet::Direction arrowToDirection(Qt::ArrowType p);
+KDE_EXPORT int sizeValue(KPanelExtension::Size s);
+
+/**
+ * Pixel sizes for but sizes and margins
+ */
+KDE_EXPORT int maxButtonDim();
+
+/**
+ * Tint the image to reflect the current color scheme
+ * Used, for instance, by KMenu side bar
+ */
+KDE_EXPORT void colorize(QImage& image);
+
+/**
+ * Blend a color rectangle on a painter
+ */
+KDE_EXPORT void drawBlendedRect(QPainter *p, const QRect &r, const QColor &color = Qt::black, int alpha = 0x40);
+
+/**
+ * Blend two colours together to get a colour halfway in between
+ */
+KDE_EXPORT QColor blendColors(const QColor& c1, const QColor& c2);
+
+/**
+ * Create or copy .desktop files for use in kicker safely and easily
+ */
+KDE_EXPORT QString copyDesktopFile(const KURL&url);
+KDE_EXPORT QString newDesktopFile(const KURL&url);
+
+
+/**
+ * Reduces a popup menu
+ *
+ * When a popup menu contains only 1 sub-menu, it makes no sense to
+ * show this popup-menu but we better show the sub-menu directly.
+ *
+ * This function checks whether that is the case and returns either the
+ * original menu or the sub-menu when appropriate.
+ */
+KDE_EXPORT QPopupMenu *reduceMenu(QPopupMenu *);
+
+
+/**
+ * Calculate the appropriate position for a popup menu based on the
+ * direction, the size of the menu, the widget geometry, and a optional
+ * point in the local coordinates of the widget.
+ */
+KDE_EXPORT QPoint popupPosition(KPanelApplet::Direction d,
+ const QWidget* popup,
+ const QWidget* source,
+ const QPoint& offset = QPoint(0, 0));
+
+/**
+ * Calculate an acceptable inverse of the given color wich will be used
+ * as the shadow color.
+ */
+KDE_EXPORT QColor shadowColor(const QColor& c);
+
+/**
+ * Get an appropriate for a menu in Plasma. As the user may set this size
+ * globally, it is important to always use this method.
+ * @param icon the name of icon requested
+ * @return the icon set for the requested icon
+ */
+KDE_EXPORT QIconSet menuIconSet(const QString& icon);
+
+}
+
+#endif // __pglobal_h__
diff --git a/kicker/libkicker/kickerSettings.kcfg b/kicker/libkicker/kickerSettings.kcfg
new file mode 100644
index 000000000..42f02bcad
--- /dev/null
+++ b/kicker/libkicker/kickerSettings.kcfg
@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+
+<include>kapplication.h</include>
+<include>klocale.h</include>
+<kcfgfile arg="true" />
+
+<group name="General">
+
+<entry name="Locked" type="Bool" >
+ <label>When this option is enabled, the panels may not be moved and items cannot be removed or added</label>
+ <default>false</default>
+ </entry>
+
+<entry name="ConserveSpace" type="Bool" >
+ <label>Enable conserve space</label>
+ <default>true</default>
+ </entry>
+
+<entry name="Transparent" type="Bool" >
+ <label>Enable transparency</label>
+ <whatsthis>When this option is enabled, the panel will become pseudo-transparent</whatsthis>
+ <default>false</default>
+ </entry>
+
+<entry name="MenubarPanelTransparent" type="Bool" >
+ <label>Enable transparency for menubar panel</label>
+ <whatsthis>When this option is enabled, the panel containing the menubar will become pseudo-transparent as well</whatsthis>
+ <default>false</default>
+ </entry>
+
+<entry name="UseBackgroundTheme" type="Bool" >
+ <label>Enable background image</label>
+ <whatsthis>When this option is enabled, the panel will display a tiled image as its background</whatsthis>
+ <default>true</default>
+ </entry>
+
+<entry name="ColorizeBackground" type="Bool" >
+ <label>Enable colourized background.</label>
+ <default>false</default>
+ </entry>
+
+<entry name="RotateBackground" type="Bool" >
+ <label>Rotate background</label>
+ <whatsthis>When this option is enabled, when the panel is placed on the side or top edges of the screen, the background image will be rotated to match the panel's orientation</whatsthis>
+ <default>true</default>
+ </entry>
+
+<entry name="BackgroundTheme" type="Path" >
+ <label>Background image</label>
+ <whatsthis>Here you can choose an image to be displayed on the panel. Press the 'browse' button to choose a theme using the file dialog. This option is only effective if 'Enable background image' is selected</whatsthis>
+ <default>wallpapers/default.png</default>
+ </entry>
+
+<entry name="TintValue" type="Int" >
+ <label>Controls the saturation level of the tint color used with transparent panels</label>
+ <default>33</default>
+ <min>0</min>
+ <max>100</max>
+ </entry>
+
+<entry name="TintColor" type="Color" >
+ <label>The tint color used to colorize transparent panels</label>
+ <default code="true">(QApplication::palette().active().mid())</default>
+ <whatsthis>This option sets the color to use when tinting transparent panels</whatsthis>
+ </entry>
+
+<entry name="UnhideLocation" type="Int">
+ <label>Raise when the pointer touches the screen here</label>
+ <default>0</default>
+ </entry>
+
+<entry name="FadeOutAppletHandles" type="Bool">
+ <label>Fade out applet handles</label>
+ <default>true</default>
+ <whatsthis>Select this option to make applet handles only visible on mouse hover. Applet handles let you move, remove and configure applets.</whatsthis>
+ </entry>
+
+<entry name="HideAppletHandles" type="Bool">
+ <label>Hide applet handles</label>
+ <default>false</default>
+ <whatsthis>Select this option to always hide the applet handles. Beware this could disable moving, removing or configuring some applets.</whatsthis>
+ </entry>
+
+<entry name="ShowToolTips" type="Bool" >
+ <label>Show informational tooltips</label>
+ <default>true</default>
+ </entry>
+
+<entry name="UntrustedApplets" type="StringList">
+ <label>A list of applets that have been loaded at runtime. In the case of a crash these applets will not be loaded at the next Kicker start, in case they caused the crash</label>
+ </entry>
+
+<entry name="UntrustedExtensions" type="StringList">
+ <label>A list of extensions that have been loaded at runtime. In the case of a crash these extensions will not be loaded at the next Kicker start, in case they caused the crash</label>
+ </entry>
+
+</group>
+
+<group name="menus">
+
+ <entry name="MenuEntryFormat" type="Enum" >
+ <choices>
+ <choice name="NameOnly">
+ <label>Show simple menu entries</label>
+ </choice>
+ <choice name="NameAndDescription">
+ <label>Show names first on detailed entries</label>
+ </choice>
+ <choice name="DescriptionOnly">
+ <label>Show only description for menu entries</label>
+ </choice>
+ <choice name="DescriptionAndName">
+ <label>Show detailed menu entries</label>
+ </choice>
+ </choices>
+ <default>DescriptionAndName</default>
+ <label>Formation of the menu entry text</label>
+ </entry>
+
+<entry name="ShowMenuTitles" type="Bool" >
+ <label>Show section titles in Kmenu</label>
+ <default>true</default>
+ </entry>
+
+<entry name="MenuEntryHeight" type="Int" >
+ <label>Height of menu entries in pixels</label>
+ <default>0</default>
+ </entry>
+
+<entry name="ShowHiddenFiles" type="Bool" >
+ <label>Show hidden files in Quick Browser</label>
+ <default>false</default>
+ </entry>
+
+<entry name="MaxEntries2" type="UInt" >
+ <label>Maximum number of entries</label>
+ <default>30</default>
+ <min>1</min>
+ </entry>
+
+<entry name="UseBookmarks" type="Bool" >
+ <label>Show bookmarks in KMenu</label>
+ <default>false</default>
+ </entry>
+
+<entry name="UseBrowser" type="Bool" >
+ <label>Use the Quick Browser</label>
+ <default>false</default>
+ </entry>
+
+<entry name="MenuExtensions" key="Extensions" type="StringList" >
+ <label>Optional Menus</label>
+ <default>prefmenu.desktop,systemmenu.desktop</default>
+ </entry>
+
+<entry name="RecentAppsStat" type="StringList" >
+ <label>Recently used applications</label>
+ </entry>
+
+<entry name="NumVisibleEntries" type="UInt" >
+ <label>Number of visible entries</label>
+ <default>5</default>
+ <max>100</max>
+ </entry>
+
+<entry name="RecentVsOften" type="Bool" >
+ <label>Show most recently used applications rather than most frequently used</label>
+ <default>false</default>
+ </entry>
+
+</group>
+
+<group name="button_tiles">
+
+<entry name="EnableKMenuTiles" type="Bool">
+ <label>Enable a tile background image for the KMenu button</label>
+ <default>false</default>
+ </entry>
+
+<entry name="EnableDesktopButtonTiles" type="Bool">
+ <label>Enable a tile background image for the Desktop button</label>
+ <default>false</default>
+ </entry>
+
+<entry name="EnableURLTiles" type="Bool" >
+ <label>Enable a tile background image for Application, URL and special buttons</label>
+ <default>false</default>
+ </entry>
+
+<entry name="EnableBrowserTiles" type="Bool" >
+ <label>Enable a tile background image for the Quick Browser button</label>
+ <default>false</default>
+ </entry>
+
+<entry name="EnableWindowListTiles" type="Bool" >
+ <label>Enable a tile background image for the Window List button</label>
+ <default>false</default>
+ </entry>
+
+<entry name="KMenuTile" type="Path" >
+ <label>Image tile for Kmenu button background</label>
+ </entry>
+
+<entry name="KMenuTileColor" type="Color" >
+ <label>Color to use for Kmenu button background</label>
+ <default code="true">QColor()</default>
+ </entry>
+
+<entry name="DesktopButtonTile" type="Path" >
+ <label>Image tile for Desktop button background</label>
+ </entry>
+
+<entry name="DesktopButtonTileColor" type="Color" >
+ <label>Color to use for Kmenu button background</label>
+ <default code="true">QColor()</default>
+ </entry>
+
+<entry name="URLTile" type="Path" >
+ <label>Image tile for Application, URL and special button backgrounds</label>
+ </entry>
+
+<entry name="URLTileColor" type="Color" >
+ <label>Color to use for Application, URL and special button backgrounds</label>
+ <default code="true">QColor()</default>
+ </entry>
+
+<entry name="BrowserTile" type="Path" >
+ <label>Image tile for Browser button background</label>
+ </entry>
+
+<entry name="BrowserTileColor" type="Color" >
+ <label>Color to use for Browser button background</label>
+ <default code="true">QColor()</default>
+ </entry>
+
+<entry name="WindowListTile" type="Path" >
+ <label>Image tile for Window List button background</label>
+ </entry>
+
+<entry name="WindowListTileColor" type="Color" >
+ <label>Color to use for Window List button background</label>
+ <default code="true">QColor()</default>
+ </entry>
+
+</group>
+
+<group name="KMenu" >
+
+<entry name="UseSidePixmap" type="Bool" >
+ <label>Use side image in Kmenu</label>
+ <default>true</default>
+ </entry>
+
+<entry name="SidePixmapName" key="SideName" type="String" >
+ <label>The name of the file to use as the side image in the K Menu</label>
+ <default>kside.png</default>
+ </entry>
+
+<entry name="SideTileName" key="SideTileName" type="String" >
+ <label>The name of the file used as a tile to fill the height of K Menu that SidePixmapName does not cover</label>
+ <default>kside_tile.png</default>
+ </entry>
+
+<entry name="ShowKMenuText" key="ShowText" type="Bool" >
+ <label>Show text on the K Menu button</label>
+ <default>false</default>
+ </entry>
+
+<entry name="KMenuText" key="Text" type="String" >
+ <label>Text to be shown on K Menu Button</label>
+ <default code="true">i18n("Applications")</default>
+ </entry>
+
+</group>
+
+<group name="buttons" >
+
+<entry name="ShowMouseOverEffects" key="EnableIconZoom" type="Bool" >
+ <label>Enable icon mouse over effects</label>
+ <default>true</default>
+ </entry>
+
+<entry name="MouseOversShowIcon" type="Bool" >
+ <label>Show icons in mouse over effects</label>
+ <default>true</default>
+ </entry>
+
+<entry name="MouseOversShowText" type="Bool" >
+ <label>Show text in mouse over effects</label>
+ <default>true</default>
+ </entry>
+
+<entry name="MouseOversSpeed" type="Int" >
+ <label>Controls how fast the tooltips fade in, measured in thousandths of a second</label>
+ <default>500</default>
+ <min>0</min>
+ </entry>
+
+ <entry name="MouseOversShowDelay" type="UInt" >
+ <label>Mouse over effects are shown after the defined time (in milliseconds)</label>
+ <default>500</default>
+ </entry>
+
+ <entry name="MouseOversHideDelay" type="UInt" >
+ <label>Mouse over effects are hidden after the defined time (in milliseconds)</label>
+ <default>200</default>
+ </entry>
+
+<entry name="EnableTileBackground" type="Bool" >
+ <label>Enable background tiles</label>
+ <default>false</default>
+ </entry>
+
+<entry name="IconMargin" key="IconMargin" type="Int" >
+ <label>The margin between panel icons and the panel border</label>
+ <default>3</default>
+ </entry>
+
+<entry name="RemoveButtonsWhenBroken" type="Bool" >
+ <label>Buttons that represent KServices (applications, primarily) watch for the removal of the service and delete themselves when this happens. This setting turns this off.</label>
+ <default>true</default>
+ </entry>
+
+<entry name="ButtonFont" key="Font" type="Font" >
+ <label>Font for the buttons with text.</label>
+ <default code="true">KGlobalSettings::generalFont()</default>
+ </entry>
+
+<entry name="ButtonTextColor" key="TextColor" type="Color" >
+ <label>Text color for the buttons.</label>
+ <default code="true">KGlobalSettings::textColor()</default>
+ </entry>
+
+</group>
+
+</kcfg>
+
+
diff --git a/kicker/libkicker/kickerSettings.kcfgc b/kicker/libkicker/kickerSettings.kcfgc
new file mode 100644
index 000000000..59c271928
--- /dev/null
+++ b/kicker/libkicker/kickerSettings.kcfgc
@@ -0,0 +1,8 @@
+File=kickerSettings.kcfg
+Singleton=true
+ClassName=KickerSettings
+Mutators=true
+Visibility=KDE_EXPORT
+IncludeFiles=qapplication.h
+GlobalEnums=true
+MemberVariables=dpointer
diff --git a/kicker/libkicker/kickertip.cpp b/kicker/libkicker/kickertip.cpp
new file mode 100644
index 000000000..403641443
--- /dev/null
+++ b/kicker/libkicker/kickertip.cpp
@@ -0,0 +1,557 @@
+/*****************************************************************
+
+Copyright (c) 2004 Zack Rusin <zrusin@kde.org>
+ Sami Kyostil <skyostil@kempele.fi>
+ Aaron J. Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qapplication.h>
+#include <qpainter.h>
+#include <qsimplerichtext.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+
+#include <kdialog.h>
+
+#include "global.h"
+
+#include "kickertip.h"
+#include "kickerSettings.h"
+
+// putting this #include higher results in compile errors
+#include <netwm.h>
+
+static const int DEFAULT_FRAMES_PER_SECOND = 30;
+
+KickerTip* KickerTip::m_self = 0;
+int KickerTip::m_tippingEnabled = 1;
+
+void KickerTip::Client::updateKickerTip() const
+{
+ if (KickerTip::the()->isTippingFor(dynamic_cast<const QWidget*>(this)) &&
+ KickerTip::the()->isVisible())
+ {
+ KickerTip::the()->display();
+ }
+}
+
+KickerTip* KickerTip::the()
+{
+ if (!m_self)
+ {
+ m_self = new KickerTip(0);
+ }
+
+ return m_self;
+}
+
+KickerTip::KickerTip(QWidget * parent)
+ : QWidget(parent, "animtt",WX11BypassWM),
+ m_richText(0),
+ m_mimeFactory(0),
+ m_dissolveSize(0),
+ m_dissolveDelta(-1),
+ m_direction(KPanelApplet::Up),
+ m_dirty(false),
+ m_toolTipsEnabled(KickerSettings::showToolTips()),
+ m_tippingFor(0)
+{
+ setFocusPolicy(NoFocus);
+ setBackgroundMode(NoBackground);
+ resize(0, 0);
+ hide();
+ connect(&m_frameTimer, SIGNAL(timeout()), SLOT(internalUpdate()));
+}
+
+KickerTip::~KickerTip()
+{
+ delete m_richText;
+ delete m_mimeFactory;
+}
+
+void KickerTip::display()
+{
+ if (!tippingEnabled())
+ {
+ return;
+ }
+
+ {
+ // prevent tips from showing when the active window is fullscreened
+ NETRootInfo ri(qt_xdisplay(), NET::ActiveWindow);
+ NETWinInfo wi(qt_xdisplay(), ri.activeWindow(), ri.rootWindow(), NET::WMState);
+ if (wi.state() & NET::FullScreen)
+ {
+ return;
+ }
+ }
+
+ QWidget *widget = const_cast<QWidget*>(m_tippingFor);
+ KickerTip::Client *client = dynamic_cast<KickerTip::Client*>(widget);
+
+ if (!client)
+ {
+ return;
+ }
+
+ // delete the mimefactory and create a new one so any old pixmaps used in the
+ // richtext area are freed but the mimefactory is ready to be added to in
+ // the call to updateKickerTip
+ delete m_mimeFactory;
+ m_mimeFactory = new QMimeSourceFactory();
+
+ // Declare interchange object and define defaults.
+ Data data;
+ data.maskEffect = Dissolve;
+ data.duration = 2000;
+ data.direction = KPanelApplet::Up;
+ data.mimeFactory = m_mimeFactory;
+
+ // Tickle the information out of the bastard.
+ client->updateKickerTip(data);
+
+ // Hide the tip if there is nothing to show
+ if (data.message.isEmpty() && data.subtext.isEmpty() && data.icon.isNull())
+ {
+ hide();
+ return;
+ }
+
+ delete m_richText;
+ m_richText = new QSimpleRichText("<qt><h3>" + data.message + "</h3><p>" +
+ data.subtext + "</p></qt>", font(), QString::null, 0,
+ m_mimeFactory);
+ m_richText->setWidth(640);
+ m_direction = data.direction;
+
+ if (KickerSettings::mouseOversShowIcon())
+ {
+ m_icon = data.icon;
+ }
+ else if (KickerSettings::mouseOversShowText())
+ {
+ m_icon = QPixmap();
+ }
+ else
+ {
+ // don't bother since we have NOTHING to show
+ return;
+ }
+
+ m_maskEffect = isVisible() ? Plain : data.maskEffect;
+ m_dissolveSize = 24;
+ m_dissolveDelta = -1;
+
+ displayInternal();
+
+ m_frameTimer.start(1000 / DEFAULT_FRAMES_PER_SECOND);
+
+ // close the message window after given mS
+ if (data.duration > 0)
+ {
+ disconnect(&m_timer, SIGNAL(timeout()), 0, 0);
+ connect(&m_timer, SIGNAL(timeout()), SLOT(hide()));
+ m_timer.start(data.duration, true);
+ }
+ else
+ {
+ m_timer.stop();
+ }
+
+ move(KickerLib::popupPosition(m_direction, this, m_tippingFor));
+ show();
+}
+
+void KickerTip::paintEvent(QPaintEvent * e)
+{
+ if (m_dirty)
+ {
+ displayInternal();
+ m_dirty = false;
+ }
+
+ QPainter p(this);
+ p.drawPixmap(e->rect().topLeft(), m_pixmap, e->rect());
+}
+
+void KickerTip::mousePressEvent(QMouseEvent * /*e*/)
+{
+ QToolTip::setGloballyEnabled(m_toolTipsEnabled);
+ hide();
+}
+
+static void drawRoundRect(QPainter &p, const QRect &r)
+{
+ static int line[8] = { 1, 3, 4, 5, 6, 7, 7, 8 };
+ static int border[8] = { 1, 2, 1, 1, 1, 1, 1, 1 };
+ int xl, xr, y1, y2;
+ QPen pen = p.pen();
+ bool drawBorder = pen.style() != QPen::NoPen;
+
+ if (r.width() < 16 || r.height() < 16)
+ {
+ p.drawRect(r);
+ return;
+ }
+
+ p.fillRect(r.x(), r.y() + 8, r.width(), r.height() - 16, p.brush());
+ p.fillRect(r.x() + 8, r.y(), r.width() - 16, r.height(), p.brush());
+
+ p.setPen(p.brush().color());
+
+ for (int i = 0; i < 8; i++)
+ {
+ xl = i;
+ xr = r.width() - i - 1;
+ y1 = 7;
+ y2 = 7 - (line[i] - 1);
+
+ p.drawLine(xl, y1, xl, y2);
+ p.drawLine(xr, y1, xr, y2);
+
+ y1 = r.height() - y1 - 1;
+ y2 = r.height() - y2 - 1;
+
+ p.drawLine(xl, y1, xl, y2);
+ p.drawLine(xr, y1, xr, y2);
+
+ }
+
+ if (drawBorder)
+ {
+ p.setPen(pen);
+
+ if (r.height() > 16)
+ {
+ p.drawLine(r.x(), r.y() + 8, r.x(), r.y() + r.height() - 9);
+ p.drawLine(r.x() + r.width() - 1, r.y() + 8, r.x() + r.width() - 1, r.y() + r.height() - 9);
+ }
+ if (r.width() > 16)
+ {
+ p.drawLine(r.x() + 8, r.y(), r.x() + r.width() - 9, r.y());
+ p.drawLine(r.x() + 8, r.y() + r.height() - 1, r.x() + r.width() - 9, r.y() + r.height() - 1);
+ }
+
+ for (int i = 0; i < 8; i++)
+ {
+ xl = i;
+ xr = r.width() - i - 1;
+ y2 = 7 - (line[i] - 1);
+ y1 = y2 + (border[i] - 1);
+
+ p.drawLine(xl, y1, xl, y2);
+ p.drawLine(xr, y1, xr, y2);
+
+ y1 = r.height() - y1 - 1;
+ y2 = r.height() - y2 - 1;
+
+ p.drawLine(xl, y1, xl, y2);
+ p.drawLine(xr, y1, xr, y2);
+
+ }
+ }
+}
+
+void KickerTip::plainMask()
+{
+ QPainter maskPainter(&m_mask);
+
+ m_mask.fill(Qt::black);
+
+ maskPainter.setBrush(Qt::white);
+ maskPainter.setPen(Qt::NoPen);
+ //maskPainter.drawRoundRect(m_mask.rect(), 1600 / m_mask.rect().width(), 1600 / m_mask.rect().height());
+ drawRoundRect(maskPainter, m_mask.rect());
+ setMask(m_mask);
+ m_frameTimer.stop();
+}
+
+void KickerTip::dissolveMask()
+{
+ QPainter maskPainter(&m_mask);
+
+ m_mask.fill(Qt::black);
+
+ maskPainter.setBrush(Qt::white);
+ maskPainter.setPen(Qt::NoPen);
+ //maskPainter.drawRoundRect(m_mask.rect(), 1600 / m_mask.rect().width(), 1600 / m_mask.rect().height());
+ drawRoundRect(maskPainter, m_mask.rect());
+
+ m_dissolveSize += m_dissolveDelta;
+
+ if (m_dissolveSize > 0)
+ {
+ maskPainter.setRasterOp(Qt::EraseROP);
+
+ int x, y, s;
+ const int size = 16;
+
+ for (y = 0; y < height() + size; y += size)
+ {
+ x = width();
+ s = 4 * m_dissolveSize * x / 128;
+ for (; x > -size; x -= size, s -= 2)
+ {
+ if (s < 0)
+ {
+ break;
+ }
+ maskPainter.drawEllipse(x - s / 2, y - s / 2, s, s);
+ }
+ }
+ }
+ else if (m_dissolveSize < 0)
+ {
+ m_frameTimer.stop();
+ m_dissolveDelta = 1;
+ }
+
+ setMask(m_mask);
+}
+
+void KickerTip::displayInternal()
+{
+ // we need to check for m_tippingFor here as well as m_richText
+ // since if one is really persistant and moves the mouse around very fast
+ // you can trigger a situation where m_tippingFor gets reset to 0 but
+ // before display() is called!
+ if (!m_tippingFor || !m_richText)
+ {
+ return;
+ }
+
+ // determine text rectangle
+ QRect textRect(0, 0, 0, 0);
+ if (KickerSettings::mouseOversShowText())
+ {
+ textRect.setWidth(m_richText->widthUsed());
+ textRect.setHeight(m_richText->height());
+ }
+
+ int margin = KDialog::marginHint();
+ int height = QMAX(m_icon.height(), textRect.height()) + 2 * margin;
+ int textX = m_icon.isNull() ? margin : 2 + m_icon.width() + 2 * margin;
+ int width = textX + textRect.width() + margin;
+ int textY = (height - textRect.height()) / 2;
+
+ // resize pixmap, mask and widget
+ bool firstTime = m_dissolveSize == 24;
+ if (firstTime)
+ {
+ m_mask.resize(width, height);
+ m_pixmap.resize(width, height);
+ resize(width, height);
+ if (isVisible())
+ {
+ // we've already been shown before, but we may grow larger.
+ // in the case of Up or Right displaying tips, this growth can
+ // result in the tip occluding the panel and causing it to redraw
+ // once we return back to display() causing horrid flicker
+ move(KickerLib::popupPosition(m_direction, this, m_tippingFor));
+ }
+ }
+
+ // create and set transparency mask
+ switch(m_maskEffect)
+ {
+ case Plain:
+ plainMask();
+ break;
+
+ case Dissolve:
+ dissolveMask();
+ break;
+ }
+
+ // draw background
+ QPainter bufferPainter(&m_pixmap);
+ bufferPainter.setPen(colorGroup().foreground());
+ bufferPainter.setBrush(colorGroup().background());
+ //bufferPainter.drawRoundRect(0, 0, width, height, 1600 / width, 1600 / height);
+ drawRoundRect(bufferPainter, QRect(0, 0, width, height));
+
+ // draw icon if present
+ if (!m_icon.isNull())
+ {
+ bufferPainter.drawPixmap(margin,
+ margin,
+ m_icon, 0, 0,
+ m_icon.width(), m_icon.height());
+ }
+
+ if (KickerSettings::mouseOversShowText())
+ {
+ // draw text shadow
+ QColorGroup cg = colorGroup();
+ cg.setColor(QColorGroup::Text, cg.background().dark(115));
+ int shadowOffset = QApplication::reverseLayout() ? -1 : 1;
+ m_richText->draw(&bufferPainter, textX + shadowOffset, textY + 1, QRect(), cg);
+
+ // draw text
+ cg = colorGroup();
+ m_richText->draw(&bufferPainter, textX, textY, rect(), cg);
+ }
+}
+
+void KickerTip::tipFor(const QWidget* w)
+{
+ if (m_tippingFor)
+ {
+ disconnect(m_tippingFor, SIGNAL(destroyed(QObject*)),
+ this, SLOT(tipperDestroyed(QObject*)));
+ }
+
+ m_tippingFor = w;
+
+ if (m_tippingFor)
+ {
+ connect(m_tippingFor, SIGNAL(destroyed(QObject*)),
+ this, SLOT(tipperDestroyed(QObject*)));
+ }
+}
+
+void KickerTip::untipFor(const QWidget* w)
+{
+ if (isTippingFor(w))
+ hide();
+}
+
+bool KickerTip::isTippingFor(const QWidget* w) const
+{
+ return m_tippingFor == w;
+}
+
+void KickerTip::tipperDestroyed(QObject* o)
+{
+ // we can't do a dynamic cast because we are in the process of dieing
+ // so static it is.
+ untipFor(static_cast<QWidget*>(o));
+}
+
+void KickerTip::internalUpdate()
+{
+ m_dirty = true;
+ repaint(false);
+}
+
+void KickerTip::enableTipping(bool tip)
+{
+ if (tip)
+ {
+ m_tippingEnabled++;
+ }
+ else
+ {
+ m_tippingEnabled--;
+ }
+
+ if (m_tippingEnabled < 1 && m_self)
+ {
+ m_self->hide();
+ }
+}
+
+bool KickerTip::tippingEnabled()
+{
+ return m_tippingEnabled > 0;
+}
+
+void KickerTip::hide()
+{
+ tipFor(0);
+ m_timer.stop();
+ m_frameTimer.stop();
+ QWidget::hide();
+}
+
+bool KickerTip::eventFilter(QObject *object, QEvent *event)
+{
+ if (!tippingEnabled())
+ {
+ return false;
+ }
+
+ if (!object->isWidgetType())
+ {
+ return false;
+ }
+
+ QWidget *widget = static_cast<QWidget*>(object);
+
+ switch (event->type())
+ {
+ case QEvent::Enter:
+ if (!KickerSettings::showMouseOverEffects())
+ {
+ return false;
+ }
+
+ if (!mouseGrabber() &&
+ !qApp->activePopupWidget() &&
+ !isTippingFor(widget))
+ {
+ m_toolTipsEnabled = QToolTip::isGloballyEnabled();
+ QToolTip::setGloballyEnabled(false);
+
+ tipFor(widget);
+ m_timer.stop();
+ disconnect(&m_timer, SIGNAL(timeout()), 0, 0);
+ connect(&m_timer, SIGNAL(timeout()), SLOT(display()));
+
+ // delay to avoid false starts
+ // e.g. when the user quickly zooms their mouse over
+ // a button then out of kicker
+ if (isVisible())
+ {
+ m_timer.start(150, true);
+ }
+ else
+ {
+ m_timer.start(KickerSettings::mouseOversShowDelay(), true);
+ }
+ }
+ break;
+ case QEvent::Leave:
+ QToolTip::setGloballyEnabled(m_toolTipsEnabled);
+
+ m_timer.stop();
+
+ if (isTippingFor(widget) && isVisible())
+ {
+ disconnect(&m_timer, SIGNAL(timeout()), 0, 0);
+ connect(&m_timer, SIGNAL(timeout()), SLOT(hide()));
+ m_timer.start(KickerSettings::mouseOversHideDelay(), true);
+ }
+
+ tipFor(0);
+ break;
+ case QEvent::MouseButtonPress:
+ QToolTip::setGloballyEnabled(m_toolTipsEnabled);
+ hide();
+ default:
+ break;
+ }
+
+ return false;
+}
+
+#include <kickertip.moc>
+
diff --git a/kicker/libkicker/kickertip.h b/kicker/libkicker/kickertip.h
new file mode 100644
index 000000000..7211012fb
--- /dev/null
+++ b/kicker/libkicker/kickertip.h
@@ -0,0 +1,121 @@
+/*****************************************************************
+
+Copyright (c) 2004 Zack Rusin <zrusin@kde.org>
+ Sami Kyostil <skyostil@kempele.fi>
+ Aaron J. Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef KICKER_TIP_H
+#define KICKER_TIP_H
+
+#include <qbitmap.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include <kpanelapplet.h>
+
+class QMimeSourceFactory;
+class QPaintEvent;
+class QSimpleRichText;
+class QTimer;
+
+class KDE_EXPORT KickerTip : public QWidget
+{
+ Q_OBJECT
+
+public:
+ enum MaskEffect { Plain, Dissolve };
+
+ struct Data
+ {
+ QString message;
+ QString subtext;
+ QPixmap icon;
+ KickerTip::MaskEffect maskEffect;
+ int duration;
+ KPanelApplet::Direction direction;
+
+ // do NOT delete this in the client!
+ QMimeSourceFactory* mimeFactory;
+ };
+
+ class KDE_EXPORT Client
+ {
+ public:
+ virtual void updateKickerTip(KickerTip::Data&) = 0;
+ void updateKickerTip() const;
+ };
+
+ static KickerTip* the();
+ static void enableTipping(bool tip);
+ static bool tippingEnabled();
+
+ void untipFor(const QWidget* w);
+ bool eventFilter(QObject *o, QEvent *e);
+
+protected:
+ KickerTip(QWidget * parent);
+ ~KickerTip();
+
+ void paintEvent(QPaintEvent * e);
+ void mousePressEvent(QMouseEvent * e);
+
+ void plainMask();
+ void dissolveMask();
+
+ void displayInternal();
+ void hide();
+
+ void tipFor(const QWidget* w);
+ bool isTippingFor(const QWidget* w) const;
+
+protected slots:
+ void tipperDestroyed(QObject* o);
+ void internalUpdate();
+ void display();
+
+private:
+ QBitmap m_mask;
+ QPixmap m_pixmap;
+ QPixmap m_icon;
+ MaskEffect m_maskEffect;
+ QSimpleRichText* m_richText;
+ QMimeSourceFactory* m_mimeFactory;
+
+ int m_dissolveSize;
+ int m_dissolveDelta;
+ KPanelApplet::Direction m_direction;
+
+ QTimer m_timer;
+ QTimer m_frameTimer;
+ bool m_dirty;
+ bool m_toolTipsEnabled;
+
+ const QWidget* m_tippingFor;
+
+ static KickerTip* m_self;
+ static int m_tippingEnabled;
+
+ friend class KickerTip::Client;
+};
+
+#endif
diff --git a/kicker/libkicker/kshadowengine.cpp b/kicker/libkicker/kshadowengine.cpp
new file mode 100644
index 000000000..32008883e
--- /dev/null
+++ b/kicker/libkicker/kshadowengine.cpp
@@ -0,0 +1,251 @@
+/* This file is proposed to be part of the KDE libraries.
+ * Copyright (C) 2003 Laur Ivan <laurivan@eircom.net>
+ *
+ * Many thanks to:
+ * - Bernardo Hung <deciare@gta.igs.net> for the enhanced shadow
+ * algorithm (currently used)
+ * - Tim Jansen <tim@tjansen.de> for the API updates and fixes.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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 <qcolor.h>
+#include <qpainter.h>
+#include <qbitmap.h>
+#include <qpixmap.h>
+
+#include "kshadowsettings.h"
+#include "kshadowengine.h"
+
+KShadowEngine::KShadowEngine() :
+ m_shadowSettings( new KShadowSettings )
+{
+}
+
+KShadowEngine::~KShadowEngine()
+{
+ delete m_shadowSettings;
+}
+
+KShadowEngine::KShadowEngine(KShadowSettings *fx) :
+ m_shadowSettings(0L)
+{
+ setShadowSettings(fx);
+}
+
+
+void KShadowEngine::setShadowSettings(KShadowSettings *fx)
+{
+ delete m_shadowSettings;
+
+ m_shadowSettings = fx;
+}
+
+KShadowSettings *KShadowEngine::shadowSettings()
+{
+ return m_shadowSettings;
+}
+
+QImage KShadowEngine::makeShadow(const QPixmap& textPixmap, const QColor &bgColor)
+{
+ QImage result;
+
+ // create a new image for for the shaddow
+ int w = textPixmap.width();
+ int h = textPixmap.height();
+
+ // avoid calling these methods for every pixel
+ int bgRed = bgColor.red();
+ int bgGreen = bgColor.green();
+ int bgBlue = bgColor.blue();
+
+ int thick = m_shadowSettings->thickness() >> 1;
+
+ double alphaShadow;
+
+ /*
+ * This is the source pixmap
+ */
+ QImage img = textPixmap.convertToImage().convertDepth(32);
+
+ /*
+ * Resize the image if necessary
+ */
+ if ((result.width() != w) || (result.height() != h))
+ {
+ result.create(w, h, 32);
+ }
+
+ result.fill(0); // all black
+ result.setAlphaBuffer(true);
+
+ for (int i = thick; i < w - thick; i++)
+ {
+ for (int j = thick; j < h - thick; j++)
+ {
+ switch (m_shadowSettings->algorithm())
+ {
+ case KShadowSettings::DoubleLinearDecay:
+ alphaShadow = doubleLinearDecay(img, i, j);
+ break;
+ case KShadowSettings::RadialDecay:
+ alphaShadow = radialDecay(img, i, j);
+ break;
+ case KShadowSettings::NoDecay:
+ alphaShadow = noDecay(img, i, j);
+ break;
+ case KShadowSettings::DefaultDecay:
+ default:
+ alphaShadow = defaultDecay(img, i, j);
+ }
+
+ alphaShadow = (alphaShadow > m_shadowSettings->maxOpacity()) ? m_shadowSettings->maxOpacity() : alphaShadow;
+
+ // update the shadow's i,j pixel.
+ result.setPixel(i,j, qRgba(bgRed, bgGreen , bgBlue, (int) alphaShadow));
+ }
+ }
+ return result;
+}
+
+// Multiplication factor for pixels directly above, under, or next to the text
+#define AXIS_FACTOR 2.0
+// Multiplication factor for pixels diagonal to the text
+#define DIAGONAL_FACTOR 1.0
+
+double KShadowEngine::defaultDecay(QImage& source, int i, int j)
+{
+ if ((i < 1) || (j < 1) || (i > source.width() - 2) || (j > source.height() - 2))
+ return 0;
+
+ double alphaShadow;
+ alphaShadow =(qGray(source.pixel(i-1,j-1)) * DIAGONAL_FACTOR +
+ qGray(source.pixel(i-1,j )) * AXIS_FACTOR +
+ qGray(source.pixel(i-1,j+1)) * DIAGONAL_FACTOR +
+ qGray(source.pixel(i ,j-1)) * AXIS_FACTOR +
+ 0 +
+ qGray(source.pixel(i ,j+1)) * AXIS_FACTOR +
+ qGray(source.pixel(i+1,j-1)) * DIAGONAL_FACTOR +
+ qGray(source.pixel(i+1,j )) * AXIS_FACTOR +
+ qGray(source.pixel(i+1,j+1)) * DIAGONAL_FACTOR) / m_shadowSettings->multiplicationFactor();
+
+ return alphaShadow;
+}
+
+double KShadowEngine::doubleLinearDecay(QImage& source, int i, int j)
+{
+ //printf("img: %p, %d %d\n", (char *) &source, i, j);
+ return defaultDecay( source, i, j ); // for now
+}
+
+double KShadowEngine::radialDecay(QImage& source, int i, int j)
+{
+ //printf("img: %p, %d %d\n", (char *) &source, i, j);
+ return defaultDecay( source, i, j ); // for now
+}
+
+double KShadowEngine::noDecay(QImage& source, int i, int j)
+{
+ // create a new image for for the shaddow
+ int w = source.width();
+ int h = source.height();
+ int sx, sy;
+ //int thick = m_shadowSettings->thickness() >> 1;
+
+ double alphaShadow = 0;
+ double opacity = 0;
+ for (int k = 1; k <= m_shadowSettings->thickness(); k++) {
+ /* Generate a shadow THICKNESS pixels thicker
+ * on either side than the text image. Ensure
+ * that i +/- k and j +/- k are within the
+ * bounds of the text pixmap.
+ */
+ opacity = 0;
+ for (int l = -k; l <= k; l++) {
+ if (i < k)
+ sx = 0;
+ else if (i >= w - k)
+ sx = w - 1;
+ else
+ sx = i + l;
+
+ for (int m = -k; m <= k; m++) {
+ if (j < k)
+ sy = 0;
+ else if (j >= h - k)
+ sy = h - 1;
+ else
+ sy = j + m;
+
+ opacity += qGray(source.pixel(sx, sy));
+ }
+ }
+ alphaShadow += opacity / m_shadowSettings->multiplicationFactor();
+ }
+ return alphaShadow;
+}
+
+KTextShadowEngine::KTextShadowEngine() : KShadowEngine()
+{
+ KShadowSettings *shadset = new KShadowSettings();
+
+ shadset->setOffsetX(0);
+ shadset->setOffsetY(0);
+ shadset->setThickness(1);
+ shadset->setMaxOpacity(96);
+
+ setShadowSettings(shadset);
+}
+
+// taken from mtaskbar, by Sebastian Wolff
+void KTextShadowEngine::drawText(QPainter &p, const QRect &tr, int tf, const QString &str, const QSize &size)
+{
+ // get the color of the shadow: white for dark text, black for bright text
+ QPen textPen = p.pen();
+ QColor shadCol = textPen.color();
+
+ if (shadCol.red() +
+ shadCol.green() +
+ shadCol.blue() <= 3*256/2-1)
+ {
+ shadCol = QColor(255,255,255);
+ }
+ else
+ {
+ shadCol = QColor(0,0,0);
+ }
+
+ // get a transparent pixmap
+ QPainter pixPainter;
+ QPixmap textPixmap(size);
+
+ textPixmap.fill(QColor(0,0,0));
+ textPixmap.setMask(textPixmap.createHeuristicMask(true));
+
+ // draw text
+ pixPainter.begin(&textPixmap);
+ pixPainter.setPen(Qt::white);
+ pixPainter.setFont(p.font()); // get the font from the root painter
+ pixPainter.drawText(tr, tf, str);
+ pixPainter.end();
+
+ // draw shadow
+ QImage img = makeShadow(textPixmap, shadCol);
+
+ // return
+ p.drawImage(0, 0, img);
+ p.drawText(tr, tf, str);
+}
+
diff --git a/kicker/libkicker/kshadowengine.h b/kicker/libkicker/kshadowengine.h
new file mode 100644
index 000000000..0fc4877fa
--- /dev/null
+++ b/kicker/libkicker/kshadowengine.h
@@ -0,0 +1,123 @@
+/* This file is proposed to be part of the KDE libraries.
+ * Copyright (C) 2003 Laur Ivan <laurivan@eircom.net>
+ *
+ * Many thanks to:
+ * - Bernardo Hung <deciare@gta.igs.net> for the enhanced shadow
+ * algorithm (currently used)
+ * - Tim Jansen <tim@tjansen.de> for the API updates and fixes.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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 __FX_SHADOW
+#define __FX_SHADOW
+
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qcolor.h>
+
+#include <kdemacros.h>
+
+class KShadowSettings;
+
+/**
+ * This class implements the shadow algorithm(s). It uses a FxData
+ * object for its parameters. Note that the shadow algorithm is using the
+ * luminosity of the original pixmap for the shadow one.
+ * @see KShadowSettings
+ * @author laur.ivan@corvil.com
+ * @since 3.2
+ */
+class KDE_EXPORT KShadowEngine
+{
+public:
+ /// Creates a new shadow engine.
+ KShadowEngine();
+
+ ~KShadowEngine();
+
+ /**
+ * Creates a new shadow engine.
+ * @param fx the shadow settings object with the configuration. The Shadow
+ * Engine will own this object and also delete it. Must
+ * be heap-allocated
+ */
+ KShadowEngine(KShadowSettings *fx);
+
+ /**
+ * Set the KShadowSettings object.
+ * @param fx the shadow settings object with the configuration. The Shadow
+ * Engine will own this object and also delete it. Must
+ * be heap-allocated.
+ */
+ void setShadowSettings(KShadowSettings *fx);
+
+ /**
+ * Get the current KShadowSettings.
+ * @param the current shadow settings
+ */
+ KShadowSettings *shadowSettings();
+
+ /**
+ * Make shadow!
+ *
+ * textPixmap is the original pixmap where a (white) text is drawn.
+ * bgColor is the color used for the shadow.
+ * @param textPixmap the pixmap of the text
+ * @param bgColor the background color
+ * @return the resulting image
+ */
+ QImage makeShadow(const QPixmap& textPixmap, const QColor &bgColor);
+
+private:
+ // No static objects in libs, and no static deleters in kdefx...
+ //static KShadowSettings s_defaultShadowSettings;
+
+ KShadowSettings *m_shadowSettings;
+
+ /*
+ * a simple algorithm with 3 pixels thickness
+ */
+ double defaultDecay(QImage& source, int x, int y);
+
+ /*
+ * a slower algorithm where the influence of a pixel
+ * is qGray(px)/(abs(dx) + abs(dy) +1).
+ */
+ double doubleLinearDecay(QImage& source, int x, int y);
+
+ /*
+ * a very slow algorithm where the influence of a pixel
+ * is qGray(px)/(sqrt(sqr(dx) + sqr(dy)) +1).
+ */
+ double radialDecay(QImage& source, int x, int y);
+
+ /*
+ * a nice/fast algorithm proposed by Bernardo Hung
+ */
+ double noDecay(QImage& source, int x, int y);
+
+ void *d;
+};
+
+class KDE_EXPORT KTextShadowEngine : public KShadowEngine
+{
+public:
+ KTextShadowEngine();
+
+ void drawText(QPainter &p, const QRect &tr, int tf, const QString &str, const QSize &size);
+};
+
+#endif
diff --git a/kicker/libkicker/kshadowsettings.cpp b/kicker/libkicker/kshadowsettings.cpp
new file mode 100644
index 000000000..9c935d30f
--- /dev/null
+++ b/kicker/libkicker/kshadowsettings.cpp
@@ -0,0 +1,182 @@
+/* This file is proposed to be part of the KDE libraries.
+ * Copyright (C) 2003 Laur Ivan <laurivan@eircom.net>
+ *
+ * Many thanks to:
+ * - Tim Jansen <tim@tjansen.de> for the API updates and fixes.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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 <qstring.h>
+#include <qstringlist.h>
+#include "kshadowsettings.h"
+
+KShadowSettings::KShadowSettings()
+{
+ // init the components with some default values
+ setDefaults();
+}
+
+// load/save methods
+void KShadowSettings::fromString(const QString &val)
+{
+ setOffsetX(val.section(',', OFFSET_X, OFFSET_X).toInt());
+ setOffsetY(val.section(',', OFFSET_Y, OFFSET_Y).toInt());
+ setMultiplicationFactor(val.section(',', MULTIPLICATION_FACTOR, MULTIPLICATION_FACTOR).toDouble());
+ setMaxOpacity(val.section(',', MAX_OPACITY, MAX_OPACITY).toDouble());
+ setThickness(val.section(',', THICKNESS, THICKNESS).toInt());
+ setAlgorithm((Algorithm) val.section(',', ALGORITHM, ALGORITHM).toInt());
+ setSelectionType((SelectionType)val.section(',', SELECTION_TYPE, SELECTION_TYPE).toInt());
+}
+
+QString KShadowSettings::toString() const
+{
+ QString result;
+ result.sprintf("%d,%d,%f,%f,%d,%d,%d",
+ offsetX(),
+ offsetY(),
+ multiplicationFactor(),
+ maxOpacity(),
+ thickness(),
+ (int)algorithm(),
+ (int)selectionType());
+ return result;
+}
+
+//***********************************
+// get methods
+//***********************************
+
+/**
+ * Returns the decay algorithm to be used (see the alg. enumeration in the .h)
+ */
+KShadowSettings::Algorithm KShadowSettings::algorithm() const
+{
+ return _algorithm;
+}
+
+/**
+ * Returns a multiplication facor used to average the resulted data
+ */
+double KShadowSettings::multiplicationFactor() const
+{
+ return _multiplicationFactor;
+}
+
+/**
+ * Returns the max opacity allowed (0 = transparent, 255 = opaque)
+ */
+double KShadowSettings::maxOpacity() const
+{
+ return _maxOpacity;
+}
+
+/**
+ * Returns the Y offset (0 is centered on text)
+ */
+int KShadowSettings::offsetX() const
+{
+ return _offsetX;
+}
+
+/**
+ * Returns the Y offset (0 is centered on text)
+ */
+int KShadowSettings::offsetY() const
+{
+ return _offsetY;
+}
+
+/**
+ * Returns the thickness. Used by the KShadow algorithm
+ */
+int KShadowSettings::thickness() const
+{
+ return _thickness;
+}
+
+/**
+ * Returns the selection type
+ */
+KShadowSettings::SelectionType KShadowSettings::selectionType() const
+{
+ return _selectionType;
+}
+
+// set methods
+/**
+ * set the default parameters
+ */
+void KShadowSettings::setDefaults()
+{
+ fromString(DEFAULT_SHADOW_CONFIGURATION);
+}
+
+
+/**
+ * Set the algorithm
+ */
+void KShadowSettings::setAlgorithm(Algorithm val)
+{
+ _algorithm = val;
+}
+
+/**
+ * Set the multiplication factor
+ */
+void KShadowSettings::setMultiplicationFactor(double val)
+{
+ _multiplicationFactor = val;
+}
+
+/**
+ * Set the max. opacity
+ */
+void KShadowSettings::setMaxOpacity(double val)
+{
+ _maxOpacity = val;
+}
+
+/**
+ * Set the X offset of the shadow
+ */
+void KShadowSettings::setOffsetX(int val)
+{
+ _offsetX = val;
+}
+
+/**
+ * Set the Y offset of the shadow
+ */
+void KShadowSettings::setOffsetY(int val)
+{
+ _offsetY = val;
+}
+
+/**
+ * Set the shadow thickness
+ */
+void KShadowSettings::setThickness(int val)
+{
+ _thickness = val;
+}
+
+/**
+ * Set the selection type
+ */
+void KShadowSettings::setSelectionType(SelectionType val)
+{
+ _selectionType = val;
+}
diff --git a/kicker/libkicker/kshadowsettings.h b/kicker/libkicker/kshadowsettings.h
new file mode 100644
index 000000000..9a91f1c15
--- /dev/null
+++ b/kicker/libkicker/kshadowsettings.h
@@ -0,0 +1,236 @@
+/* This file is proposed to be part of the KDE libraries.
+ * Copyright (C) 2003 Laur Ivan <laurivan@eircom.net>
+ *
+ * Many thanks to:
+ * - Tim Jansen <tim@tjansen.de> for the API updates and fixes.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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 __FX_DATA
+#define __FX_DATA
+
+#include <kdemacros.h>
+
+#define SHADOW_CONFIG_ENTRY QString("ShadowParameters")
+#define SHADOW_TEXT_COLOR QString("ShadowTextColor")
+#define SHADOW_TEXT_BACKGROUND QString("ShadowTextBackground")
+
+// fallback configuration string
+#define DEFAULT_SHADOW_CONFIGURATION QString("0,0,4.0,120.0,2,1,1,0,0,0")
+
+/**
+ * This class is the implementation of a structure for the
+ * various parameters required by the shadow class.
+ *
+ * One may afford this implementation since the shadow class is
+ * designed to be used as singleton for an application.
+ * @see KShadowEngine
+ * @author laur.ivan@corvil.com
+ * @since 3.2
+ */
+class KDE_EXPORT KShadowSettings
+{
+ public:
+ /**
+ * Specifies the order of the options.
+ * @see fromString
+ */
+ enum ConfigurationOrder
+ {
+ OFFSET_X = 0,
+ OFFSET_Y = OFFSET_X + 1,
+ MULTIPLICATION_FACTOR = OFFSET_Y + 1,
+ MAX_OPACITY = MULTIPLICATION_FACTOR + 1,
+ THICKNESS = MAX_OPACITY + 1,
+ ALGORITHM = THICKNESS + 1,
+ SELECTION_TYPE = ALGORITHM + 1
+ };
+
+ public:
+ /**
+ * The algorithm used.
+ */
+ enum Algorithm
+ {
+ DefaultDecay = 1, ///< the default AXIS/DIAGONAL_FACTOR based alg
+ DoubleLinearDecay, ///< decay factor is 1/dx+dy
+ RadialDecay, ///< decay factor is 1/sqrt(dx*dx + dy*dy)
+ NoDecay ///< decay factor is 1 always
+ };
+
+ /**
+ * The selected method used.
+ */
+ enum SelectionType
+ {
+ InverseVideoOnSelection = 0, ///< when selected, the halo is on I/Video
+ SelectionColorsOnSelection ///< the halo is made w/ selected colors
+ };
+
+ /**
+ * The default constructor.
+ * Creates an object with default settings for all the variabless.
+ */
+ KShadowSettings();
+
+ // load/save methods
+ /**
+ * Loads the configuration from a string.
+ * @param the string to load from (comma-separated values)
+ * @see ConfigurationOrder
+ */
+ virtual void fromString(const QString &s);
+ /**
+ * Saves the configuration to a string.
+ * @return the configuration (comma-separated values)
+ * @see ConfigurationOrder
+ */
+ virtual QString toString() const;
+
+ // get methods
+ /**
+ * Returns the x offset of the shadow.
+ * @return the x offset
+ */
+ int offsetX() const;
+
+ /**
+ * Returns the y offset of the shadow.
+ * @return the y offset
+ */
+ int offsetY() const;
+
+ /**
+ * Returns the multiplication factor.
+ * @return the multiplication factor
+ */
+ double multiplicationFactor() const;
+
+ /**
+ * Returns the maximum opacity of the shadow.
+ * @return the maximum opacity
+ */
+ double maxOpacity() const;
+
+ /**
+ * Returns the thickness.
+ * @return the thickness
+ */
+ int thickness() const;
+
+ /**
+ * Returns the used algorithm.
+ * @return the algorithm used
+ */
+ Algorithm algorithm() const;
+
+ /**
+ * Returns the selection type used.
+ * @return the selection type
+ */
+ SelectionType selectionType() const;
+
+ // set methods
+ /**
+ * Sets default values.
+ */
+ virtual void setDefaults();
+
+ /**
+ * Sets the used algorithm.
+ * @param a the algorithm used
+ */
+ virtual void setAlgorithm(Algorithm a);
+
+ /**
+ * Sets the multiplication factor.
+ * @param mf the multiplication factor
+ */
+ virtual void setMultiplicationFactor(double mf);
+
+ /**
+ * Sets the maximum opacity of the shadow.
+ * @param mo the maximum opacity
+ */
+ virtual void setMaxOpacity(double mo);
+
+ /**
+ * Sets the x offset of the shadow.
+ * @param x the x offset
+ */
+ virtual void setOffsetX(int x);
+
+ /**
+ * Sets the y offset of the shadow.
+ * @param y the y offset
+ */
+ virtual void setOffsetY(int y);
+
+ /**
+ * Sets the thickness.
+ * @param t the thickness
+ */
+ virtual void setThickness(int t);
+
+ /**
+ * Sets the selection type used.
+ * @param s the selection type
+ */
+ virtual void setSelectionType(SelectionType s);
+
+ private:
+
+ /*
+ * The employed algorithm (see fxshadow.h)
+ */
+ Algorithm _algorithm;
+
+ /**
+ * This is the multiplication factor for the resulted shadow
+ */
+ double _multiplicationFactor;
+
+ /**
+ * The maximum permitted opacity for the shadow
+ */
+ double _maxOpacity;
+
+ /*
+ * offsetX and offsetY are the x/y offsets of the shadow with
+ * the mention that 0,0 is a centered shadow.
+ */
+ int _offsetX;
+ int _offsetY;
+
+ /*
+ * The shadow thickness:
+ * shadow is this many pixels thicker than the text.
+ */
+ int _thickness;
+
+ /*
+ * If the value is InverseVideoOnSelection, then the fg/bg
+ * colours are swapped when the element is selected.
+ * Otherwise, the selected fg/bg colors are used for text
+ * as well
+ */
+ SelectionType _selectionType;
+
+ void *d;
+};
+
+
+#endif
diff --git a/kicker/libkicker/menuinfo.cpp b/kicker/libkicker/menuinfo.cpp
new file mode 100644
index 000000000..740d44d95
--- /dev/null
+++ b/kicker/libkicker/menuinfo.cpp
@@ -0,0 +1,68 @@
+/*****************************************************************
+
+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 "menuinfo.h"
+
+#include <qfile.h>
+#include <qwidget.h>
+
+#include <kapplication.h>
+#include <ksimpleconfig.h>
+#include <klibloader.h>
+#include <kstandarddirs.h>
+#include <kpanelmenu.h>
+#include <kparts/componentfactory.h>
+
+MenuInfo::MenuInfo(const QString& desktopFile)
+{
+ KSimpleConfig df(locate("data", QString::fromLatin1("kicker/menuext/%1").arg(desktopFile)));
+ df.setGroup("Desktop Entry");
+
+ QStringList list = df.readListEntry("X-KDE-AuthorizeAction");
+ if (kapp && !list.isEmpty())
+ {
+ for(QStringList::ConstIterator it = list.begin();
+ it != list.end();
+ ++it)
+ {
+ if (!kapp->authorize((*it).stripWhiteSpace()))
+ return;
+ }
+ }
+
+ name_ = df.readEntry("Name");
+ comment_ = df.readEntry("Comment");
+ icon_ = df.readEntry("Icon");
+ library_ = df.readEntry("X-KDE-Library");
+ desktopfile_ = desktopFile;
+}
+
+KPanelMenu* MenuInfo::load(QWidget *parent, const char *name)
+{
+ if (library_.isEmpty())
+ return 0;
+
+ return KParts::ComponentFactory::createInstanceFromLibrary<KPanelMenu>(
+ QFile::encodeName( library_ ),
+ parent, name );
+}
diff --git a/kicker/libkicker/menuinfo.h b/kicker/libkicker/menuinfo.h
new file mode 100644
index 000000000..0d324538e
--- /dev/null
+++ b/kicker/libkicker/menuinfo.h
@@ -0,0 +1,52 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef _menuinfo_h_
+#define _menuinfo_h_
+
+#include <qstring.h>
+
+#include <kdemacros.h>
+
+class KPanelMenu;
+class QWidget;
+
+class KDE_EXPORT MenuInfo
+{
+public:
+ MenuInfo(const QString& desktopFile);
+
+ QString name() const { return name_; }
+ QString comment() const { return comment_; }
+ QString icon() const { return icon_; }
+ QString library() const { return library_; }
+ QString desktopFile() const { return desktopfile_; }
+ bool isValid() const { return !name_.isEmpty(); }
+
+ KPanelMenu* load(QWidget *parent = 0, const char *name = 0);
+
+private:
+ QString name_, comment_, icon_, library_, desktopfile_;
+};
+
+#endif
diff --git a/kicker/libkicker/panelbutton.cpp b/kicker/libkicker/panelbutton.cpp
new file mode 100644
index 000000000..f53d4b38f
--- /dev/null
+++ b/kicker/libkicker/panelbutton.cpp
@@ -0,0 +1,985 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qcursor.h>
+#include <qfile.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+#include <qpopupmenu.h>
+#include <qstyle.h>
+#include <qstylesheet.h>
+#include <qtooltip.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdialog.h>
+#include <kdirwatch.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <kicontheme.h>
+#include <kipc.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+
+#include "global.h"
+
+#include "kshadowengine.h"
+#include "kshadowsettings.h"
+
+#include "kickerSettings.h"
+#include "panelbutton.h"
+#include "panelbutton.moc"
+
+// init static variable
+KShadowEngine* PanelButton::s_textShadowEngine = 0L;
+
+PanelButton::PanelButton( QWidget* parent, const char* name )
+ : QButton(parent, name),
+ m_valid(true),
+ m_isLeftMouseButtonDown(false),
+ m_drawArrow(false),
+ m_highlight(false),
+ m_changeCursorOverItem(true),
+ m_hasAcceptedDrag(false),
+ m_arrowDirection(KPanelExtension::Bottom),
+ m_popupDirection(KPanelApplet::Up),
+ m_orientation(Horizontal),
+ m_size((KIcon::StdSizes)-1),
+ m_fontPercent(0.40)
+{
+ setBackgroundOrigin(AncestorOrigin);
+ setWFlags(WNoAutoErase);
+ KGlobal::locale()->insertCatalogue("libkicker");
+ calculateIconSize();
+ setAcceptDrops(true);
+
+ m_textColor = KGlobalSettings::textColor();
+
+ updateSettings(KApplication::SETTINGS_MOUSE);
+
+ kapp->addKipcEventMask(KIPC::SettingsChanged | KIPC::IconChanged);
+
+ installEventFilter(KickerTip::the());
+
+ connect(kapp, SIGNAL(settingsChanged(int)), SLOT(updateSettings(int)));
+ connect(kapp, SIGNAL(iconChanged(int)), SLOT(updateIcon(int)));
+}
+
+void PanelButton::configure()
+{
+ QString name = tileName();
+ if( name.isEmpty() )
+ return;
+
+ if (!KickerSettings::enableTileBackground())
+ {
+ setTile(QString::null);
+ return;
+ }
+
+ KConfigGroup tilesGroup( KGlobal::config(), "button_tiles" );
+ if( !tilesGroup.readBoolEntry( "Enable" + name + "Tiles", true ) ) {
+ setTile( QString::null );
+ return;
+ }
+
+ QString tile = tilesGroup.readEntry( name + "Tile" );
+ QColor color = QColor();
+
+ if (tile == "Colorize")
+ {
+ color = tilesGroup.readColorEntry( name + "TileColor" );
+ tile = QString::null;
+ }
+
+ setTile( tile, color );
+}
+
+void PanelButton::setTile(const QString& tile, const QColor& color)
+{
+ if (tile == m_tile && m_tileColor == color)
+ {
+ return;
+ }
+
+ m_tile = tile;
+ m_tileColor = color;
+ loadTiles();
+ update();
+}
+
+void PanelButton::setDrawArrow(bool drawArrow)
+{
+ if (m_drawArrow == drawArrow)
+ {
+ return;
+ }
+
+ m_drawArrow = drawArrow;
+ update();
+}
+
+QImage PanelButton::loadTile(const QString& tile,
+ const QSize& size,
+ const QString& state)
+{
+ QString name = tile;
+
+ if (size.height() < 42)
+ {
+ name += "_tiny_";
+ }
+ else if (size.height() < 54)
+ {
+ name += "_normal_";
+ }
+ else
+ {
+ name += "_large_";
+ }
+
+ name += state + ".png";
+
+ QImage tileImg(KGlobal::dirs()->findResource("tiles", name));
+
+ // scale if size does not match exactly
+ if (!tileImg.isNull() && tileImg.size() != size)
+ {
+ tileImg = tileImg.smoothScale(size);
+ }
+
+ return tileImg;
+}
+
+void PanelButton::setEnabled(bool enable)
+{
+ QButton::setEnabled(enable);
+ loadIcons();
+ update();
+}
+
+void PanelButton::setPopupDirection(KPanelApplet::Direction d)
+{
+ m_popupDirection = d;
+ setArrowDirection(KickerLib::directionToPopupPosition(d));
+}
+
+void PanelButton::setOrientation(Orientation o)
+{
+ m_orientation = o;
+}
+
+void PanelButton::updateIcon(int group)
+{
+ if (group != KIcon::Panel)
+ {
+ return;
+ }
+
+ loadIcons();
+ update();
+}
+
+void PanelButton::updateSettings(int category)
+{
+ if (category != KApplication::SETTINGS_MOUSE)
+ {
+ return;
+ }
+
+ m_changeCursorOverItem = KGlobalSettings::changeCursorOverIcon();
+
+ if (m_changeCursorOverItem)
+ {
+ setCursor(KCursor::handCursor());
+ }
+ else
+ {
+ unsetCursor();
+ }
+}
+
+void PanelButton::checkForDeletion(const QString& path)
+{
+ if (path == m_backingFile)
+ {
+ setEnabled(false);
+ QTimer::singleShot(1000, this, SLOT(scheduleForRemoval()));
+ }
+}
+
+bool PanelButton::checkForBackingFile()
+{
+ return QFile::exists(m_backingFile);
+}
+
+void PanelButton::scheduleForRemoval()
+{
+ static int timelapse = 1000;
+ if (checkForBackingFile())
+ {
+ setEnabled(true);
+ timelapse = 1000;
+ emit hideme(false);
+ return;
+ }
+ else if (KickerSettings::removeButtonsWhenBroken())
+ {
+ if (timelapse > 255*1000) // we'v given it ~8.5 minutes by this point
+ {
+ emit removeme();
+ return;
+ }
+
+ if (timelapse > 3000 && isVisible())
+ {
+ emit hideme(true);
+ }
+
+ timelapse *= 2;
+ QTimer::singleShot(timelapse, this, SLOT(scheduleForRemoval()));
+ }
+}
+
+// return the dimension that the button wants to be for a given panel dimension (panelDim)
+int PanelButton::preferredDimension(int panelDim) const
+{
+ // determine the upper limit on the size. Normally, this is panelDim,
+ // but if conserveSpace() is true, we restrict size to comfortably fit the icon
+ if (KickerSettings::conserveSpace())
+ {
+ int newSize = preferredIconSize(panelDim);
+ if (newSize > 0)
+ {
+ return QMIN(panelDim, newSize + (KDialog::spacingHint() * 2));
+ }
+ }
+
+ return panelDim;
+}
+
+int PanelButton::widthForHeight(int height) const
+{
+ int rc = preferredDimension(height);
+
+ // we only paint the text when horizontal, so make sure we're horizontal
+ // before adding the text in here
+ if (orientation() == Horizontal && !m_buttonText.isEmpty())
+ {
+ QFont f(font());
+ f.setPixelSize(KMIN(height, KMAX(int(float(height) * m_fontPercent), 16)));
+ QFontMetrics fm(f);
+
+ rc += fm.width(m_buttonText) + KMIN(25, KMAX(5, fm.width('m') / 2));
+ }
+
+ return rc;
+}
+
+int PanelButton::heightForWidth(int width) const
+{
+ return preferredDimension(width);
+}
+
+const QPixmap& PanelButton::labelIcon() const
+{
+ return m_highlight ? m_iconh : m_icon;
+}
+
+const QPixmap& PanelButton::zoomIcon() const
+{
+ return m_iconz;
+}
+
+bool PanelButton::isValid() const
+{
+ return m_valid;
+}
+
+void PanelButton::setTitle(const QString& t)
+{
+ m_title = t;
+}
+
+void PanelButton::setIcon(const QString& icon)
+{
+ if (icon == m_iconName)
+ {
+ return;
+ }
+
+ m_iconName = icon;
+ loadIcons();
+ update();
+ emit iconChanged();
+}
+
+QString PanelButton::icon() const
+{
+ return m_iconName;
+}
+
+bool PanelButton::hasText() const
+{
+ return !m_buttonText.isEmpty();
+}
+
+void PanelButton::setButtonText(const QString& text)
+{
+ m_buttonText = text;
+ update();
+}
+
+QString PanelButton::buttonText() const
+{
+ return m_buttonText;
+}
+
+void PanelButton::setTextColor(const QColor& c)
+{
+ m_textColor = c;
+}
+
+QColor PanelButton::textColor() const
+{
+ return m_textColor;
+}
+
+void PanelButton::setFontPercent(double p)
+{
+ m_fontPercent = p;
+}
+
+double PanelButton::fontPercent() const
+{
+ return m_fontPercent;
+}
+
+KPanelExtension::Orientation PanelButton::orientation() const
+{
+ return m_orientation;
+}
+
+KPanelApplet::Direction PanelButton::popupDirection() const
+{
+ return m_popupDirection;
+}
+
+QPoint PanelButton::center() const
+{
+ return mapToGlobal(rect().center());
+}
+
+QString PanelButton::title() const
+{
+ return m_title;
+}
+
+void PanelButton::triggerDrag()
+{
+ setDown(false);
+
+ startDrag();
+}
+
+void PanelButton::startDrag()
+{
+ emit dragme(m_icon);
+}
+
+void PanelButton::enterEvent(QEvent* e)
+{
+ if (!m_highlight)
+ {
+ m_highlight = true;
+ repaint(false);
+ }
+
+ QButton::enterEvent(e);
+}
+
+void PanelButton::leaveEvent(QEvent* e)
+{
+ if (m_highlight)
+ {
+ m_highlight = false;
+ repaint(false);
+ }
+
+ QButton::leaveEvent(e);
+}
+
+void PanelButton::dragEnterEvent(QDragEnterEvent* e)
+{
+ if (e->isAccepted())
+ {
+ m_hasAcceptedDrag = true;
+ }
+
+ update();
+ QButton::dragEnterEvent( e );
+}
+
+void PanelButton::dragLeaveEvent(QDragLeaveEvent* e)
+{
+ m_hasAcceptedDrag = false;
+ update();
+ QButton::dragLeaveEvent( e );
+}
+
+void PanelButton::dropEvent(QDropEvent* e)
+{
+ m_hasAcceptedDrag = false;
+ update();
+ QButton::dropEvent( e );
+}
+
+void PanelButton::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!m_isLeftMouseButtonDown || (e->state() & LeftButton) == 0)
+ {
+ return;
+ }
+
+ QPoint p(e->pos() - m_lastLeftMouseButtonPress);
+ if (p.manhattanLength() <= 16)
+ {
+ // KGlobalSettings::dndEventDelay() is not enough!
+ return;
+ }
+
+ m_isLeftMouseButtonDown = false;
+ triggerDrag();
+}
+
+void PanelButton::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == LeftButton)
+ {
+ m_lastLeftMouseButtonPress = e->pos();
+ m_isLeftMouseButtonDown = true;
+ }
+ QButton::mousePressEvent(e);
+}
+
+void PanelButton::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() == LeftButton)
+ {
+ m_isLeftMouseButtonDown = false;
+ }
+ QButton::mouseReleaseEvent(e);
+}
+
+void PanelButton::resizeEvent(QResizeEvent*)
+{
+ loadTiles();
+
+ if (calculateIconSize())
+ {
+ loadIcons();
+ }
+}
+
+void PanelButton::drawButton(QPainter *p)
+{
+ const QPixmap& tile = (isDown() || isOn()) ? m_down : m_up;
+
+ if (m_tileColor.isValid())
+ {
+ p->fillRect(rect(), m_tileColor);
+ style().drawPrimitive(QStyle::PE_Panel, p, rect(), colorGroup());
+ }
+ else if (paletteBackgroundPixmap())
+ {
+ // Draw the background. This is always needed, even when using tiles,
+ // because they don't have to cover the entire button.
+ QPoint offset = backgroundOffset();
+ int ox = offset.x();
+ int oy = offset.y();
+ p->drawTiledPixmap( 0, 0, width(), height(),*paletteBackgroundPixmap(), ox, oy);
+ }
+
+ if (!tile.isNull())
+ {
+ // Draw the tile.
+ p->drawPixmap(0, 0, tile);
+ }
+ else if (isDown() || isOn())
+ {
+ // Draw shapes to indicate the down state.
+ style().drawPrimitive(QStyle::PE_Panel, p, rect(), colorGroup(), QStyle::Style_Sunken);
+ }
+
+ drawButtonLabel(p);
+
+ if (hasFocus() || m_hasAcceptedDrag)
+ {
+ int x1, y1, x2, y2;
+ rect().coords(&x1, &y1, &x2, &y2);
+ QRect r(x1+2, y1+2, x2-x1-3, y2-y1-3);
+ style().drawPrimitive(QStyle::PE_FocusRect, p, r, colorGroup(),
+ QStyle::Style_Default, colorGroup().button());
+ }
+}
+
+void PanelButton::drawButtonLabel(QPainter *p)
+{
+ QPixmap icon = labelIcon();
+ bool active = isDown() || isOn();
+
+ if (active)
+ {
+ icon = icon.convertToImage().smoothScale(icon.width() - 2,
+ icon.height() - 2);
+ }
+
+ if (!m_buttonText.isEmpty() && orientation() == Horizontal)
+ {
+ int h = height();
+ int w = width();
+ int y = (h - icon.height())/2;
+ p->save();
+ QFont f = font();
+
+ double fontPercent = m_fontPercent;
+ if (active)
+ {
+ fontPercent *= .8;
+ }
+ f.setPixelSize(KMIN(h, KMAX(int(float(h) * m_fontPercent), 16)));
+ QFontMetrics fm(f);
+ p->setFont(f);
+
+ /* Draw shadowed text */
+ bool reverse = QApplication::reverseLayout();
+ QPainter::TextDirection rtl = reverse ? QPainter::RTL : QPainter::LTR;
+
+ if (!reverse && !icon.isNull())
+ {
+ /* Draw icon */
+ p->drawPixmap(3, y, icon);
+ }
+
+ int tX = reverse ? 3 : icon.width() + KMIN(25, KMAX(5, fm.width('m') / 2));
+ int tY = fm.ascent() + ((h - fm.height()) / 2);
+
+ QColor shadCol = KickerLib::shadowColor(m_textColor);
+
+ // get a transparent pixmap
+ QPainter pixPainter;
+ QPixmap textPixmap(w, h);
+
+ textPixmap.fill(QColor(0,0,0));
+ textPixmap.setMask(textPixmap.createHeuristicMask(true));
+
+ // draw text
+ pixPainter.begin(&textPixmap);
+ pixPainter.setPen(m_textColor);
+ pixPainter.setFont(p->font()); // get the font from the root painter
+ pixPainter.drawText(tX, tY, m_buttonText, -1, rtl);
+ pixPainter.end();
+
+ if (!s_textShadowEngine)
+ {
+ KShadowSettings* shadset = new KShadowSettings();
+ shadset->setOffsetX(0);
+ shadset->setOffsetY(0);
+ shadset->setThickness(1);
+ shadset->setMaxOpacity(96);
+ s_textShadowEngine = new KShadowEngine(shadset);
+ }
+
+ // draw shadow
+ QImage img = s_textShadowEngine->makeShadow(textPixmap, shadCol);
+ p->drawImage(0, 0, img);
+ p->save();
+ p->setPen(m_textColor);
+ p->drawText(tX, tY, m_buttonText, -1, rtl);
+ p->restore();
+
+ if (reverse && !icon.isNull())
+ {
+ p->drawPixmap(w - icon.width() - 3, y, icon);
+ }
+
+ p->restore();
+ }
+ else if (!icon.isNull())
+ {
+ int y = (height() - icon.height()) / 2;
+ int x = (width() - icon.width()) / 2;
+ p->drawPixmap(x, y, icon);
+ }
+
+ if (m_drawArrow && (m_highlight || active))
+ {
+ QStyle::PrimitiveElement e = QStyle::PE_ArrowUp;
+ int arrowSize = style().pixelMetric(QStyle::PM_MenuButtonIndicator);
+ QRect r((width() - arrowSize)/2, 0, arrowSize, arrowSize);
+
+ switch (m_arrowDirection)
+ {
+ case KPanelExtension::Top:
+ e = QStyle::PE_ArrowUp;
+ break;
+ case KPanelExtension::Bottom:
+ e = QStyle::PE_ArrowDown;
+ r.moveBy(0, height() - arrowSize);
+ break;
+ case KPanelExtension::Right:
+ e = QStyle::PE_ArrowRight;
+ r = QRect(width() - arrowSize, (height() - arrowSize)/2, arrowSize, arrowSize);
+ break;
+ case KPanelExtension::Left:
+ e = QStyle::PE_ArrowLeft;
+ r = QRect(0, (height() - arrowSize)/2, arrowSize, arrowSize);
+ break;
+ case KPanelExtension::Floating:
+ if (orientation() == Horizontal)
+ {
+ e = QStyle::PE_ArrowDown;
+ r.moveBy(0, height() - arrowSize);
+ }
+ else if (QApplication::reverseLayout())
+ {
+ e = QStyle::PE_ArrowLeft;
+ r = QRect(0, (height() - arrowSize)/2, arrowSize, arrowSize);
+ }
+ else
+ {
+ e = QStyle::PE_ArrowRight;
+ r = QRect(width() - arrowSize, (height() - arrowSize)/2, arrowSize, arrowSize);
+ }
+ break;
+ }
+
+ int flags = QStyle::Style_Enabled;
+ if (active)
+ {
+ flags |= QStyle::Style_Down;
+ }
+ style().drawPrimitive(e, p, r, colorGroup(), flags);
+ }
+}
+
+// return the icon size that would be used if the panel were proposed_size
+// if proposed_size==-1, use the current panel size instead
+int PanelButton::preferredIconSize(int proposed_size) const
+{
+ // (re)calculates the icon sizes and report true if they have changed.
+ // Get sizes from icontheme. We assume they are sorted.
+ KIconTheme *ith = KGlobal::iconLoader()->theme();
+
+ if (!ith)
+ {
+ return -1; // unknown icon size
+ }
+
+ QValueList<int> sizes = ith->querySizes(KIcon::Panel);
+
+ int sz = ith->defaultSize(KIcon::Panel);
+
+ if (proposed_size < 0)
+ {
+ proposed_size = (orientation() == Horizontal) ? height() : width();
+ }
+
+ // determine the upper limit on the size. Normally, this is panelSize,
+ // but if conserve space is requested, the max button size is used instead.
+ int upperLimit = proposed_size;
+ if (proposed_size > KickerLib::maxButtonDim() &&
+ KickerSettings::conserveSpace())
+ {
+ upperLimit = KickerLib::maxButtonDim();
+ }
+
+ //kdDebug()<<endl<<endl<<flush;
+ QValueListConstIterator<int> i = sizes.constBegin();
+ while (i != sizes.constEnd())
+ {
+ if ((*i) + (2 * KickerSettings::iconMargin()) > upperLimit)
+ {
+ break;
+ }
+ sz = *i; // get the largest size under the limit
+ ++i;
+ }
+
+ //kdDebug()<<"Using icon sizes: "<<sz<<" "<<zoom_sz<<endl<<flush;
+ return sz;
+}
+
+void PanelButton::backedByFile(const QString& localFilePath)
+{
+ m_backingFile = localFilePath;
+
+ if (m_backingFile.isEmpty())
+ {
+ return;
+ }
+
+ // avoid multiple connections
+ disconnect(KDirWatch::self(), SIGNAL(deleted(const QString&)),
+ this, SLOT(checkForDeletion(const QString&)));
+
+ if (!KDirWatch::self()->contains(m_backingFile))
+ {
+ KDirWatch::self()->addFile(m_backingFile);
+ }
+
+ connect(KDirWatch::self(), SIGNAL(deleted(const QString&)),
+ this, SLOT(checkForDeletion(const QString&)));
+
+}
+
+void PanelButton::setArrowDirection(KPanelExtension::Position dir)
+{
+ if (m_arrowDirection != dir)
+ {
+ m_arrowDirection = dir;
+ update();
+ }
+}
+
+void PanelButton::loadTiles()
+{
+ if (m_tileColor.isValid())
+ {
+ setBackgroundOrigin(WidgetOrigin);
+ m_up = m_down = QPixmap();
+ }
+ else if (m_tile.isNull())
+ {
+ setBackgroundOrigin(AncestorOrigin);
+ m_up = m_down = QPixmap();
+ }
+ else
+ {
+ setBackgroundOrigin(WidgetOrigin);
+ // If only the tiles were named a bit smarter we wouldn't have
+ // to pass the up or down argument.
+ m_up = QPixmap(loadTile(m_tile, size(), "up"));
+ m_down = QPixmap(loadTile(m_tile, size(), "down"));
+ }
+}
+
+void PanelButton::loadIcons()
+{
+ KIconLoader * ldr = KGlobal::iconLoader();
+ QString nm = m_iconName;
+ KIcon::States defaultState = isEnabled() ? KIcon::DefaultState :
+ KIcon::DisabledState;
+ m_icon = ldr->loadIcon(nm, KIcon::Panel, m_size, defaultState, 0L, true);
+
+ if (m_icon.isNull())
+ {
+ nm = defaultIcon();
+ m_icon = ldr->loadIcon(nm, KIcon::Panel, m_size, defaultState);
+ }
+
+ if (!isEnabled())
+ {
+ m_iconh = m_icon;
+ }
+ else
+ {
+ m_iconh = ldr->loadIcon(nm, KIcon::Panel, m_size,
+ KIcon::ActiveState, 0L, true);
+ }
+
+ m_iconz = ldr->loadIcon(nm, KIcon::Panel, KIcon::SizeHuge,
+ defaultState, 0L, true );
+}
+
+// (re)calculates the icon sizes and report true if they have changed.
+// (false if we don't know, because theme couldn't be loaded?)
+bool PanelButton::calculateIconSize()
+{
+ int size = preferredIconSize();
+
+ if (size < 0)
+ {
+ // size unknown
+ return false;
+ }
+
+ if (m_size != size)
+ {
+ // Size has changed, update
+ m_size = size;
+ return true;
+ }
+
+ return false;
+}
+
+void PanelButton::updateKickerTip(KickerTip::Data& data)
+{
+ data.message = QStyleSheet::escape(title());
+ data.subtext = QStyleSheet::escape(QToolTip::textFor(this));
+ data.icon = zoomIcon();
+ data.direction = popupDirection();
+}
+
+//
+// PanelPopupButton class
+//
+
+PanelPopupButton::PanelPopupButton(QWidget *parent, const char *name)
+ : PanelButton(parent, name),
+ m_popup(0),
+ m_pressedDuringPopup(false),
+ m_initialized(false)
+{
+ connect(this, SIGNAL(pressed()), SLOT(slotExecMenu()));
+}
+
+void PanelPopupButton::setPopup(QPopupMenu *popup)
+{
+ if (m_popup)
+ {
+ m_popup->removeEventFilter(this);
+ disconnect(m_popup, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
+ }
+
+ m_popup = popup;
+ setDrawArrow(m_popup != 0);
+
+ if (m_popup)
+ {
+ m_popup->installEventFilter(this);
+ connect(m_popup, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
+ }
+}
+
+QPopupMenu *PanelPopupButton::popup() const
+{
+ return m_popup;
+}
+
+bool PanelPopupButton::eventFilter(QObject *, QEvent *e)
+{
+ if (e->type() == QEvent::MouseMove)
+ {
+ QMouseEvent *me = static_cast<QMouseEvent *>(e);
+ if (rect().contains(mapFromGlobal(me->globalPos())) &&
+ ((me->state() & ControlButton) != 0 ||
+ (me->state() & ShiftButton) != 0))
+ {
+ PanelButton::mouseMoveEvent(me);
+ return true;
+ }
+ }
+ else if (e->type() == QEvent::MouseButtonPress ||
+ e->type() == QEvent::MouseButtonDblClick)
+ {
+ QMouseEvent *me = static_cast<QMouseEvent *>(e);
+ if (rect().contains(mapFromGlobal(me->globalPos())))
+ {
+ m_pressedDuringPopup = true;
+ return true;
+ }
+ }
+ else if (e->type() == QEvent::MouseButtonRelease)
+ {
+ QMouseEvent *me = static_cast<QMouseEvent *>(e);
+ if (rect().contains(mapFromGlobal(me->globalPos())))
+ {
+ if (m_pressedDuringPopup && m_popup)
+ {
+ m_popup->hide();
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void PanelPopupButton::showMenu()
+{
+ if (isDown())
+ {
+ if (m_popup)
+ {
+ m_popup->hide();
+ }
+
+ setDown(false);
+ return;
+ }
+
+ setDown(true);
+ update();
+ slotExecMenu();
+}
+
+void PanelPopupButton::slotExecMenu()
+{
+ if (!m_popup)
+ {
+ return;
+ }
+
+ m_pressedDuringPopup = false;
+ KickerTip::enableTipping(false);
+ kapp->syncX();
+ kapp->processEvents();
+
+ if (!m_initialized)
+ {
+ initPopup();
+ }
+
+ m_popup->adjustSize();
+ m_popup->exec(KickerLib::popupPosition(popupDirection(), m_popup, this));
+}
+
+void PanelPopupButton::menuAboutToHide()
+{
+ if (!m_popup)
+ {
+ return;
+ }
+
+ setDown(false);
+ KickerTip::enableTipping(true);
+}
+
+void PanelPopupButton::triggerDrag()
+{
+ if (m_popup)
+ {
+ m_popup->hide();
+ }
+
+ PanelButton::triggerDrag();
+}
+
+void PanelPopupButton::setInitialized(bool initialized)
+{
+ m_initialized = initialized;
+}
+
diff --git a/kicker/libkicker/panelbutton.h b/kicker/libkicker/panelbutton.h
new file mode 100644
index 000000000..f71865c77
--- /dev/null
+++ b/kicker/libkicker/panelbutton.h
@@ -0,0 +1,471 @@
+/*****************************************************************
+
+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 __panelbutton_h__
+#define __panelbutton_h__
+
+#include <algorithm>
+
+#include <qbutton.h>
+
+#include <kpanelapplet.h>
+#include <kpanelextension.h>
+#include <kurldrag.h>
+
+#include "kickertip.h"
+
+class QPopupMenu;
+class KConfigGroup;
+class KShadowEngine;
+
+/**
+ * PanelButton is the base class for all buttons to be
+ * placed in Kicker's panels. It inherits QButton, and
+ * KickerTip::Client.
+ */
+class KDE_EXPORT PanelButton: public QButton, public KickerTip::Client
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Create a panel button
+ * @param parent the parent widget
+ * @param name the widget's name
+ */
+ PanelButton( QWidget* parent, const char* name );
+
+ /**
+ * Configures this button according to the user's preferences for
+ * button tiles/colors/etc. This must be called by the container
+ * embedding the button after consturction and thereafter whenever
+ * the configuration changes to ensure it remains properly styled.
+ * Note that it is not used for configuration specific to the subclass.
+ */
+ void configure();
+
+ /**
+ * Prompts the button to save it's configuration. Subclass specific
+ * settings should be saved in this method to the KConfigGroup passed in.
+ */
+ virtual void saveConfig(KConfigGroup&) const {}
+
+ /**
+ * Reimplement this to display a properties dialog for your button.
+ */
+ virtual void properties() {}
+
+ /**
+ * Reimplement this to give Kicker a hint for the width of the button
+ * given a certain height.
+ */
+ virtual int widthForHeight(int height) const;
+
+ /**
+ * Reimplement this to give Kicker a hint for the height of the button
+ * given a certain width.
+ */
+ virtual int heightForWidth(int width) const;
+
+ /**
+ * @return the button's current icon
+ */
+ virtual const QPixmap& labelIcon() const;
+
+ /**
+ * @return the button's zoom icon
+ */
+ virtual const QPixmap& zoomIcon() const;
+
+ /**
+ * @return true if this button is valid.
+ */
+ bool isValid() const;
+
+ /**
+ * Changes the title for the panel button.
+ * @param t the button's title
+ */
+ void setTitle(const QString& t);
+
+ /**
+ * @return the title of the button.
+ */
+ QString title() const;
+
+ /**
+ * Changes the name of the panel button's tile, with
+ * optional color.
+ * @param tile the button's tile name
+ * @param color the button's tile color
+ */
+ void setTile(const QString& tile, const QColor& color = QColor());
+
+ /**
+ * Set to true to draw an arrow on the button.
+ */
+ void setDrawArrow(bool drawArrow);
+
+ /**
+ * Used to set the icon for this panel button.
+ * @param icon the path to the button's icon
+ */
+ void setIcon(const QString& icon);
+
+ /**
+ * @return the button's icon
+ */
+ QString icon() const;
+
+ /**
+ * @return whether this button has a text label or not
+ */
+ bool hasText() const;
+
+ /**
+ * Change the button's text label
+ * @param text text for button's label
+ */
+ void setButtonText(const QString& text);
+
+ /**
+ * @return button's text label
+ */
+ QString buttonText() const;
+
+ /**
+ * Change the button's text label color
+ * @param c the new text label color
+ */
+ void setTextColor(const QColor& c);
+
+ /**
+ * @return the button's text label color
+ */
+ QColor textColor() const;
+
+ /**
+ * Change the button's text scale
+ * @param p font scale (in percent)
+ */
+ void setFontPercent(double p);
+
+ /**
+ * @return the button's text scale (in percent)
+ */
+ double fontPercent() const;
+
+ /**
+ * @return the orientation of the button
+ */
+ Orientation orientation() const;
+
+ /**
+ * @return the button's popup direction (read from parent KPanelApplet)
+ */
+ KPanelApplet::Direction popupDirection() const;
+
+ /**
+ * @return global position of the center of the button
+ */
+ QPoint center() const;
+
+ /**
+ * Used to load the graphical tile of the button
+ * @param name path/name of button's tile
+ * @param size size of the tile
+ * @param state used if button has multiple states (null by default)
+ */
+ static QImage loadTile(const QString& name, const QSize&,
+ const QString& state = QString::null);
+
+ /**
+ * Update the contents of the button's KickerTip
+ * @param data new KickerTip data
+ */
+ void updateKickerTip(KickerTip::Data& data);
+
+signals:
+ /**
+ * Emitted when the button's icon is changed.
+ */
+ void iconChanged();
+
+ /**
+ * Emitted to notify parent containers to save config
+ */
+ void requestSave();
+
+ /**
+ * Emitted when the button needs to be removed from it's container
+ * @see KickerSettings::removeButtonsWhenBroken()
+ */
+ void removeme();
+
+ /**
+ * Emitted when the button may need to be removed, but that removal depends
+ * on as-yet-uncertain future events and therefore ought to be hidden from
+ * view, though not deleted quite yet.
+ * @see KickerSettings::removeButtonsWhenBroken()
+ */
+ void hideme(bool hide);
+
+ /**
+ * Emitted when button initiates a drag
+ */
+ void dragme(const QPixmap);
+
+ /**
+ * Overloads dragme to support panel button's with a list of KURL's ([url/servicemenu/browser]button)
+ */
+ void dragme(const KURL::List, const QPixmap);
+
+public slots:
+ /**
+ * Set to true to enable the button.
+ */
+ void setEnabled(bool enable);
+
+ /**
+ * Sets the orientation of the button (ie. which direction the icon will rotate).
+ */
+ void setOrientation(Orientation o);
+
+ /**
+ * Sets the direction to pop up the contents of the button.
+ */
+ void setPopupDirection(KPanelApplet::Direction d);
+
+protected:
+ /**
+ * Subclasses must implement this to define the name of the button which is
+ * used to identify this button for saving and loading. It must be unique
+ * to the subclass, should not be i18n'd and is never made user visible.
+ * KDE4: remove this and use the classname directly instead.
+ */
+ virtual QString tileName() = 0;
+
+ /**
+ * @return the default icon for the button
+ */
+ virtual QString defaultIcon() const { return "unknown"; };
+
+ /**
+ * Called right before drag occurs.
+ */
+ virtual void triggerDrag();
+
+ /**
+ * Emits a signal to drag the button. Reimplement this if, for example,
+ * if you need the button to call dragme(KURL::List, const QPixmap)
+ * instead of dragme(const QPixmap)
+ */
+ virtual void startDrag();
+
+ virtual void enterEvent(QEvent *);
+ virtual void leaveEvent(QEvent *);
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ virtual void dragLeaveEvent(QDragLeaveEvent *);
+ virtual void dropEvent(QDropEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void resizeEvent(QResizeEvent*);
+ virtual void drawButton(QPainter *);
+ virtual void drawButtonLabel(QPainter *);
+
+ /**
+ * @return the preferred icon size.
+ */
+ virtual int preferredIconSize(int proposed_size = -1) const;
+
+ /**
+ * @return the preferred dimensions for the button
+ */
+ virtual int preferredDimension(int panelDim) const;
+
+ /**
+ * if the button represents a local file, it tells PanelButton
+ * what file that is and it starts to watch it. if the file is
+ * deleted, it is disabled and then checked for one second later
+ * to see if has returned (e.g. a reinstall occurred) by calling
+ * checkForBackingFile(). if that returns false, then the button
+ * is removed from kicker.
+ * TODO: implement a heuristic that checks back in intervals for
+ * the reappearance of the file and returns the button to the panel
+ */
+ virtual bool checkForBackingFile();
+
+ /**
+ * Set the file backing this button (See @ref checkForBackingFile()),
+ * you shouldn't need to use this, currently it's only used in [url/service]button
+ */
+ void backedByFile(const QString& localFilePath);
+
+ /**
+ * Sets the button's arrow direction.
+ * @param dir the arrow direction
+ */
+ void setArrowDirection(KPanelExtension::Position dir);
+
+ /**
+ * Loads the tiles for the button
+ */
+ void loadTiles();
+
+ /**
+ * Loads the icons for the button
+ */
+ void loadIcons();
+
+ /**
+ * (Re)Calculate icon sizes and return true if they have changed.
+ */
+ bool calculateIconSize();
+
+ bool m_valid;
+ QPixmap m_icon;
+
+protected slots:
+ /**
+ * Called from KApplication when global icon settings have changed.
+ * @param group the new group
+ */
+ void updateIcon(int group);
+
+ /**
+ * Called from KApplication when global settings have changed.
+ * @param category the settings category, see KApplication::SettingsCategory
+ */
+ void updateSettings(int category);
+
+ /**
+ * Used for backedByFile, to check if the file backing this button
+ * has been deleted.
+ * @param path path to backing file
+ */
+ void checkForDeletion(const QString& path);
+
+ /**
+ * Called to prepare the button for removal from the Kicker
+ */
+ void scheduleForRemoval();
+
+private:
+ QPoint m_lastLeftMouseButtonPress;
+ bool m_isLeftMouseButtonDown;
+ bool m_drawArrow;
+ bool m_highlight;
+ bool m_changeCursorOverItem;
+ bool m_hasAcceptedDrag;
+ QColor m_textColor;
+ QColor m_tileColor;
+ QString m_buttonText;
+ QString m_tile;
+ QString m_title;
+ QString m_iconName;
+ QString m_backingFile;
+ QPixmap m_up;
+ QPixmap m_down;
+ QPixmap m_iconh; // hover
+ QPixmap m_iconz; // mouse over
+ KPanelExtension::Position m_arrowDirection;
+ KPanelApplet::Direction m_popupDirection;
+ Orientation m_orientation;
+ int m_size;
+ double m_fontPercent;
+ static KShadowEngine* s_textShadowEngine;
+
+ class PanelPopupPrivate;
+ PanelPopupPrivate* d;
+};
+
+/**
+ * Base class for panelbuttons which popup a menu
+ */
+class KDE_EXPORT PanelPopupButton : public PanelButton
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Create a panel button that pops up a menu.
+ * @param parent the parent widget
+ * @param name the widget's name
+ */
+ PanelPopupButton(QWidget *parent=0, const char *name=0);
+
+ /**
+ * Sets the button's popup menu.
+ * @param popup the menu to pop up
+ */
+ void setPopup(QPopupMenu *popup);
+
+ /**
+ * @return the button's popup menu
+ */
+ QPopupMenu *popup() const;
+
+ bool eventFilter(QObject *, QEvent *);
+ virtual void showMenu();
+
+protected:
+ /**
+ * Called each time the button is clicked and the popup
+ * is displayed. Reimplement for dynamic popup menus.
+ */
+ virtual void initPopup() {};
+
+ /**
+ * Called before drag occurs. Reimplement to do any
+ * necessary setup before the button is dragged.
+ */
+ virtual void triggerDrag();
+
+ /**
+ * Marks the menu as initialized.
+ */
+ void setInitialized(bool initialized);
+
+protected slots:
+ /**
+ * Connected to the button's pressed() signal, this is
+ * the code that actually displays the menu. Reimplement if
+ * you need to take care of any tasks before the popup is
+ * displayed (eg. KickerTip)
+ */
+ virtual void slotExecMenu();
+
+private slots:
+ void menuAboutToHide();
+
+private:
+ QPopupMenu *m_popup;
+ bool m_pressedDuringPopup;
+ bool m_initialized;
+
+ class PanelPopupButtonPrivate;
+ PanelPopupButtonPrivate* d;
+};
+
+#endif // __panelbutton_h__
diff --git a/kicker/libkicker/paneldrag.cpp b/kicker/libkicker/paneldrag.cpp
new file mode 100644
index 000000000..871ac1d96
--- /dev/null
+++ b/kicker/libkicker/paneldrag.cpp
@@ -0,0 +1,180 @@
+/*****************************************************************
+Copyright (c) 2004 Aaron J. Seigo <aseigo@kde.org>
+ 2004 Stephen Depooter <sbdep@woot.net>
+
+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 <sys/types.h>
+#include <unistd.h>
+
+#include <qbuffer.h>
+
+#include "paneldrag.h"
+
+#define PANELDRAG_BUFSIZE sizeof(BaseContainer*) + sizeof(pid_t)
+
+PanelDrag::PanelDrag(BaseContainer* container, QWidget* dragSource)
+ : QDragObject(dragSource, 0)
+{
+ pid_t source_pid = getpid();
+
+ a.resize(PANELDRAG_BUFSIZE);
+ memcpy(a.data(), &container, sizeof(BaseContainer*));
+ memcpy(a.data() + sizeof(BaseContainer*), &source_pid, sizeof(pid_t));
+}
+
+PanelDrag::~PanelDrag()
+{
+}
+
+bool PanelDrag::decode(const QMimeSource* e, BaseContainer** container)
+{
+ QByteArray a = e->encodedData("application/basecontainerptr");
+
+ if (a.size() != PANELDRAG_BUFSIZE)
+ {
+ return false;
+ }
+
+ pid_t target_pid = getpid();
+ pid_t source_pid;
+ memcpy(&source_pid, a.data() + sizeof(QObject*), sizeof(pid_t));
+
+ if (source_pid == target_pid)
+ {
+ memcpy(container, a.data(), sizeof(QObject*));
+ return true;
+ }
+
+ return false;
+}
+
+bool PanelDrag::canDecode(const QMimeSource *e)
+{
+ if (!e->provides("application/basecontainerptr"))
+ {
+ return false;
+ }
+
+ QByteArray a = e->encodedData("application/basecontainerptr");
+ if (a.size() != PANELDRAG_BUFSIZE)
+ {
+ return false;
+ }
+
+/* pid_t target_pid = getpid();
+ pid_t source_pid;
+ memcpy(&source_pid, a.data() + sizeof(void*), sizeof(pid_t));
+
+ if (source_pid != target_pid)
+ {
+ return true;
+ } */
+
+ return true;
+}
+
+QByteArray PanelDrag::encodedData(const char * mimeType) const
+{
+ if (QString("application/basecontainerptr") == mimeType &&
+ a.size() == PANELDRAG_BUFSIZE)
+ {
+ return a;
+ }
+
+ return QByteArray();
+}
+
+const char * PanelDrag::format(int i) const
+{
+ if (i == 0)
+ {
+ return "application/basecontainerptr";
+ }
+
+ return 0;
+}
+
+
+AppletInfoDrag::AppletInfoDrag(const AppletInfo& info, QWidget *dragSource)
+ : QDragObject(dragSource, 0)
+{
+ QBuffer buff(a);
+ buff.open(IO_WriteOnly);
+ QDataStream s(&buff);
+ s << info.desktopFile() << info.configFile() << info.type();
+}
+
+AppletInfoDrag::~AppletInfoDrag()
+{
+}
+
+const char * AppletInfoDrag::format(int i) const
+{
+ if (i == 0)
+ {
+ return "application/appletinfo";
+ }
+
+ return 0;
+}
+
+QByteArray AppletInfoDrag::encodedData(const char* mimeType) const
+{
+ if (QString("application/appletinfo") == mimeType)
+ {
+ return a;
+ }
+
+ return QByteArray();
+}
+
+bool AppletInfoDrag::canDecode(const QMimeSource * e)
+{
+ if (!e->provides("application/appletinfo"))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool AppletInfoDrag::decode(const QMimeSource* e, AppletInfo& container)
+{
+ QByteArray a = e->encodedData("application/appletinfo");
+
+ if (a.isEmpty())
+ {
+ return false;
+ }
+
+ QBuffer buff(a);
+ buff.open(IO_ReadOnly);
+ QDataStream s(&buff);
+
+ QString desktopFile;
+ QString configFile;
+ int type;
+ s >> desktopFile >> configFile >> type;
+ AppletInfo info(desktopFile, configFile, (AppletInfo::AppletType)type);
+ container = info;
+ return true;
+}
+
diff --git a/kicker/libkicker/paneldrag.h b/kicker/libkicker/paneldrag.h
new file mode 100644
index 000000000..ba85ad375
--- /dev/null
+++ b/kicker/libkicker/paneldrag.h
@@ -0,0 +1,68 @@
+/*****************************************************************
+Copyright (c) 2004 Aaron J. Seigo <aseigo@kde.org>
+ 2004 Stephen Depooter <sbdep@woot.net>
+
+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 _paneldrag_h_
+#define _paneldrag_h_
+
+#include <qdragobject.h>
+
+#include <kdemacros.h>
+
+#include "appletinfo.h"
+
+class BaseContainer;
+
+class KDE_EXPORT PanelDrag : public QDragObject
+{
+ public:
+ PanelDrag(BaseContainer* container, QWidget *dragSource);
+ ~PanelDrag();
+
+ virtual const char * format(int i = 0) const;
+ virtual QByteArray encodedData(const char *) const;
+
+ static bool canDecode(const QMimeSource * e);
+ static bool decode(const QMimeSource* e, BaseContainer** container);
+
+ private:
+ QByteArray a;
+};
+
+class KDE_EXPORT AppletInfoDrag : public QDragObject
+{
+ public:
+ AppletInfoDrag(const AppletInfo& container, QWidget *dragSource);
+ ~AppletInfoDrag();
+
+ virtual const char * format(int i = 0) const;
+ virtual QByteArray encodedData(const char *) const;
+
+ static bool canDecode(const QMimeSource * e);
+ static bool decode(const QMimeSource* e, AppletInfo& container);
+
+ private:
+ QByteArray a;
+};
+
+#endif
+
diff --git a/kicker/libkicker/panner.cpp b/kicker/libkicker/panner.cpp
new file mode 100644
index 000000000..43dd67a41
--- /dev/null
+++ b/kicker/libkicker/panner.cpp
@@ -0,0 +1,396 @@
+/*****************************************************************
+
+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 <qlayout.h>
+#include <qtooltip.h>
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qstyle.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "simplebutton.h"
+#include "panner.h"
+#include "panner.moc"
+
+Panner::Panner( QWidget* parent, const char* name )
+ : QWidget( parent, name ),
+ _luSB(0),
+ _rdSB(0),
+ _cwidth(0), _cheight(0),
+ _cx(0), _cy(0)
+{
+ KGlobal::locale()->insertCatalogue("libkicker");
+ setBackgroundOrigin( AncestorOrigin );
+
+ _updateScrollButtonsTimer = new QTimer(this);
+ connect(_updateScrollButtonsTimer, SIGNAL(timeout()), this, SLOT(reallyUpdateScrollButtons()));
+
+ _clipper = new QWidget(this);
+ _clipper->setBackgroundOrigin(AncestorOrigin);
+ _clipper->installEventFilter( this );
+ _viewport = new QWidget(_clipper);
+ _viewport->setBackgroundOrigin(AncestorOrigin);
+
+ // layout
+ _layout = new QBoxLayout(this, QBoxLayout::LeftToRight);
+ _layout->addWidget(_clipper, 1);
+ setOrientation(Horizontal);
+}
+
+Panner::~Panner()
+{
+}
+
+void Panner::createScrollButtons()
+{
+ if (_luSB)
+ {
+ return;
+ }
+
+ // left/up scroll button
+ _luSB = new SimpleArrowButton(this);
+ _luSB->installEventFilter(this);
+ //_luSB->setAutoRepeat(true);
+ _luSB->setMinimumSize(12, 12);
+ _luSB->hide();
+ _layout->addWidget(_luSB);
+ connect(_luSB, SIGNAL(pressed()), SLOT(startScrollLeftUp()));
+ connect(_luSB, SIGNAL(released()), SLOT(stopScroll()));
+
+ // right/down scroll button
+ _rdSB = new SimpleArrowButton(this);
+ _rdSB->installEventFilter(this);
+ //_rdSB->setAutoRepeat(true);
+ _rdSB->setMinimumSize(12, 12);
+ _rdSB->hide();
+ _layout->addWidget(_rdSB);
+ connect(_rdSB, SIGNAL(pressed()), SLOT(startScrollRightDown()));
+ connect(_rdSB, SIGNAL(released()), SLOT(stopScroll()));
+
+ // set up the buttons
+ setupButtons();
+}
+
+void Panner::setupButtons()
+{
+ if (orientation() == Horizontal)
+ {
+ if (_luSB)
+ {
+ _luSB->setArrowType(Qt::LeftArrow);
+ _rdSB->setArrowType(Qt::RightArrow);
+ _luSB->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
+ _rdSB->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
+ QToolTip::add(_luSB, i18n("Scroll left"));
+ QToolTip::add(_rdSB, i18n("Scroll right"));
+ setMinimumSize(24, 0);
+ }
+ _layout->setDirection(QBoxLayout::LeftToRight);
+ }
+ else
+ {
+ if (_luSB)
+ {
+ _luSB->setArrowType(Qt::UpArrow);
+ _rdSB->setArrowType(Qt::DownArrow);
+ _luSB->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+ _rdSB->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+ QToolTip::add(_luSB, i18n("Scroll up"));
+ QToolTip::add(_rdSB, i18n("Scroll down"));
+ setMinimumSize(0, 24);
+ }
+ _layout->setDirection(QBoxLayout::TopToBottom);
+ }
+
+ if (isVisible())
+ {
+ // we need to manually redo the layout if we are visible
+ // otherwise let the toolkit decide when to do this
+ _layout->activate();
+ }
+}
+
+void Panner::setOrientation(Orientation o)
+{
+ _orient = o;
+ setupButtons();
+ reallyUpdateScrollButtons();
+}
+
+void Panner::resizeEvent( QResizeEvent* )
+{
+ //QScrollView::resizeEvent( e );
+ //updateScrollButtons();
+}
+
+void Panner::scrollRightDown()
+{
+ if(orientation() == Horizontal) // scroll right
+ scrollBy( _step, 0 );
+ else // scroll down
+ scrollBy( 0, _step );
+ if (_step < 64)
+ _step++;
+}
+
+void Panner::scrollLeftUp()
+{
+ if(orientation() == Horizontal) // scroll left
+ scrollBy( -_step, 0 );
+ else // scroll up
+ scrollBy( 0, -_step );
+ if (_step < 64)
+ _step++;
+}
+
+void Panner::startScrollRightDown()
+{
+ _scrollTimer = new QTimer(this);
+ connect(_scrollTimer, SIGNAL(timeout()), SLOT(scrollRightDown()));
+ _scrollTimer->start(50);
+ _step = 8;
+ scrollRightDown();
+}
+
+void Panner::startScrollLeftUp()
+{
+ _scrollTimer = new QTimer(this);
+ connect(_scrollTimer, SIGNAL(timeout()), SLOT(scrollLeftUp()));
+ _scrollTimer->start(50);
+ _step = 8;
+ scrollLeftUp();
+}
+
+void Panner::stopScroll()
+{
+ delete _scrollTimer;
+ _scrollTimer = 0;
+}
+
+void Panner::reallyUpdateScrollButtons()
+{
+ int delta = 0;
+
+ _updateScrollButtonsTimer->stop();
+
+ if (orientation() == Horizontal)
+ {
+ delta = contentsWidth() - width();
+ }
+ else
+ {
+ delta = contentsHeight() - height();
+ }
+
+ if (delta >= 1)
+ {
+ createScrollButtons();
+
+ // since the buttons may be visible but of the wrong size
+ // we need to do this every single time
+ _luSB->show();
+ _rdSB->show();
+ }
+ else if (_luSB && _luSB->isVisibleTo(this))
+ {
+ _luSB->hide();
+ _rdSB->hide();
+ }
+}
+
+void Panner::updateScrollButtons()
+{
+ _updateScrollButtonsTimer->start(200, true);
+}
+
+void Panner::setContentsPos(int x, int y)
+{
+ if (x < 0)
+ x = 0;
+ else if (x > (contentsWidth() - visibleWidth()))
+ x = contentsWidth() - visibleWidth();
+
+ if (y < 0)
+ y = 0;
+ else if (y > (contentsHeight() - visibleHeight()))
+ y = contentsHeight() - visibleHeight();
+
+ if (x == contentsX() && y == contentsY())
+ return;
+
+ _viewport->move(-x, -y);
+ emit contentsMoving(x, y);
+}
+
+void Panner::scrollBy(int dx, int dy)
+{
+ setContentsPos(contentsX() + dx, contentsY() + dy);
+}
+
+void Panner::resizeContents( int w, int h )
+{
+ _viewport->resize(w, h);
+ setContentsPos(contentsX(), contentsY());
+ updateScrollButtons();
+}
+
+QPoint Panner::contentsToViewport( const QPoint& p ) const
+{
+ return QPoint(p.x() - contentsX() - _clipper->x(), p.y() - contentsY() - _clipper->y());
+}
+
+QPoint Panner::viewportToContents( const QPoint& vp ) const
+{
+ return QPoint(vp.x() + contentsX() + _clipper->x(), vp.y() + contentsY() + _clipper->y());
+}
+
+void Panner::contentsToViewport( int x, int y, int& vx, int& vy ) const
+{
+ const QPoint v = contentsToViewport(QPoint(x,y));
+ vx = v.x();
+ vy = v.y();
+}
+
+void Panner::viewportToContents( int vx, int vy, int& x, int& y ) const
+{
+ const QPoint c = viewportToContents(QPoint(vx,vy));
+ x = c.x();
+ y = c.y();
+}
+
+void Panner::ensureVisible( int x, int y )
+{
+ ensureVisible(x, y, 50, 50);
+}
+
+void Panner::ensureVisible( int x, int y, int xmargin, int ymargin )
+{
+ int pw=visibleWidth();
+ int ph=visibleHeight();
+
+ int cx=-contentsX();
+ int cy=-contentsY();
+ int cw=contentsWidth();
+ int ch=contentsHeight();
+
+ if ( pw < xmargin*2 )
+ xmargin=pw/2;
+ if ( ph < ymargin*2 )
+ ymargin=ph/2;
+
+ if ( cw <= pw ) {
+ xmargin=0;
+ cx=0;
+ }
+ if ( ch <= ph ) {
+ ymargin=0;
+ cy=0;
+ }
+
+ if ( x < -cx+xmargin )
+ cx = -x+xmargin;
+ else if ( x >= -cx+pw-xmargin )
+ cx = -x+pw-xmargin;
+
+ if ( y < -cy+ymargin )
+ cy = -y+ymargin;
+ else if ( y >= -cy+ph-ymargin )
+ cy = -y+ph-ymargin;
+
+ if ( cx > 0 )
+ cx=0;
+ else if ( cx < pw-cw && cw>pw )
+ cx=pw-cw;
+
+ if ( cy > 0 )
+ cy=0;
+ else if ( cy < ph-ch && ch>ph )
+ cy=ph-ch;
+
+ setContentsPos( -cx, -cy );
+}
+
+bool Panner::eventFilter( QObject *obj, QEvent *e )
+{
+ if ( obj == _viewport || obj == _clipper )
+ {
+ switch ( e->type() )
+ {
+ case QEvent::Resize:
+ viewportResizeEvent((QResizeEvent *)e);
+ break;
+ case QEvent::MouseButtonPress:
+ viewportMousePressEvent( (QMouseEvent*)e );
+ if ( ((QMouseEvent*)e)->isAccepted() )
+ return true;
+ break;
+ case QEvent::MouseButtonRelease:
+ viewportMouseReleaseEvent( (QMouseEvent*)e );
+ if ( ((QMouseEvent*)e)->isAccepted() )
+ return true;
+ break;
+ case QEvent::MouseButtonDblClick:
+ viewportMouseDoubleClickEvent( (QMouseEvent*)e );
+ if ( ((QMouseEvent*)e)->isAccepted() )
+ return true;
+ break;
+ case QEvent::MouseMove:
+ viewportMouseMoveEvent( (QMouseEvent*)e );
+ if ( ((QMouseEvent*)e)->isAccepted() )
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return QWidget::eventFilter( obj, e ); // always continue with standard event processing
+}
+
+void Panner::viewportResizeEvent( QResizeEvent* )
+{
+}
+
+void Panner::viewportMousePressEvent( QMouseEvent* e)
+{
+ e->ignore();
+}
+
+void Panner::viewportMouseReleaseEvent( QMouseEvent* e )
+{
+ e->ignore();
+}
+
+void Panner::viewportMouseDoubleClickEvent( QMouseEvent* e )
+{
+ e->ignore();
+}
+
+void Panner::viewportMouseMoveEvent( QMouseEvent* e )
+{
+ e->ignore();
+}
diff --git a/kicker/libkicker/panner.h b/kicker/libkicker/panner.h
new file mode 100644
index 000000000..6657c9a76
--- /dev/null
+++ b/kicker/libkicker/panner.h
@@ -0,0 +1,115 @@
+/*****************************************************************
+
+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 __panner_h__
+#define __panner_h__
+
+#include <qwidget.h>
+
+#include "simplebutton.h"
+
+class QBoxLayout;
+class QTimer;
+
+class KDE_EXPORT Panner : public QWidget
+{
+ Q_OBJECT
+
+public:
+ Panner( QWidget* parent, const char* name = 0 );
+ ~Panner();
+
+ QSize minimumSizeHint() const { return QWidget::minimumSizeHint(); }
+
+ Qt::Orientation orientation() const { return _orient; }
+ virtual void setOrientation(Orientation orientation);
+
+ QWidget *viewport() const { return _viewport; }
+
+ QRect contentsRect() const { return QRect(0, 0, width(), height()); }
+
+ int contentsX() const { return _viewport ? -_viewport->x() : 0; }
+ int contentsY() const { return _viewport ? -_viewport->y() : 0; }
+ int contentsWidth() const { return _viewport ? _viewport->width() : 0; }
+ int contentsHeight() const { return _viewport ? _viewport->height() : 0; }
+ void setContentsPos(int x, int y);
+
+ int visibleWidth() const { return _clipper->width(); }
+ int visibleHeight() const { return _clipper->height(); }
+
+ void contentsToViewport( int x, int y, int& vx, int& vy ) const;
+ void viewportToContents( int vx, int vy, int& x, int& y ) const;
+ QPoint contentsToViewport( const QPoint& ) const;
+ QPoint viewportToContents( const QPoint& ) const;
+
+ void addChild(QWidget *child) { child->show(); }
+ void removeChild(QWidget *child) { child->hide(); }
+ int childX(QWidget *child) const { return child->x(); }
+ int childY(QWidget *child) const { return child->y(); }
+ void moveChild(QWidget *child, int x, int y) { child->move(x, y); }
+
+ void ensureVisible( int x, int y );
+ void ensureVisible( int x, int y, int xmargin, int ymargin );
+
+public slots:
+ virtual void resizeContents( int w, int h );
+ void startScrollRightDown();
+ void startScrollLeftUp();
+ void stopScroll();
+ void scrollRightDown();
+ void scrollLeftUp();
+ void reallyUpdateScrollButtons();
+ void scrollBy(int dx, int dy);
+
+signals:
+ void contentsMoving(int x, int y);
+
+protected:
+ virtual bool eventFilter( QObject *obj, QEvent *e );
+ virtual void resizeEvent(QResizeEvent *ev);
+ virtual void viewportResizeEvent( QResizeEvent* );
+ virtual void viewportMousePressEvent( QMouseEvent* );
+ virtual void viewportMouseReleaseEvent( QMouseEvent* );
+ virtual void viewportMouseDoubleClickEvent( QMouseEvent* );
+ virtual void viewportMouseMoveEvent( QMouseEvent* );
+
+private:
+ void setupButtons();
+ void createScrollButtons();
+ void updateScrollButtons();
+
+ Orientation _orient;
+ QBoxLayout *_layout;
+ SimpleArrowButton *_luSB; // Left Scroll Button
+ SimpleArrowButton *_rdSB; // Right Scroll Button
+ QTimer *_updateScrollButtonsTimer;
+ QTimer *_scrollTimer;
+
+ QWidget *_clipper;
+ QWidget *_viewport;
+ int _cwidth, _cheight;
+ int _cx, _cy;
+ int _step;
+};
+
+#endif
diff --git a/kicker/libkicker/simplebutton.cpp b/kicker/libkicker/simplebutton.cpp
new file mode 100644
index 000000000..223e71982
--- /dev/null
+++ b/kicker/libkicker/simplebutton.cpp
@@ -0,0 +1,258 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2004 Nadeem Hasan <nhasan@kde.org>
+ Copyright (C) 2004-2005 Aaron J. Seigo <aseigo@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "simplebutton.h"
+
+#include <qpainter.h>
+#include <qstyle.h>
+
+#include <kapplication.h>
+#include <kcursor.h>
+#include <kdialog.h>
+#include <kglobalsettings.h>
+#include <kiconeffect.h>
+#include <kicontheme.h>
+#include <kipc.h>
+#include <kstandarddirs.h>
+
+#define BUTTON_MARGIN KDialog::spacingHint()
+
+SimpleButton::SimpleButton(QWidget *parent, const char *name)
+ : QButton(parent, name),
+ m_highlight(false),
+ m_orientation(Qt::Horizontal)
+{
+ setBackgroundOrigin( AncestorOrigin );
+
+ connect( kapp, SIGNAL( settingsChanged( int ) ),
+ SLOT( slotSettingsChanged( int ) ) );
+ connect( kapp, SIGNAL( iconChanged( int ) ),
+ SLOT( slotIconChanged( int ) ) );
+
+ kapp->addKipcEventMask( KIPC::SettingsChanged );
+ kapp->addKipcEventMask( KIPC::IconChanged );
+
+ slotSettingsChanged( KApplication::SETTINGS_MOUSE );
+}
+
+void SimpleButton::setPixmap(const QPixmap &pix)
+{
+ QButton::setPixmap(pix);
+ generateIcons();
+ update();
+}
+
+void SimpleButton::setOrientation(Qt::Orientation orientation)
+{
+ m_orientation = orientation;
+ update();
+}
+
+QSize SimpleButton::sizeHint() const
+{
+ const QPixmap* pm = pixmap();
+
+ if (!pm)
+ return QButton::sizeHint();
+ else
+ return QSize(pm->width() + BUTTON_MARGIN, pm->height() + BUTTON_MARGIN);
+}
+
+QSize SimpleButton::minimumSizeHint() const
+{
+ const QPixmap* pm = pixmap();
+
+ if (!pm)
+ return QButton::minimumSizeHint();
+ else
+ return QSize(pm->width(), pm->height());
+}
+
+void SimpleButton::drawButton( QPainter *p )
+{
+ drawButtonLabel(p);
+}
+
+void SimpleButton::drawButtonLabel( QPainter *p )
+{
+ if (!pixmap())
+ {
+ return;
+ }
+
+ QPixmap pix = isEnabled() ? (m_highlight? m_activeIcon : m_normalIcon) : m_disabledIcon;
+
+ if (isOn() || isDown())
+ {
+ pix = pix.convertToImage().smoothScale(pix.width() - 2,
+ pix.height() - 2);
+ }
+
+ int h = height();
+ int w = width();
+ int ph = pix.height();
+ int pw = pix.width();
+ int margin = BUTTON_MARGIN;
+ QPoint origin(margin / 2, margin / 2);
+
+ if (ph < (h - margin))
+ {
+ origin.setY((h - ph) / 2);
+ }
+
+ if (pw < (w - margin))
+ {
+ origin.setX((w - pw) / 2);
+ }
+
+ p->drawPixmap(origin, pix);
+}
+
+void SimpleButton::generateIcons()
+{
+ if (!pixmap())
+ {
+ return;
+ }
+
+ QImage image = pixmap()->convertToImage();
+ KIconEffect effect;
+
+ m_normalIcon = effect.apply(image, KIcon::Panel, KIcon::DefaultState);
+ m_activeIcon = effect.apply(image, KIcon::Panel, KIcon::ActiveState);
+ m_disabledIcon = effect.apply(image, KIcon::Panel, KIcon::DisabledState);
+
+ updateGeometry();
+}
+
+void SimpleButton::slotSettingsChanged(int category)
+{
+ if (category != KApplication::SETTINGS_MOUSE)
+ {
+ return;
+ }
+
+ bool changeCursor = KGlobalSettings::changeCursorOverIcon();
+
+ if (changeCursor)
+ {
+ setCursor(KCursor::handCursor());
+ }
+ else
+ {
+ unsetCursor();
+ }
+}
+
+void SimpleButton::slotIconChanged( int group )
+{
+ if (group != KIcon::Panel)
+ {
+ return;
+ }
+
+ generateIcons();
+ update();
+}
+
+void SimpleButton::enterEvent( QEvent *e )
+{
+ m_highlight = true;
+
+ repaint( false );
+ QButton::enterEvent( e );
+}
+
+void SimpleButton::leaveEvent( QEvent *e )
+{
+ m_highlight = false;
+
+ repaint( false );
+ QButton::enterEvent( e );
+}
+
+void SimpleButton::resizeEvent( QResizeEvent * )
+{
+ generateIcons();
+}
+
+
+SimpleArrowButton::SimpleArrowButton(QWidget *parent, Qt::ArrowType arrow, const char *name)
+ : SimpleButton(parent, name)
+{
+ setBackgroundOrigin(AncestorOrigin);
+ _arrow = arrow;
+ _inside = false;
+}
+
+QSize SimpleArrowButton::sizeHint() const
+{
+ return QSize( 12, 12 );
+}
+
+void SimpleArrowButton::setArrowType(Qt::ArrowType a)
+{
+ if (_arrow != a)
+ {
+ _arrow = a;
+ update();
+ }
+}
+
+Qt::ArrowType SimpleArrowButton::arrowType() const
+{
+ return _arrow;
+}
+
+void SimpleArrowButton::drawButton( QPainter *p )
+{
+ QRect r(1, 1, width() - 2, height() - 2);
+
+ QStyle::PrimitiveElement pe = QStyle::PE_ArrowLeft;
+ switch (_arrow)
+ {
+ case Qt::LeftArrow: pe = QStyle::PE_ArrowLeft; break;
+ case Qt::RightArrow: pe = QStyle::PE_ArrowRight; break;
+ case Qt::UpArrow: pe = QStyle::PE_ArrowUp; break;
+ case Qt::DownArrow: pe = QStyle::PE_ArrowDown; break;
+ }
+
+ int flags = QStyle::Style_Default | QStyle::Style_Enabled;
+ if (isDown() || isOn()) flags |= QStyle::Style_Down;
+ style().drawPrimitive(pe, p, r, colorGroup(), flags);
+}
+
+void SimpleArrowButton::enterEvent( QEvent *e )
+{
+ _inside = true;
+ SimpleButton::enterEvent( e );
+ update();
+}
+
+void SimpleArrowButton::leaveEvent( QEvent *e )
+{
+ _inside = false;
+ SimpleButton::enterEvent( e );
+ update();
+}
+
+#include "simplebutton.moc"
+
+// vim:ts=4:sw=4:et
diff --git a/kicker/libkicker/simplebutton.h b/kicker/libkicker/simplebutton.h
new file mode 100644
index 000000000..5423dff6b
--- /dev/null
+++ b/kicker/libkicker/simplebutton.h
@@ -0,0 +1,89 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2004 Nadeem Hasan <nhasan@kde.org>
+ Copyright (C) 2004-2005 Aaron J. Seigo <aseigo@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SIMPLEBUTTON_H
+#define SIMPLEBUTTON_H
+
+#include <qbutton.h>
+#include <qpixmap.h>
+
+#include <kdemacros.h>
+
+class KDE_EXPORT SimpleButton : public QButton
+{
+ Q_OBJECT
+
+ public:
+ SimpleButton(QWidget *parent, const char *name = 0);
+ void setPixmap(const QPixmap &pix);
+ void setOrientation(Qt::Orientation orientaton);
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ protected:
+ void drawButton( QPainter *p );
+ void drawButtonLabel( QPainter *p );
+ void generateIcons();
+
+ void enterEvent( QEvent *e );
+ void leaveEvent( QEvent *e );
+ void resizeEvent( QResizeEvent *e );
+
+ protected slots:
+ virtual void slotSettingsChanged( int category );
+ virtual void slotIconChanged( int group );
+
+ private:
+ bool m_highlight;
+ QPixmap m_normalIcon;
+ QPixmap m_activeIcon;
+ QPixmap m_disabledIcon;
+ Qt::Orientation m_orientation;
+ class SimpleButtonPrivate;
+ SimpleButtonPrivate* d;
+};
+
+class KDE_EXPORT SimpleArrowButton: public SimpleButton
+{
+ Q_OBJECT
+
+ public:
+ SimpleArrowButton(QWidget *parent = 0, Qt::ArrowType arrow = Qt::UpArrow, const char *name = 0);
+ virtual ~SimpleArrowButton() {};
+ QSize sizeHint() const;
+
+ protected:
+ virtual void enterEvent( QEvent *e );
+ virtual void leaveEvent( QEvent *e );
+ virtual void drawButton(QPainter *p);
+ Qt::ArrowType arrowType() const;
+
+ public slots:
+ void setArrowType(Qt::ArrowType a);
+
+ private:
+ Qt::ArrowType _arrow;
+ bool _inside;
+};
+
+
+#endif // HIDEBUTTON_H
+
+// vim:ts=4:sw=4:et