--- taskbar/taskcontainer.cpp (revision 755866)
+++ taskbar/taskcontainer.cpp (revision 774644)
@@ -67,7 +67,11 @@ TaskContainer::TaskContainer(Task::Ptr t
discardNextMouseEvent(false),
aboutToActivate(false),
m_mouseOver(false),
- m_paintEventCompression(false)
+ animationTimer(0, "TaskContainer::animationTimer"),
+ dragSwitchTimer(0, "TaskContainer::dragSwitchTimer"),
+ attentionTimer(0, "TaskContainer::attentionTimer"),
+ m_paintEventCompression(false),
+ m_paintEventCompressionTimer(0, "TaskContainer::paintEventCompressionTimer")
{
init();
setAcceptDrops(true); // Always enabled to activate task during drag&drop.
@@ -95,7 +99,11 @@ TaskContainer::TaskContainer(Startup::Pt
discardNextMouseEvent(false),
aboutToActivate(false),
m_mouseOver(false),
- m_paintEventCompression(false)
+ animationTimer(0, "TaskContainer::animationTimer"),
+ dragSwitchTimer(0, "TaskContainer::dragSwitchTimer"),
+ attentionTimer(0, "TaskContainer::attentionTimer"),
+ m_paintEventCompression(false),
+ m_paintEventCompressionTimer(0, "TaskContainer::paintEventCompressionTimer")
{
init();
setEnabled(false);
--- taskbar/taskbar.cpp (revision 755866)
+++ taskbar/taskbar.cpp (revision 774644)
@@ -61,7 +61,8 @@ TaskBar::TaskBar( QWidget *parent, const
m_showIcon(false),
m_showOnlyIconified(false),
m_textShadowEngine(0),
- m_ignoreUpdates(false)
+ m_ignoreUpdates(false),
+ m_relayoutTimer(0, "TaskBar::m_relayoutTimer")
{
setBackgroundOrigin( AncestorOrigin );
--- configure.in.in (revision 0)
+++ configure.in.in (revision 774644)
@@ -0,0 +1,78 @@
+dnl Check for pkg-config
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+
+if test "$PKG_CONFIG" = "no"; then
+ AC_MSG_ERROR([
+This package requires pkg-config.
+])
+fi
+
+dnl Check for Glib-2.0
+# GLIB_CFLAGS: cflags for compiling glib dependant sources
+# GLIB_LIBADD: glib libraries (-l options)
+# GLIB_LDFLAGS: flags containing path to glib libraries (-L options)
+
+GLIB_PACKAGES="gmodule-2.0 gthread-2.0"
+GLIB_VERSION="1.3.3"
+AC_MSG_CHECKING(for GLib-2.0 (at least $GLIB_VERSION))
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.15 ; then
+ if $PKG_CONFIG --atleast-version $GLIB_VERSION $GLIB_PACKAGES >/dev/null 2>&1 ; then
+ GLIB_CFLAGS="`$PKG_CONFIG --cflags $GLIB_PACKAGES`"
+ GLIB_LIBADD="`$PKG_CONFIG --libs-only-l --libs-only-other $GLIB_PACKAGES`"
+ GLIB_LDFLAGS="`$PKG_CONFIG --libs-only-L $GLIB_PACKAGES`"
+ AC_MSG_RESULT(yes)
+ fi
+else
+ if $PKG_CONFIG --atleast-version $GLIB_VERSION $GLIB_PACKAGES >/dev/null 2>&1 ; then
+ GLIB_CFLAGS="`$PKG_CONFIG --cflags $GLIB_PACKAGES`"
+ GLIB_LIBADD="`$PKG_CONFIG --libs-only-l $GLIB_PACKAGES`"
+ GLIB_LDFLAGS="`$PKG_CONFIG --libs-only-L $GLIB_PACKAGES`"
+ AC_MSG_RESULT(yes)
+ AC_MSG_WARN([you may need to run make LDFLAGS=-pthread to compile arts])
+ fi
+fi
+
+if test -z "$GLIB_LIBADD"; then
+ AC_MSG_RESULT(not installed)
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kerry gmcop"
+fi
+
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBADD)
+AC_SUBST(GLIB_LDFLAGS)
+
+dnl Check for libbeagle 0.2.0
+# LIBBEAGLE_CFLAGS: cflags for compiling libbeagle dependant sources
+# LIBBEAGLE_LIBADD: libbeagle libraries (-l options)
+# LIBBEAGLE_LDFLAGS: flags containing path to libbeagle libraries (-L options)
+
+LIBBEAGLE_PACKAGES="libbeagle-0.0"
+LIBBEAGLE_VERSION="0.2.4"
+AC_MSG_CHECKING(for libbeagle-0.2.4 (at least $LIBBEAGLE_VERSION))
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.15 ; then
+ if $PKG_CONFIG --atleast-version $LIBBEAGLE_VERSION $LIBBEAGLE_PACKAGES >/dev/null 2>&1 ; then
+ LIBBEAGLE_CFLAGS="`$PKG_CONFIG --cflags $LIBBEAGLE_PACKAGES`"
+ LIBBEAGLE_LIBADD="`$PKG_CONFIG --libs-only-l --libs-only-other $LIBBEAGLE_PACKAGES`"
+ LIBBEAGLE_LDFLAGS="`$PKG_CONFIG --libs-only-L $LIBBEAGLE_PACKAGES`"
+ AC_MSG_RESULT(yes)
+ fi
+else
+ if $PKG_CONFIG --atleast-version $LIBBEAGLE_VERSION $LIBBEAGLE_PACKAGES >/dev/null 2>&1 ; then
+ LIBBEAGLE_CFLAGS="`$PKG_CONFIG --cflags $LIBBEAGLE_PACKAGES`"
+ LIBBEAGLE_LIBADD="`$PKG_CONFIG --libs-only-l $LIBBEAGLE_PACKAGES`"
+ LIBBEAGLE_LDFLAGS="`$PKG_CONFIG --libs-only-L $LIBBEAGLE_PACKAGES`"
+ AC_MSG_RESULT(yes)
+ AC_MSG_WARN([you may need to run make LDFLAGS=-pthread to compile arts])
+ fi
+fi
+
+if test -z "$LIBBEAGLE_LIBADD"; then
+ AC_MSG_RESULT(not installed)
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kerry gmcop"
+fi
+
+AC_SUBST(LIBBEAGLE_CFLAGS)
+AC_SUBST(LIBBEAGLE_LIBADD)
+AC_SUBST(LIBBEAGLE_LDFLAGS)
--- libkicker/panelbutton.h (revision 755866)
+++ libkicker/panelbutton.h (revision 774644)
@@ -254,9 +254,11 @@ public slots:
/**
* Sets the direction to pop up the contents of the button.
*/
- void setPopupDirection(KPanelApplet::Direction d);
+ virtual void setPopupDirection(KPanelApplet::Direction d);
protected:
+
+ void setIconAlignment(AlignmentFlags align);
/**
* 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
@@ -391,6 +393,7 @@ private:
QPixmap m_iconz; // mouse over
KPanelExtension::Position m_arrowDirection;
KPanelApplet::Direction m_popupDirection;
+ AlignmentFlags m_iconAlignment;
Orientation m_orientation;
int m_size;
double m_fontPercent;
@@ -419,12 +422,12 @@ public:
* Sets the button's popup menu.
* @param popup the menu to pop up
*/
- void setPopup(QPopupMenu *popup);
+ void setPopup(QWidget *popup);
/**
* @return the button's popup menu
*/
- QPopupMenu *popup() const;
+ QWidget *popup() const;
bool eventFilter(QObject *, QEvent *);
virtual void showMenu();
@@ -459,8 +462,8 @@ protected slots:
private slots:
void menuAboutToHide();
-private:
- QPopupMenu *m_popup;
+protected:
+ QWidget *m_popup;
bool m_pressedDuringPopup;
bool m_initialized;
--- libkicker/kickerSettings.kcfg (revision 755866)
+++ libkicker/kickerSettings.kcfg (revision 774644)
@@ -98,6 +98,70 @@
+
+
+ false
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ 0
+
+
+
+
+ 0
+
+
+
+
+ 0
+ -100
+ 100
+
+
+
+
+ false
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ LabelAndIcon
+
+
+
+
+
+ true
+
+
+
@@ -172,6 +236,19 @@
false
+
+
+
+
+
+
+ false
+
+
+
+
+
+
@@ -337,6 +414,29 @@
+
+
+
+
+
+
+
+ 50
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
--- libkicker/kickertip.cpp (revision 755866)
+++ libkicker/kickertip.cpp (revision 774644)
@@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE
// putting this #include higher results in compile errors
#include
+#include
static const int DEFAULT_FRAMES_PER_SECOND = 30;
@@ -71,14 +72,16 @@ KickerTip::KickerTip(QWidget * parent)
m_dissolveDelta(-1),
m_direction(KPanelApplet::Up),
m_dirty(false),
- m_toolTipsEnabled(KickerSettings::showToolTips()),
- m_tippingFor(0)
+ m_tippingFor(0),
+ m_timer(0, "KickerTip::m_timer"),
+ m_frameTimer(0, "KickerTip::m_frameTimer")
{
setFocusPolicy(NoFocus);
setBackgroundMode(NoBackground);
resize(0, 0);
hide();
connect(&m_frameTimer, SIGNAL(timeout()), SLOT(internalUpdate()));
+ connect(kapp, SIGNAL(settingsChanged(SettingsCategory)), SLOT(slotSettingsChanged()));
}
KickerTip::~KickerTip()
@@ -87,6 +90,11 @@ KickerTip::~KickerTip()
delete m_mimeFactory;
}
+void KickerTip::slotSettingsChanged()
+{
+ QToolTip::setGloballyEnabled(KickerSettings::showToolTips());
+}
+
void KickerTip::display()
{
if (!tippingEnabled())
@@ -192,9 +200,7 @@ void KickerTip::paintEvent(QPaintEvent *
void KickerTip::mousePressEvent(QMouseEvent * /*e*/)
{
- QToolTip::setGloballyEnabled(m_toolTipsEnabled);
m_timer.stop();
- m_frameTimer.stop();
hide();
}
@@ -395,8 +401,11 @@ void KickerTip::enableTipping(bool tip)
m_tippingEnabled--;
}
+ assert(m_tippingEnabled >= -1);
+
if (m_tippingEnabled < 1 && m_self)
{
+ m_self->m_timer.stop();
m_self->hide();
}
}
@@ -411,6 +420,8 @@ void KickerTip::hide()
m_tippingFor = 0;
m_frameTimer.stop();
QWidget::hide();
+
+ QToolTip::setGloballyEnabled(KickerSettings::showToolTips());
}
bool KickerTip::eventFilter(QObject *object, QEvent *event)
@@ -439,7 +450,6 @@ bool KickerTip::eventFilter(QObject *obj
!qApp->activePopupWidget() &&
!isTippingFor(widget))
{
- m_toolTipsEnabled = QToolTip::isGloballyEnabled();
QToolTip::setGloballyEnabled(false);
tipFor(widget);
@@ -461,8 +471,6 @@ bool KickerTip::eventFilter(QObject *obj
}
break;
case QEvent::Leave:
- QToolTip::setGloballyEnabled(m_toolTipsEnabled);
-
m_timer.stop();
if (isTippingFor(widget) && isVisible())
@@ -475,9 +483,7 @@ bool KickerTip::eventFilter(QObject *obj
tipFor(0);
break;
case QEvent::MouseButtonPress:
- QToolTip::setGloballyEnabled(m_toolTipsEnabled);
m_timer.stop();
- m_frameTimer.stop();
hide();
default:
break;
--- libkicker/kickertip.h (revision 755866)
+++ libkicker/kickertip.h (revision 774644)
@@ -92,6 +92,7 @@ protected slots:
void tipperDestroyed(QObject* o);
void internalUpdate();
void display();
+ void slotSettingsChanged();
private:
QBitmap m_mask;
@@ -108,7 +109,6 @@ private:
QTimer m_timer;
QTimer m_frameTimer;
bool m_dirty;
- bool m_toolTipsEnabled;
const QWidget* m_tippingFor;
--- libkicker/panelbutton.cpp (revision 755866)
+++ libkicker/panelbutton.cpp (revision 774644)
@@ -42,6 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE
#include
#include
#include
+#include
#include "global.h"
@@ -65,6 +66,7 @@ PanelButton::PanelButton( QWidget* paren
m_hasAcceptedDrag(false),
m_arrowDirection(KPanelExtension::Bottom),
m_popupDirection(KPanelApplet::Up),
+ m_iconAlignment(AlignCenter),
m_orientation(Horizontal),
m_size((KIcon::StdSizes)-1),
m_fontPercent(0.40)
@@ -184,6 +186,12 @@ void PanelButton::setPopupDirection(KPan
setArrowDirection(KickerLib::directionToPopupPosition(d));
}
+void PanelButton::setIconAlignment(AlignmentFlags align)
+{
+ m_iconAlignment = align;
+ update();
+}
+
void PanelButton::setOrientation(Orientation o)
{
m_orientation = o;
@@ -298,7 +306,9 @@ int PanelButton::widthForHeight(int heig
int PanelButton::heightForWidth(int width) const
{
- return preferredDimension(width);
+ int rc=preferredDimension(width);
+
+ return rc;
}
const QPixmap& PanelButton::labelIcon() const
@@ -550,11 +560,16 @@ void PanelButton::drawButtonLabel(QPaint
icon.height() - 2);
}
+ int y = 0;
+ if (m_iconAlignment & AlignVCenter)
+ y = (height() - icon.height()) / 2;
+ else if (m_iconAlignment & AlignBottom)
+ y = (height() - icon.height());
+
if (!m_buttonText.isEmpty() && orientation() == Horizontal)
{
int h = height();
int w = width();
- int y = (h - icon.height())/2;
p->save();
QFont f = font();
@@ -623,8 +638,11 @@ void PanelButton::drawButtonLabel(QPaint
}
else if (!icon.isNull())
{
- int y = (height() - icon.height()) / 2;
- int x = (width() - icon.width()) / 2;
+ int x = 0;
+ if (m_iconAlignment & AlignHCenter)
+ x = (width() - icon.width()) / 2;
+ else if (m_iconAlignment & AlignRight)
+ x = (width() - icon.width());
p->drawPixmap(x, y, icon);
}
@@ -786,7 +804,19 @@ void PanelButton::loadIcons()
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 (nm=="kmenu-suse")
+ {
+ QString pth = locate( "data", "kicker/pics/kmenu_basic.mng" );
+ if (!pth.isEmpty())
+ {
+ m_icon = QImage(pth);
+ m_iconh = QPixmap(m_icon);
+ m_iconz = QPixmap(m_icon);
+ return;
+ }
+ }
+ else
+ m_icon = ldr->loadIcon(nm, KIcon::Panel, m_size, defaultState, 0L, true);
if (m_icon.isNull())
{
@@ -851,7 +881,7 @@ PanelPopupButton::PanelPopupButton(QWidg
connect(this, SIGNAL(pressed()), SLOT(slotExecMenu()));
}
-void PanelPopupButton::setPopup(QPopupMenu *popup)
+void PanelPopupButton::setPopup(QWidget *popup)
{
if (m_popup)
{
@@ -869,7 +899,7 @@ void PanelPopupButton::setPopup(QPopupMe
}
}
-QPopupMenu *PanelPopupButton::popup() const
+QWidget *PanelPopupButton::popup() const
{
return m_popup;
}
@@ -948,7 +978,9 @@ void PanelPopupButton::slotExecMenu()
}
m_popup->adjustSize();
- m_popup->exec(KickerLib::popupPosition(popupDirection(), m_popup, this));
+ if(dynamic_cast(m_popup))
+ static_cast(m_popup)->exec(KickerLib::popupPosition(popupDirection(), m_popup, this));
+ // else.. hmm. some derived class has to fix it.
}
void PanelPopupButton::menuAboutToHide()
@@ -958,8 +990,10 @@ void PanelPopupButton::menuAboutToHide()
return;
}
- setDown(false);
- KickerTip::enableTipping(true);
+ if (isDown()) {
+ setDown(false);
+ KickerTip::enableTipping(true);
+ }
}
void PanelPopupButton::triggerDrag()
@@ -977,3 +1011,5 @@ void PanelPopupButton::setInitialized(bo
m_initialized = initialized;
}
+
+
--- extensions/kasbar/kasbar.cpp (revision 755866)
+++ extensions/kasbar/kasbar.cpp (revision 774644)
@@ -719,7 +719,7 @@ void KasBar::addTestItems()
i->setText( "Animated" );
i->setIcon( KGlobal::iconLoader()->loadIcon( "icons", KIcon::NoGroup, KIcon::SizeMedium ) );
i->setAnimation( resources()->startupAnimation() );
- QTimer *aniTimer = new QTimer( i );
+ QTimer *aniTimer = new QTimer( i, "aniTimer" );
connect( aniTimer, SIGNAL( timeout() ), i, SLOT( advanceAnimation() ) );
aniTimer->start( 100 );
i->setShowAnimation( true );
--- extensions/kasbar/kasclockitem.cpp (revision 755866)
+++ extensions/kasbar/kasclockitem.cpp (revision 774644)
@@ -38,7 +38,7 @@ KasClockItem::KasClockItem( KasBar *pare
{
setCustomPopup( true );
- QTimer *t = new QTimer( this );
+ QTimer *t = new QTimer( this, "t" );
connect( t, SIGNAL( timeout() ), SLOT( updateTime() ) );
t->start( 1000 );
--- extensions/kasbar/kasstartupitem.cpp (revision 755866)
+++ extensions/kasbar/kasstartupitem.cpp (revision 774644)
@@ -79,7 +79,7 @@ KasStartupItem::KasStartupItem( KasBar *
setShowFrame( false );
setAnimation( resources()->startupAnimation() );
- aniTimer = new QTimer( this );
+ aniTimer = new QTimer( this, "aniTimer" );
connect( aniTimer, SIGNAL( timeout() ), SLOT( aniTimerFired() ) );
aniTimer->start( 100 );
}
--- extensions/kasbar/kasloaditem.cpp (revision 755866)
+++ extensions/kasbar/kasloaditem.cpp (revision 774644)
@@ -33,7 +33,7 @@
KasLoadItem::KasLoadItem( KasBar *parent )
: KasItem( parent )
{
- QTimer *t = new QTimer( this );
+ QTimer *t = new QTimer( this, "KasLoadItem::t" );
connect( t, SIGNAL( timeout() ), SLOT( updateDisplay() ) );
t->start( 1000 );
updateDisplay();
--- kicker/plugins/beaglesearch.cpp (revision 0)
+++ kicker/plugins/beaglesearch.cpp (revision 774644)
@@ -0,0 +1,362 @@
+/*****************************************************************
+
+ Copyright (c) 2006 Debajyoti Bera
+
+ 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 "beaglesearch.h"
+
+#include
+#include
+#include
+#include
+#include
+
+void beagle_init ()
+{
+ g_type_init ();
+}
+
+// ---------------- Hit ---------------------------
+
+Hit::Hit (BeagleHit *_hit) : processed (false)
+{
+ hit = beagle_hit_ref (_hit);
+}
+
+Hit::~Hit ()
+{
+ beagle_hit_unref (hit);
+ if (! processed)
+ return;
+ QDictIterator it (property_map);
+ for( ; it.current(); ++it )
+ ((QStringList *)it.current())->clear ();
+
+}
+
+void Hit::processProperties ()
+{
+ processed = true;
+ GSList *prop_list = beagle_hit_get_all_properties (hit);
+ GSList *it;
+ property_map.setAutoDelete (true);
+ for (it = prop_list; it; it = it->next) {
+ BeagleProperty *property = (BeagleProperty *) it->data;
+ QString key = QString::fromUtf8 (beagle_property_get_key (property));
+ if (! property_map [key])
+ property_map.insert (key, new QStringList ());
+ property_map [key]->append (QString::fromUtf8 (beagle_property_get_value (property)));
+ }
+ g_slist_free (prop_list);
+}
+
+const QString Hit::operator[] (QString prop_name)
+{
+ if (! processed)
+ processProperties ();
+
+ QStringList *prop_list = property_map [prop_name];
+ if (! prop_list)
+ return QString::null;
+ if (prop_list->count () != 1)
+ return QString::null;
+ return (QString)prop_list->first ();
+}
+
+// ---------------- BeagleSearch ------------------
+
+BeagleSearchResult::BeagleSearchResult(int client_id)
+ : client_id (client_id), total (0)
+{
+ hitlist = new QPtrList;
+ hitlist->setAutoDelete (true);
+}
+
+
+BeagleSearchResult::~BeagleSearchResult()
+{
+ // everything is set to autodelete
+}
+
+void BeagleSearchResult::addHit(BeagleHit *_hit)
+{
+ Hit *hit = new Hit (_hit);
+ hitlist->prepend (hit);
+}
+
+const QPtrList *BeagleSearchResult::getHits () const
+{
+ return hitlist;
+}
+
+
+static int total_hits;
+
+static void print_feed_item_hit (BeagleHit *hit)
+{
+ const char *text;
+
+ if (beagle_hit_get_one_property (hit, "dc:title", &text))
+ g_print ("Blog: %s\n", text);
+}
+
+static void print_file_hit (BeagleHit *hit)
+{
+ g_print ("File: %s, (%s)\n", beagle_hit_get_uri (hit), beagle_hit_get_mime_type (hit));
+}
+
+static void print_other_hit (BeagleHit *hit)
+{
+ const char *text;
+
+ g_print ("%s (%s)", beagle_hit_get_uri (hit),
+ beagle_hit_get_source (hit));
+ if (beagle_hit_get_one_property (hit, "dc:title", &text))
+ g_print ("title = %s\n", text);
+}
+
+static void print_hit (BeagleHit *hit)
+{
+ if (strcmp (beagle_hit_get_type (hit), "FeedItem") == 0) {
+ print_feed_item_hit (hit);
+ }
+ else if (strcmp (beagle_hit_get_type (hit), "File") == 0) {
+ print_file_hit (hit);
+ } else {
+ print_other_hit (hit);
+ }
+}
+
+// ---------------- BeagleSearchClient ------------------
+
+void BeagleSearchClient::run ()
+{
+ kdDebug () << "Starting query ..." << endl;
+
+ QTime query_timer;
+ query_timer.start ();
+
+ g_signal_connect (query, "hits-added",
+ G_CALLBACK (hitsAddedSlot),
+ this);
+ g_signal_connect (query, "finished",
+ G_CALLBACK (finishedSlot),
+ this);
+ beagle_client_send_request_async (client,
+ BEAGLE_REQUEST (query),
+ NULL);
+ g_main_loop_run (main_loop);
+ kdDebug () << "Finished query ..." << endl;
+
+ QCustomEvent *ev;
+ if (collate_results) {
+ result->query_msec = query_timer.elapsed ();
+
+ ev = new QCustomEvent (RESULTFOUND, result);
+ QApplication::postEvent (object, ev);
+ }
+
+ ev = new QCustomEvent (KILLME, this);
+ QApplication::postEvent (object, ev);
+
+}
+
+void BeagleSearchClient::stopClient ()
+{
+ if (finished ())
+ return; // duh!
+ kdDebug () << "Query thread " << id << " not yet finished ..." << endl;
+ // get ready for suicide
+ client_mutex->lock ();
+ kill_me = true;
+ g_signal_handlers_disconnect_by_func (
+ query,
+ (void *)hitsAddedSlot,
+ this);
+ g_signal_handlers_disconnect_by_func (
+ query,
+ (void *)finishedSlot,
+ this);
+ g_main_loop_quit (main_loop);
+ client_mutex->unlock ();
+}
+
+void BeagleSearchClient::hitsAddedSlot (BeagleQuery *query,
+ BeagleHitsAddedResponse *response,
+ BeagleSearchClient *bsclient)
+{
+ GSList *hits, *l;
+ gint i;
+ gint nr_hits;
+
+ // check if we are supposed to be killed
+ bsclient->client_mutex->lock ();
+ if (bsclient->kill_me) {
+ kdDebug () << "Suicide time before processing" << endl;
+ bsclient->client_mutex->unlock ();
+ return;
+ }
+ bsclient->client_mutex->unlock ();
+
+ hits = beagle_hits_added_response_get_hits (response);
+
+ nr_hits = g_slist_length (hits);
+ total_hits += nr_hits;
+ g_print ("Found hits (%d) at %ld:\n", nr_hits, time (NULL));
+
+ BeagleSearchResult *search_result;
+ if (! bsclient->collate_results)
+ search_result = new BeagleSearchResult (bsclient->id);
+ else
+ search_result = bsclient->result;
+ search_result->total += nr_hits;
+
+ for (l = hits, i = 1; l; l = l->next, ++i) {
+ //g_print ("[%d] ", i);
+ //print_hit (BEAGLE_HIT (l->data));
+ //g_print ("\n");
+
+ search_result->addHit(BEAGLE_HIT (l->data));//hit);
+ }
+ g_print ("[%ld] hits adding finished \n", time (NULL));
+
+ // check if we are supposed to be killed
+ bsclient->client_mutex->lock ();
+ if (bsclient->kill_me) {
+ kdDebug () << "Suicide time before sending ..." << endl;
+ bsclient->client_mutex->unlock ();
+ if (! bsclient->collate_results)
+ delete search_result;
+ return;
+ }
+ bsclient->client_mutex->unlock ();
+
+ // time to send back results, if user asked so
+ if (bsclient->collate_results)
+ return;
+ QCustomEvent *ev = new QCustomEvent (RESULTFOUND, search_result);
+ g_print ("[%ld] event notified \n", time (NULL));
+ QApplication::postEvent (bsclient->object, ev);
+}
+
+void BeagleSearchClient::finishedSlot (BeagleQuery *query,
+ BeagleFinishedResponse *response,
+ BeagleSearchClient *bsclient)
+{
+ // check if we are supposed to be killed
+ bsclient->client_mutex->lock ();
+ bool should_kill = bsclient->kill_me;
+ QObject* receiver = bsclient->object;
+ bsclient->client_mutex->unlock ();
+
+ if (should_kill)
+ return;
+
+ g_main_loop_quit (bsclient->main_loop);
+
+ if (bsclient->collate_results)
+ return; // if we are collating, everything will be send from a central place
+ if (receiver) {
+ QCustomEvent *ev = new QCustomEvent (SEARCHOVER, bsclient);
+ g_print ("[%ld] query finish notified \n", time (NULL));
+ QApplication::postEvent (receiver, ev);
+ }
+}
+
+// ----------------- BeagleUtil -------------------
+
+BeagleQuery *
+BeagleUtil::createQueryFromString (QString query_str,
+ QStringList &sources_menu,
+ QStringList &types_menu,
+ int max_hits_per_source)
+{
+ BeagleQuery *beagle_query = beagle_query_new ();
+ beagle_query_set_max_hits (beagle_query, max_hits_per_source); // this is per source!
+
+ kdDebug () << "Creating query from \"" << query_str << "\"" << endl;
+ for ( QStringList::Iterator it = sources_menu.begin(); it != sources_menu.end(); ++it )
+ beagle_query_add_source (beagle_query, g_strdup ((*it).utf8 ()));
+
+ for ( QStringList::Iterator it = types_menu.begin(); it != types_menu.end(); ++it )
+ beagle_query_add_hit_type (beagle_query, g_strdup ((*it).utf8 ()));
+
+ QStringList query_terms;
+ QString start_date, end_date;
+ QStringList words = QStringList::split (' ', query_str, false);
+ for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) {
+ QStringList key_value_pair = QStringList::split ('=', *it, false);
+ if (key_value_pair.count () == 1)
+ query_terms += *it;
+ else if (key_value_pair.count () == 2) {
+ QString key = key_value_pair [0].lower ();
+ QString value = key_value_pair [1];
+ if (key == "mime")
+ beagle_query_add_mime_type (beagle_query, g_strdup (value.utf8 ()));
+ else if (key == "type")
+ beagle_query_add_hit_type (beagle_query, g_strdup (value.utf8 ()));
+ else if (key == "source")
+ beagle_query_add_source (beagle_query, g_strdup (value.utf8 ()));
+ else if (key == "start")
+ start_date = value;
+ else if (key == "end")
+ end_date = value;
+ else
+ query_terms += *it;
+ } else
+ query_terms += *it;
+ }
+
+ beagle_query_add_text (beagle_query, g_strdup (query_terms.join (" ").utf8 ()));
+ kdDebug () << "Adding query text:" << query_terms.join (" ").utf8 () << endl;
+
+ if (start_date.isNull () && end_date.isNull ())
+ return beagle_query;
+
+ //kdDebug () << "Handling dates ..." << endl;
+ BeagleQueryPartDate * date_part = beagle_query_part_date_new ();
+ if (! start_date.isNull ())
+ beagle_query_part_date_set_start_date (date_part, timestringToBeagleTimestamp (start_date));
+ if (! end_date.isNull ())
+ beagle_query_part_date_set_end_date (date_part, timestringToBeagleTimestamp (end_date));
+ beagle_query_add_part (beagle_query, BEAGLE_QUERY_PART (date_part));
+
+ return beagle_query;
+}
+
+// timestring format allowed YYYYmmDD
+BeagleTimestamp *
+BeagleUtil::timestringToBeagleTimestamp(QString timestring)
+{
+ //kdDebug () << "datetime string:" << timestring << endl;
+ // FIXME: error check timestring format
+ if (timestring.isNull () || timestring.stripWhiteSpace () == "" || timestring.length() != 8 )
+ return beagle_timestamp_new_from_unix_time (QDateTime::currentDateTime ().toTime_t ());
+ //QDateTime dt = QDateTime::fromString (timestring, Qt::ISODate);
+ struct tm tm_time;
+ time_t timet_time;
+ time (&timet_time);
+ localtime_r (&timet_time, &tm_time);
+ strptime (timestring.ascii(), "%Y%m%d", &tm_time);
+ tm_time.tm_sec = tm_time.tm_min = tm_time.tm_hour = 0;
+ //kdDebug() << asctime (&tm_time) << endl;
+ timet_time = mktime (&tm_time);
+ return beagle_timestamp_new_from_unix_time (timet_time);
+}
+
--- kicker/plugins/kickoff-beagle-plugin.cpp (revision 0)
+++ kicker/plugins/kickoff-beagle-plugin.cpp (revision 774644)
@@ -0,0 +1,499 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Stephan Binner *
+ * Copyright (c) 2006 Debajyoti Bera *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kickoff-beagle-plugin.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+QString dc_identifier = "dc:identifier";
+QString dc_title = "dc:title";
+QString parent_dc_title = "parent:dc:title";
+QString exactfilename = "beagle:ExactFilename";
+QString fixme_name = "fixme:Name";
+QString beagle_filename = "beagle:Filename";
+QString fixme_attachment_title = "fixme:attachment_title";
+QString fixme_hasattachments = "fixme:hasAttachments";
+QString parent_prefix = "parent:";
+QString fixme_folder = "fixme:folder";
+QString fixme_categories = "fixme:Categories";
+QString fixme_comment = "fixme:Comment";
+QString fixme_width = "fixme:width";
+QString fixme_height = "fixme:height";
+QString fixme_from_address = "fixme:from_address";
+QString fixme_artist = "fixme:artist";
+QString fixme_album = "fixme:album";
+QString dc_source = "dc:source";
+QString dc_publisher = "dc:publisher";
+QString digikam_tag = "digikam:Tag";
+QString fixme_speakingto = "fixme:speakingto";
+QString fixme_starttime = "fixme:starttime";
+QString comma_string = ",";
+QString vCard_FN = "vCard:FN";
+QString vCard_PREFEMAIL = "vCard:PREFEMAIL";
+QString fixme_uid = "fixme:uid";
+
+static CATEGORY getHitCategory (Hit *hit)
+{
+ QString hittype = hit->getType();
+ QString hitsource = hit->getSource();
+
+ // if hit source is None, dont handle it. Might be anthrax-envelope :)
+ if (hitsource.isNull())
+ return OTHER;
+
+ if (hitsource == "documentation")
+ return DOCS;
+
+ if (hittype == "IMLog")
+ return CHATS;
+
+ // sure shots
+ if (hittype == "FeedItem")
+ return FEEDS;
+ if (hittype == "WebHistory")
+ return WEBHIST;
+ if (hittype == "MailMessage")
+ return MAILS;
+ if (hittype == "Note")
+ return NOTES;
+
+ // check for applications
+ if (hittype == "File" && (*hit) ["beagle:FilenameExtension"] == ".desktop")
+ return APPS;
+
+ // check for music
+ QString hitmimetype = hit->getMimeType();
+ if (hitsource == "Amarok"
+ || hitmimetype.startsWith ("audio")
+ || hitmimetype == "application/ogg")
+ return MUSIC; // not an exhaustive search
+
+ // check for images from files
+ if (hitsource == "Files" && hitmimetype.startsWith ("image"))
+ return PICS;
+
+ if (hitsource == "Files" && hitmimetype.startsWith ("video"))
+ return VIDEOS;
+
+ if (hitsource == "Files")
+ return FILES;
+
+ if (hitsource == "KAddressBook")
+ return ACTIONS;
+
+ return OTHER;
+}
+
+K_EXPORT_COMPONENT_FACTORY( kickoffsearch_beagle,
+ KGenericFactory( "kickoffsearch_beagle" ) )
+
+KickoffBeaglePlugin::KickoffBeaglePlugin(QObject *parent, const char* name, const QStringList&)
+ : KickoffSearch::Plugin(parent, name ), genericTitle( true )
+{
+ g_type_init ();
+ current_beagle_client = NULL;
+}
+
+bool KickoffBeaglePlugin::daemonRunning()
+{
+ return beagle_util_daemon_is_running();
+}
+
+void KickoffBeaglePlugin::query(QString term, bool _genericTitle)
+{
+ genericTitle = _genericTitle;
+ current_query_str = term;
+
+ // Beagle search
+ if (current_beagle_client != NULL) {
+ kdDebug () << "Previous client w/id " << current_beagle_client->id << " still running ... ignoring it." << endl;
+ current_beagle_client->stopClient ();
+ }
+ current_beagle_client_id = KApplication::random ();
+ kdDebug () << "Creating client with id:" << current_beagle_client_id << endl;
+
+ BeagleClient *beagle_client = beagle_client_new (NULL);
+ if (beagle_client == NULL) {
+ kdDebug() << "beagle service not running ..." << endl;
+ return;
+ }
+
+ QStringList sources, types;
+ BeagleQuery *beagle_query = BeagleUtil::createQueryFromString (term, sources, types, 99); // maximum 99 results, if this doesnt work, blame the stars
+
+ current_beagle_client = new BeagleSearchClient (
+ current_beagle_client_id,
+ this,
+ beagle_client,
+ beagle_query,
+ false);
+ current_beagle_client->start();
+// kdDebug () << "Query dispatched at " << time (NULL) << endl;
+}
+
+void KickoffBeaglePlugin::cleanClientList ()
+{
+ toclean_list_mutex.lock ();
+ BeagleSearchClient *old_client = toclean_client_list.take (0);
+ if (old_client != NULL) { // failsafe
+ kdDebug () << "Cleanup old client " << old_client->id << endl;
+ delete old_client;
+ }
+ toclean_list_mutex.unlock ();
+}
+
+void KickoffBeaglePlugin::customEvent (QCustomEvent *e)
+{
+ if (e->type () == RESULTFOUND) {
+// kdDebug () << "Quick query thread at " << time (NULL) << " with current_id=" << current_beagle_client_id << " finished ..." << endl;
+ BeagleSearchResult *result = (BeagleSearchResult *) e->data ();
+ if (current_beagle_client_id != result->client_id) {
+ kdDebug () << "Stale result from " << result->client_id << endl;
+ delete result;
+ // FIXME: Should I also free e ?
+ } else {
+ kdDebug () << "Good results ...total=" << result->total << endl;
+ showResults (result);
+ }
+ //KPassivePopup::message( "This is the message", this );
+ } else if (e->type () == SEARCHOVER) {
+ BeagleSearchClient *client = (BeagleSearchClient *) e->data ();
+ if (client == NULL) {
+// kdDebug () << "Query finished event at " << time (NULL) << " but client is already deleted" << endl;
+ return;
+ }
+// kdDebug () << "Query finished event at " << time (NULL) << " for id=" << client->id << endl;
+ if (current_beagle_client_id == client->id) {
+ kickoffSearchInterface()->searchOver();
+ current_beagle_client = NULL; // important !
+ }
+ } else if (e->type () == KILLME) {
+ BeagleSearchClient *client = (BeagleSearchClient *) e->data ();
+ if (client->finished ())
+ delete client;
+ else {
+ // add client to cleanup list
+ toclean_list_mutex.lock ();
+ toclean_client_list.append (client);
+ kdDebug () << "Scheduling client to be deleted in 500ms" << endl;
+ toclean_list_mutex.unlock ();
+ QTimer::singleShot (500, this, SLOT (cleanClientList ()));
+ }
+ }
+}
+
+// this method decides what to display in the result list
+HitMenuItem *KickoffBeaglePlugin::hitToHitMenuItem (int category, Hit *hit)
+{
+ QString title, info, mimetype, icon;
+ int score = 0;
+ KURL uri;
+
+#if 0
+ kdDebug() << "*** " << hit->getUri() << endl;
+ QDict all = hit->getAllProperties();
+ QDictIterator it( all );
+ for( ; it.current(); ++it )
+ kdDebug() << it.currentKey() << ": " << *(it.current()) << endl;
+#endif
+
+ switch (category) {
+ case FILES:
+ {
+ uri = hit->getUri ();
+ QString uristr = uri.path ();
+ title = (*hit) [exactfilename];
+ int last_slash = uristr.findRev ('/', -1);
+ info = i18n("Folder: %1").arg(last_slash == 0 ? "/"
+ : uristr.section ('/', -2, -2));
+ }
+ break;
+ case ACTIONS:
+ {
+ if (hit->getSource()=="KAddressBook"){
+ title = i18n("Send Email to %1").arg((*hit)[vCard_FN]);
+ info = (*hit)[vCard_PREFEMAIL];
+ uri = "mailto:"+(*hit)[vCard_PREFEMAIL];
+ mimetype = hit->getMimeType ();
+ icon = "mail_new";
+
+ HitMenuItem * first_item=new HitMenuItem (title, info, uri, mimetype, 0, category, icon, score);
+ kickoffSearchInterface()->addHitMenuItem(first_item);
+
+ title =i18n("Open Addressbook at %1").arg((*hit)[vCard_FN]);
+ uri = "kaddressbook:/"+(*hit)[fixme_uid];
+ icon = "kaddressbook";
+ }
+ break;
+ }
+ case MAILS:
+ {
+ QString prefix = QString::null;
+ bool is_attachment = ((*hit) [parent_prefix + fixme_hasattachments] == "true");
+ bool has_parent = (! hit->getParentUri ().isEmpty ());
+ bool parent_mbox_file = false;
+ if (has_parent)
+ parent_mbox_file = ((*hit) [parent_prefix + fixme_folder] == QString::null);
+
+ // Logic:
+ // If has_parent == false, everything is normal
+ // If has_parent == true, parent_mbox_file == false, everything is normal, use uri
+ // FIXME: If has_parent == true, parent_mbox_file == true, ???
+ // If has_parent == true, is_attachment == true, hit is attach and access with prefix "parent:", use parenturi
+ // Else, not attachment (multipart), access with prefix "parent:", use parenturi
+
+ if (has_parent && !parent_mbox_file) {
+ uri = hit->getParentUri ();
+ prefix = parent_prefix;
+ if (is_attachment)
+ title = (*hit) [fixme_attachment_title];
+ if (title.isEmpty ())
+ title = (*hit) [prefix + dc_title];
+ if (title.isEmpty ())
+ title = i18n("No subject");
+ if (is_attachment)
+ title = title.prepend (i18n("(Attachment) "));
+ info = (i18n("From %1").arg((*hit) [prefix + fixme_from_address]));
+ } else {
+ uri = hit->getUri ();
+ title = (*hit) [dc_title];
+ info = (i18n("From %1").arg((*hit) [fixme_from_address]));
+ }
+ }
+ mimetype = "message/rfc822"; // to handle attachment results
+ break;
+ case MUSIC:
+ uri = hit->getUri ();
+ title = (*hit) [exactfilename];
+ {
+ QString artist = (*hit) [fixme_artist];
+ QString album = (*hit) [fixme_album];
+ if (! artist.isEmpty ())
+ info = (i18n("By %1").arg(artist));
+ else if (! album.isEmpty ())
+ info = (i18n("From Album %1").arg(album));
+ else {
+ QString uristr = uri.path ();
+ int last_slash = uristr.findRev ('/', -1);
+ info = i18n("Folder: %1")
+ .arg(last_slash == 0 ? "/" : uristr.section ('/', -2, -2));
+ }
+ }
+ break;
+ case VIDEOS:
+ uri = hit->getUri ();
+ title = (*hit) [exactfilename];
+ {
+ QString uristr = uri.path ();
+ int last_slash = uristr.findRev ('/', -1);
+ info = i18n("Folder: %1").arg(last_slash == 0 ? "/" : uristr.section ('/', -2, -2));
+ }
+ break;
+ case WEBHIST:
+ uri = hit->getUri ();
+ title = (*hit) [dc_title];
+ title = title.replace(QRegExp("\n")," ");
+ mimetype = "text/html";
+ if (title.isEmpty () || title.stripWhiteSpace ().isEmpty ()) {
+ title = uri.prettyURL ();
+ } else {
+ info = uri.host () + uri.path ();
+ }
+ break;
+ case FEEDS:
+ {
+ uri = KURL ((*hit) [dc_identifier]);
+ title = (*hit) [dc_title];
+ mimetype = "text/html";
+ QString publisher = (*hit) [dc_publisher];
+ QString source = (*hit) [dc_source];
+ if (! publisher.isEmpty ())
+ info = publisher;
+ else if (! source.isEmpty ())
+ info = source;
+ }
+ break;
+ case PICS:
+ {
+ uri = hit->getUri ();
+ title = (*hit) [exactfilename];
+ QString width = (*hit) [fixme_width];
+ QString height = (*hit) [fixme_height];
+ if (width.isEmpty () || height.isEmpty ()) {
+ QString uristr = uri.path ();
+ int last_slash = uristr.findRev ('/', -1);
+ info = i18n("Folder: %1")
+ .arg(last_slash == 0 ? "/" : uristr.section ('/', -2, -2));
+ break;
+ }
+ info = (QString (" (%1x%2)").arg (width).arg (height));
+ const QStringList *tags = hit->getProperties (digikam_tag);
+ if (tags == NULL)
+ break;
+ QString tags_string = tags->join (comma_string);
+ info += (" " + tags_string);
+ }
+ break;
+ case APPS:
+ {
+ uri = hit->getUri ();
+ title = (*hit) [dc_title];
+ KDesktopFile desktopfile(uri.path(),true);
+ if (genericTitle && !desktopfile.readGenericName().isEmpty()) {
+ title = desktopfile.readGenericName();
+ info = desktopfile.readName();
+ }
+ else {
+ title = desktopfile.readName();
+ info = desktopfile.readGenericName();
+ }
+ icon = desktopfile.readIcon();
+ QString input = current_query_str.lower();
+ QString command = desktopfile.readEntry("Exec");
+ if (command==input)
+ score = 100;
+ else if (command.find(input)==0)
+ score = 50;
+ else if (command.find(input)!=-1)
+ score = 10;
+ else if (title==input)
+ score = 100;
+ else if (title.find(input)==0)
+ score = 50;
+ else if (title.find(input)!=-1)
+ score = 10;
+ break;
+ }
+ break;
+ case NOTES:
+ {
+ uri = hit->getUri ();
+ title = (*hit) [dc_title];
+ title = i18n("Title: %1").arg(title.isEmpty() ? i18n("Untitled") : title);
+
+ if (hit->getSource()=="KNotes")
+ icon="knotes";
+ else
+ icon="contents2";
+ }
+ break;
+ case CHATS:
+ {
+ uri = hit->getUri ();
+ title = (*hit) [fixme_speakingto];
+ title = i18n("Conversation With %1").arg(title.isEmpty() ? i18n("Unknown Person") : title);
+ QDateTime datetime;
+ datetime = datetimeFromString((*hit) [fixme_starttime]);
+ info=i18n("Date: %1").arg(KGlobal::locale()->formatDateTime(datetime,false));
+ if (hit->getMimeType()=="beagle/x-kopete-log")
+ icon="kopete";
+ else
+ icon="gaim";
+ }
+ break;
+ case DOCS:
+ {
+ uri = hit->getUri ();
+ title = (*hit) [dc_title];
+ if (title.isEmpty () || title.stripWhiteSpace ().isEmpty ())
+ title = uri.prettyURL ();
+ else {
+ QString uristr = uri.path ();
+ int last_slash = uristr.findRev ('/', -1);
+ info = i18n("Folder: %1").arg(last_slash == 0 ? "/" : uristr.section ('/',
+ -2, -2));
+ }
+ }
+ break;
+ default:
+ return NULL;
+ }
+ if (mimetype.isEmpty ())
+ mimetype = hit->getMimeType ();
+ return new HitMenuItem (title, info, uri, mimetype, 0, category, icon, score);
+}
+
+void KickoffBeaglePlugin::showResults(BeagleSearchResult *result)
+{
+ if (result->total == 0 ) {
+ // Dont report error from here ...
+ kdDebug() << "No matches found" << endl;
+ delete result;
+ return;
+ }
+
+ const QPtrList *hits = result->getHits();
+ if (hits == NULL) {
+ kdDebug () << "Hmm... null" << endl;
+ delete result;
+ return;
+ }
+ kickoffSearchInterface()->initCategoryTitlesUpdate();
+
+ QPtrListIterator it (*hits);
+ Hit *hit;
+ for (; (hit = it.current ()) != NULL; ++it) {
+ CATEGORY category = getHitCategory (hit);
+
+ // if category is not handled, continue
+ if (category == OTHER)
+ continue;
+
+ if ( category == APPS ) {
+ // we need to check if this is useful
+ KService cs( hit->getUri().path() );
+ if ( cs.noDisplay() )
+ continue;
+ }
+
+ if (!kickoffSearchInterface()->anotherHitMenuItemAllowed(category))
+ continue;
+
+ HitMenuItem *hit_item = hitToHitMenuItem (category, hit);
+
+ if (!hit_item)
+ continue;
+
+ kickoffSearchInterface()->addHitMenuItem(hit_item);
+ }
+
+ kickoffSearchInterface()->updateCategoryTitles();
+
+ delete result;
+}
+
+QDateTime KickoffBeaglePlugin::datetimeFromString( const QString& s)
+{
+ int year( s.mid( 0, 4 ).toInt() );
+ int month( s.mid( 4, 2 ).toInt() );
+ int day( s.mid( 6, 2 ).toInt() );
+ int hour( s.mid( 8, 2 ).toInt() );
+ int min( s.mid( 10, 2 ).toInt() );
+ int sec( s.mid( 12, 2 ).toInt() );
+ return QDateTime(QDate(year,month,day),QTime(hour,min,sec));
+}
+
+#include "kickoff-beagle-plugin.moc"
--- kicker/plugins/Makefile.am (revision 0)
+++ kicker/plugins/Makefile.am (revision 774644)
@@ -0,0 +1,24 @@
+INCLUDES = -I$(top_srcdir)/interfaces $(all_includes) $(LIBBEAGLE_CFLAGS) $(GLIB_CFLAGS)
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kickoffsearch_beagle.la
+
+# Srcs for the plugin
+kickoffsearch_beagle_la_SOURCES = kickoff-beagle-plugin.cpp beaglesearch.cpp
+
+# Libs needed by the plugin
+kickoffsearch_beagle_la_LIBADD = $(LIB_KPARTS) ../interfaces/libkickoffsearch_interfaces.la \
+ $(LIBBEAGLE_LIBADD) $(GLIB_LIBADD)
+
+# LD flags for the plugin
+# -module says: this is a module, i.e. something you're going to dlopen
+# so e.g. it has no version number like a normal shared lib would have.
+kickoffsearch_beagle_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kickoffsearch_beagle.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kickoffsearch_beagle.pot
--- kicker/plugins/kickoffsearch_beagle.desktop (revision 0)
+++ kicker/plugins/kickoffsearch_beagle.desktop (revision 774644)
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Name=Beagle Search
+Comment=Beagle search plugin for Kickoff search
+ServiceTypes=KickoffSearch/Plugin
+Type=Service
+X-KDE-Library=kickoffsearch_beagle
--- kicker/plugins/beaglesearch.h (revision 0)
+++ kicker/plugins/beaglesearch.h (revision 774644)
@@ -0,0 +1,234 @@
+/*****************************************************************
+
+ Copyright (c) 2006 Debajyoti Bera
+
+ 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 BEAGLESEARCH_H
+#define BEAGLESEARCH_H
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+extern "C" {
+#include
+#include
+}
+
+// BeagleSearchClient sends 3 types of events
+// when results are to be sent as they arrive,
+// - RESULTFOUND : when result is found
+// - SEARCHOVER : when search is over
+// - KILLME : just before thread finishes - used to cleanup the thread object
+// when results are to be sent after receiving all of them
+// - RESULTFOUND : when all results are obtained
+// - KILLME : just before thread finishes - used to cleanup the thread object
+#define RESULTFOUND (QEvent::Type)1001 /* QEvent::User + 1 */
+#define SEARCHOVER (QEvent::Type)1002 /* QEvent::User + 2 */
+#define KILLME (QEvent::Type)1003 /* QEvent::User + 3 */
+
+class QStringList;
+
+// IMPORTANT: Call this before any beagle calls
+void beagle_init ();
+
+class Hit {
+public:
+ Hit (BeagleHit *_hit);
+ ~Hit ();
+
+ // convenience wrappers
+ // remember that the hit values are utf8 strings
+ const KURL getUri () const { return KURL (QString::fromUtf8 (beagle_hit_get_uri (hit)));}
+ const QString getType () const { return QString::fromUtf8 (beagle_hit_get_type (hit));}
+ const QString getMimeType () const { return QString::fromUtf8 (beagle_hit_get_mime_type (hit));}
+ const QString getSource () const { return QString::fromUtf8 (beagle_hit_get_source (hit));}
+ const KURL getParentUri () const { return KURL (QString::fromUtf8 (beagle_hit_get_parent_uri (hit)));}
+ const QDict& getAllProperties ()
+ {
+ if (! processed)
+ processProperties ();
+ return property_map;
+ }
+ const QStringList* getProperties (QString prop_name)
+ {
+ if (! processed)
+ processProperties ();
+ return property_map [prop_name];
+ }
+ const QString operator[] (QString prop_name);
+
+private:
+ BeagleHit *hit;
+ QDict property_map;
+ // not every hit may be used. so, do a lazy processing of property_map
+ bool processed;
+ void processProperties ();
+};
+
+class BeagleSearchResult{
+public:
+ BeagleSearchResult(int client_id);
+ ~BeagleSearchResult();
+ void addHit (BeagleHit *hit);
+ QString getHitCategory (Hit *hit);
+
+ // id of the bsclient
+ int client_id;
+ // time taken to finish query
+ int query_msec;
+ // total number of results in this query
+ int total;
+
+ const QPtrList *getHits () const;
+
+private:
+ // lists of hits
+ QPtrList *hitlist;
+};
+
+// caller should delete bsclient->result and bsclient
+class BeagleSearchClient : public QThread {
+public:
+ // passing NULL for client makes bsclient create client itself and
+ // delete it later
+ BeagleSearchClient (int id,
+ QObject *y,
+ BeagleClient *client,
+ BeagleQuery *query,
+ bool collate_results)
+ : id (id), kill_me (false), object (y), client (client),
+ query (query), destroy_client (false), collate_results (collate_results)
+ {
+ if (client == NULL) {
+ client = beagle_client_new (NULL);
+ destroy_client = true;
+ }
+
+// if (client == NULL)
+// throw -1;
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ if (collate_results)
+ result = new BeagleSearchResult (id);
+
+ client_mutex = new QMutex ();
+ }
+
+ // It is never safe to delete BeagleSearchClient directly, the thread might still be running
+ ~BeagleSearchClient ()
+ {
+ if (! finished ()) {
+ kdDebug () << "Thread " << id << " still running. Waiting.........." << endl;
+ wait ();
+ }
+
+ if (destroy_client)
+ g_object_unref (client);
+ g_main_loop_unref (main_loop);
+ g_object_unref (query);
+ kdDebug() << "Deleting client ..." << id << endl;
+ delete client_mutex;
+ }
+
+private:
+ static void hitsAddedSlot (BeagleQuery *query,
+ BeagleHitsAddedResponse *response,
+ BeagleSearchClient *bsclient);
+
+ static void finishedSlot (BeagleQuery *query,
+ BeagleFinishedResponse *response,
+ BeagleSearchClient *bsclient);
+
+public:
+ // run() starts the query and sends the result as follows:
+ // - either wait till get back all results and send it as RESULTFOUND
+ // - or, send results as it gets them as RESULTFOUND and
+ // send SEARCHOVER when finished
+ // collate_results controls the behaviour
+ virtual void run ( );
+
+ // after stopClient() is called, application can safely go and remove previous menu entries
+ // - i.e. after stopClient is called, app doesnt except the eventhandler to receive any results
+ // - use client_id to determine which is the current client, set it right after stopclient
+ // - Eventhandler checks client id, if it is current, it adds stuff to the menu
+ // else, it discards everything
+ // Once eventhandler is being processed, doQuery() wont be called and vice versa
+ // so no need to serialize eventhandler and doquery
+ //
+ // stopClient needs to make sure that once it is called, the thread is finished asap. Use a mutex
+ // to serialize actions. callbacks need to use mutex too.
+ // stopclient has to remove signal handlers to prevent further signal calls, set kill_me flag
+ // and quite main loop
+ // stopClient can be called at the following times:
+ // - Waiting for the first result:
+ // nothing extra
+ // - in hitsAddedSlot, processing results
+ // in callback, before processing, if killme is set, just return.
+ // - in hitsAddedSlot, after sending results
+ // before sending, if killme is set, dont send results
+ // (doing it twice in hitsAdded because forming BeagleSearchResult can take time)
+ // - Waiting for more results
+ // nothing extra
+ // - in finishedSlot, before sending finishedMsg
+ // if killme is set, just return
+ // - in finishedSlot, after sending finishedMsg
+ // if killme is set, just return
+ // in Run(), when return from mainloop, if killme is set, dont do anything more but call delete this
+ void stopClient ();
+
+ // id of the client
+ // this is required in case applications fires many clients in rapid succession
+ int id;
+
+ GMainLoop * main_loop;
+ BeagleSearchResult *result;
+
+ // this is set if the client is obsolete now i.e.
+ // the application doesnt need the results from the client anymore
+ bool kill_me;
+private:
+ // the application; need this to send events to the application
+ QObject *object;
+ // mutex to control setting the kill_me shared variable
+ QMutex *client_mutex;
+ BeagleClient *client;
+ BeagleQuery *query;
+ // should the client be destroyed by the client
+ // if the client created it, then most probably it should
+ bool destroy_client;
+ bool collate_results;
+};
+
+class BeagleUtil {
+public:
+
+ static BeagleQuery *createQueryFromString (QString query_str,
+ QStringList &sources,
+ QStringList &types,
+ int max_hits_per_source = 100);
+ static BeagleTimestamp *timestringToBeagleTimestamp (QString timestring);
+};
+
+#endif
--- kicker/plugins/kickoff-beagle-plugin.h (revision 0)
+++ kicker/plugins/kickoff-beagle-plugin.h (revision 774644)
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Stephan Binner *
+ * Copyright (c) 2006 Debajyoti Bera *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef CAPITALIZEPLUGIN_H
+#define CAPITALIZEPLUGIN_H
+
+#include "../interfaces/kickoff-search-plugin.h"
+#include "beaglesearch.h"
+
+class KickoffBeaglePlugin :public KickoffSearch::Plugin
+{
+ Q_OBJECT
+
+public:
+ KickoffBeaglePlugin(QObject *parent, const char* name, const QStringList&);
+
+ void query(QString, bool);
+ bool daemonRunning();
+
+protected slots:
+ // to clean beaglesearchclients
+ void cleanClientList ();
+
+private:
+ QString current_query_str;
+
+ // all beagle activity is done through the BSC object
+ BeagleSearchClient *current_beagle_client;
+
+ // used to send notification from the beagle thread to the main event loop
+ virtual void customEvent (QCustomEvent *e);
+
+ QPtrList toclean_client_list;
+ QMutex toclean_list_mutex;
+
+ // show the results
+ void showResults (BeagleSearchResult *);
+ HitMenuItem *hitToHitMenuItem (int category, Hit *hit);
+
+ // use a different id for each bsc client, and use that to separate stale responses from current ones
+ int current_beagle_client_id;
+
+ bool genericTitle;
+ QDateTime datetimeFromString( const QString& );
+};
+
+#endif /* CAPITALIZEPLUGIN_H */
Property changes on: kicker/plugins
___________________________________________________________________
Added: svn:ignore
+ .deps
kickoffsearch_beagle.la
.libs
Makefile
Makefile.in
*.moc
--- kicker/interfaces/kickoff-search-plugin.h (revision 0)
+++ kicker/interfaces/kickoff-search-plugin.h (revision 774644)
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Stephan Binner *
+ * Copyright (c) 2006 Debajyoti Bera *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KICKOFF_SEARCH_PLUGIN_H
+#define KICKOFF_SEARCH_PLUGIN_H
+
+#include "kickoffsearchinterface.h"
+
+#include
+#include
+#include
+
+typedef enum {
+ ACTIONS = 0,
+ APPS,
+ BOOKMARKS,
+ NOTES,
+ MAILS,
+ FILES,
+ MUSIC,
+ WEBHIST,
+ CHATS,
+ FEEDS,
+ PICS,
+ VIDEOS,
+ DOCS,
+ OTHER,
+ num_categories
+} CATEGORY;
+
+class HitMenuItem
+{
+public:
+ HitMenuItem (int id, int category)
+ : id (id), category (category),score(0) { } /* dummy */
+ HitMenuItem (QString name, QString info, KURL uri, QString mimetype, int id, int category, QString icon=QString::null, int score = 0)
+ : display_name (name)
+ , display_info (info)
+ , uri (uri)
+ , mimetype (mimetype)
+ , id (id)
+ , category (category)
+ , icon (icon)
+ , score (score)
+ , service (NULL) { }
+
+ ~HitMenuItem () { }
+
+ bool operator< (HitMenuItem item)
+ {
+ return ((category == item.category && score > item.score) || (category == item.category && id < item.id) ||
+ (category < item.category));
+ }
+
+ // FIXME: We dont really need to store display_name and display_info
+ QString display_name; // name to display
+ QString display_info; // other information to display
+ KURL uri; // uri to open when clicked
+ QString mimetype;
+ int id; // id of the item in the menu
+ int category;
+ QString icon;
+ int score;
+ KService::Ptr service;
+
+ QString quotedPath () const
+ {
+ return uri.path ().replace ('"', "\\\"");
+ }
+};
+
+namespace KickoffSearch {
+
+ class Plugin : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ Plugin(QObject *parent, const char* name=0);
+ virtual ~Plugin();
+
+ virtual bool daemonRunning()=0;
+ virtual void query(QString,bool)=0;
+
+ KickoffSearchInterface * kickoffSearchInterface();
+ };
+};
+
+#endif /* KICKOFF_SEARCH_PLUGIN_H */
--- kicker/interfaces/kickoffsearchinterface.cpp (revision 0)
+++ kicker/interfaces/kickoffsearchinterface.cpp (revision 774644)
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Stephan Binner *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kickoffsearchinterface.h"
+
+KickoffSearch::KickoffSearchInterface::KickoffSearchInterface( QObject* parent, const char* name )
+ :QObject( parent, name )
+{
+}
+
+#include "kickoffsearchinterface.moc"
--- kicker/interfaces/Makefile.am (revision 0)
+++ kicker/interfaces/Makefile.am (revision 774644)
@@ -0,0 +1,12 @@
+METASOURCES = AUTO
+INCLUDES= -I$(top_srcdir)/src $(all_includes)
+
+# The library containing the plugin base class
+lib_LTLIBRARIES = libkickoffsearch_interfaces.la
+libkickoffsearch_interfaces_la_SOURCES = kickoff-search-plugin.cpp kickoffsearchinterface.cpp
+libkickoffsearch_interfaces_la_LDFLAGS = $(all_libraries) -version-info 0:0:0
+
+kickoffsearchincludedir = $(includedir)
+kickoffsearchinclude_HEADERS = kickoff-search-plugin.h kickoffsearchinterface.h
+
+kde_servicetypes_DATA = kickoffsearchplugin.desktop
--- kicker/interfaces/kickoffsearchinterface.h (revision 0)
+++ kicker/interfaces/kickoffsearchinterface.h (revision 774644)
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Stephan Binner *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KICKOFFSEARCHINTERFACE_H
+#define KICKOFFSEARCHINTERFACE_H
+
+#include
+
+class HitMenuItem;
+
+namespace KickoffSearch
+{
+ class KickoffSearchInterface :public QObject
+ {
+ Q_OBJECT
+
+ public:
+ KickoffSearchInterface( QObject* parent, const char* name = 0);
+
+ public:
+ virtual bool anotherHitMenuItemAllowed(int cat) = 0;
+ virtual void addHitMenuItem(HitMenuItem* item) = 0;
+ virtual void searchOver() = 0;
+ virtual void initCategoryTitlesUpdate() = 0;
+ virtual void updateCategoryTitles() = 0;
+ };
+}
+
+#endif /* SELECTIONINTERFACE_H */
+
--- kicker/interfaces/kickoffsearchplugin.desktop (revision 0)
+++ kicker/interfaces/kickoffsearchplugin.desktop (revision 774644)
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KickoffSearch/Plugin
+Comment=A search plugin for Kickoff
--- kicker/interfaces/kickoff-search-plugin.cpp (revision 0)
+++ kicker/interfaces/kickoff-search-plugin.cpp (revision 774644)
@@ -0,0 +1,37 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Stephan Binner *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kickoff-search-plugin.h"
+#include
+
+KickoffSearch::Plugin::Plugin(QObject *parent, const char* name )
+ :QObject( parent, name )
+{
+}
+
+KickoffSearch::Plugin::~Plugin()
+{
+}
+
+KickoffSearch::KickoffSearchInterface* KickoffSearch::Plugin::kickoffSearchInterface()
+{
+ return static_cast( parent()->child( 0, "KickoffSearch::KickoffSearchInterface" ) );
+}
+
+#include "kickoff-search-plugin.moc"
Property changes on: kicker/interfaces
___________________________________________________________________
Added: svn:ignore
+ .deps
libkickoffsearch_interfaces.la
.libs
Makefile
Makefile.in
*.moc
--- kicker/core/menumanager.h (revision 755866)
+++ kicker/core/menumanager.h (revision 774644)
@@ -28,7 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE
#include
class PanelKMenu;
+class KMenu;
class KickerClientMenu;
+class KMenuStub;
class PanelPopupButton;
typedef QValueList KButtonList;
@@ -50,13 +52,12 @@ public:
bool process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &reply);
// KMenu controls
- PanelKMenu* kmenu() { return m_kmenu; }
- void showKMenu();
+ KMenuStub* kmenu() { return m_kmenu; }
void popupKMenu(const QPoint &p);
void registerKButton(PanelPopupButton *button);
void unregisterKButton(PanelPopupButton *button);
- PanelPopupButton* findKButtonFor(QPopupMenu* menu);
+ PanelPopupButton* findKButtonFor(QWidget* menu);
~MenuManager();
public slots:
@@ -67,7 +68,7 @@ protected slots:
void applicationRemoved(const QCString&);
protected:
- PanelKMenu* m_kmenu;
+ KMenuStub* m_kmenu;
typedef QValueList ClientMenuList;
ClientMenuList clientmenus;
--- kicker/core/kicker.cpp (revision 755866)
+++ kicker/core/kicker.cpp (revision 774644)
@@ -48,6 +48,8 @@
#include "extensionmanager.h"
#include "pluginmanager.h"
#include "menumanager.h"
+#include "k_new_mnu.h"
+#include "k_mnu_stub.h"
#include "k_mnu.h"
#include "showdesktop.h"
#include "panelbutton.h"
@@ -106,6 +108,7 @@ Kicker::Kicker()
KGlobal::iconLoader()->addExtraDesktopThemes();
+ KGlobal::locale()->insertCatalogue("kdmgreet");
KGlobal::locale()->insertCatalogue("libkonq");
KGlobal::locale()->insertCatalogue("libdmctl");
KGlobal::locale()->insertCatalogue("libtaskbar");
@@ -206,7 +209,7 @@ bool Kicker::highlightMenuItem(const QSt
void Kicker::showKMenu()
{
- MenuManager::the()->showKMenu();
+ MenuManager::the()->kmenuAccelActivated();
}
void Kicker::popupKMenu(const QPoint &p)
--- kicker/core/container_button.cpp (revision 755866)
+++ kicker/core/container_button.cpp (revision 774644)
@@ -43,6 +43,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE
#include "desktopbutton.h"
#include "extensionbutton.h"
#include "kbutton.h"
+#include "knewbutton.h"
#include "kicker.h"
#include "kickerSettings.h"
#include "kickertip.h"
@@ -367,14 +368,20 @@ KMenuButtonContainer::KMenuButtonContain
: ButtonContainer(opMenu, parent)
{
checkImmutability(config);
- embedButton( new KButton(this) );
+ if(KickerSettings::legacyKMenu())
+ embedButton( new KButton(this) );
+ else
+ embedButton( new KNewButton(this) );
_actions = PanelAppletOpMenu::KMenuEditor;
}
KMenuButtonContainer::KMenuButtonContainer(QPopupMenu *opMenu, QWidget* parent)
: ButtonContainer(opMenu, parent)
{
- embedButton( new KButton(this) );
+ if(KickerSettings::legacyKMenu())
+ embedButton( new KButton(this) );
+ else
+ embedButton( new KNewButton(this) );
_actions = PanelAppletOpMenu::KMenuEditor;
}
--- kicker/core/main.cpp (revision 755866)
+++ kicker/core/main.cpp (revision 774644)
@@ -108,7 +108,7 @@ extern "C" KDE_EXPORT int kdemain( int a
appname.sprintf("kicker-screen-%d", kicker_screen_number);
KAboutData aboutData( appname.data(), I18N_NOOP("KDE Panel"),
- version, description, KAboutData::License_BSD,
+ version, description, KAboutData::License_GPL_V2,
I18N_NOOP("(c) 1999-2004, The KDE Team") );
aboutData.addAuthor("Aaron J. Seigo", I18N_NOOP("Current maintainer"), "aseigo@kde.org");
--- kicker/core/menumanager.cpp (revision 755866)
+++ kicker/core/menumanager.cpp (revision 774644)
@@ -31,9 +31,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE
#include "client_mnu.h"
#include "container_extension.h"
#include "global.h"
+#include "k_new_mnu.h"
#include "k_mnu.h"
+#include "k_mnu_stub.h"
#include "kicker.h"
#include "panelbutton.h"
+#include "kickerSettings.h"
#include "menumanager.h"
#include "menumanager.moc"
@@ -62,7 +65,11 @@ MenuManager* MenuManager::the()
MenuManager::MenuManager(QObject *parent)
: QObject(parent, "MenuManager"), DCOPObject("MenuManager")
{
- m_kmenu = new PanelKMenu;
+ if (KickerSettings::legacyKMenu())
+ m_kmenu = new KMenuStub(new PanelKMenu);
+ else
+ m_kmenu = new KMenuStub(new KMenu);
+
kapp->dcopClient()->setNotifications(true);
connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)),
this, SLOT(applicationRemoved(const QCString&)));
@@ -83,14 +90,8 @@ void MenuManager::slotSetKMenuItemActive
m_kmenu->selectFirstItem();
}
-void MenuManager::showKMenu()
-{
- m_kmenu->showMenu();
-}
-
void MenuManager::popupKMenu(const QPoint &p)
{
-// kdDebug(1210) << "popupKMenu()" << endl;
if (m_kmenu->isVisible())
{
m_kmenu->hide();
@@ -120,7 +121,7 @@ void MenuManager::unregisterKButton(Pane
m_kbuttons.remove(button);
}
-PanelPopupButton* MenuManager::findKButtonFor(QPopupMenu* menu)
+PanelPopupButton* MenuManager::findKButtonFor(QWidget* menu)
{
KButtonList::const_iterator itEnd = m_kbuttons.constEnd();
for (KButtonList::const_iterator it = m_kbuttons.constBegin(); it != itEnd; ++it)
@@ -169,7 +170,7 @@ void MenuManager::kmenuAccelActivated()
const QSize size = m_kmenu->sizeHint();
m_kmenu->resize(size.width(),size.height());
- PanelPopupButton* button = findKButtonFor(m_kmenu);
+ PanelPopupButton* button = findKButtonFor(m_kmenu->widget());
// let's unhide the panel while we're at it. traverse the widget
// hierarchy until we find the panel, if any
@@ -189,7 +190,6 @@ void MenuManager::kmenuAccelActivated()
menuParent = menuParent->parent();
}
-
button->showMenu();
}
}
@@ -213,7 +213,7 @@ QCString MenuManager::createMenu(QPixmap
void MenuManager::removeMenu(QCString menu)
{
- bool iterate = true;
+ bool iterate = true, need_adjustSize = false;
ClientMenuList::iterator it = clientmenus.begin();
for (; it != clientmenus.end(); iterate ? ++it : it)
{
@@ -224,15 +224,17 @@ void MenuManager::removeMenu(QCString me
m_kmenu->removeClientMenu(m->idInParentMenu);
it = clientmenus.erase(it);
iterate = false;
+ need_adjustSize = true;
}
}
- m_kmenu->adjustSize();
+ if (need_adjustSize)
+ m_kmenu->adjustSize();
}
void MenuManager::applicationRemoved(const QCString& appRemoved)
{
- bool iterate = true;
+ bool iterate = true, need_adjustSize = false;
ClientMenuList::iterator it = clientmenus.begin();
for (; it != clientmenus.end(); iterate ? ++it : it)
{
@@ -243,9 +245,11 @@ void MenuManager::applicationRemoved(con
m_kmenu->removeClientMenu(m->idInParentMenu);
it = clientmenus.erase(it);
iterate = false;
+ need_adjustSize = true;
}
}
- m_kmenu->adjustSize();
+ if (need_adjustSize)
+ m_kmenu->adjustSize();
}
bool MenuManager::process(const QCString &fun, const QByteArray &data,
--- kicker/core/unhidetrigger.cpp (revision 755866)
+++ kicker/core/unhidetrigger.cpp (revision 774644)
@@ -39,7 +39,7 @@ UnhideTrigger::UnhideTrigger()
, _lastXineramaScreen( -1 )
, enabledCount( 0 )
{
- _timer = new QTimer( this );
+ _timer = new QTimer( this, "UnhideTrigger" );
connect( _timer, SIGNAL(timeout()), SLOT(pollMouse()) );
}
--- kicker/core/applethandle.cpp (revision 755866)
+++ kicker/core/applethandle.cpp (revision 774644)
@@ -196,7 +196,7 @@ void AppletHandle::setFadeOutHandle(bool
{
if (!m_handleHoverTimer)
{
- m_handleHoverTimer = new QTimer(this);
+ m_handleHoverTimer = new QTimer(this, "m_handleHoverTimer");
connect(m_handleHoverTimer, SIGNAL(timeout()),
this, SLOT(checkHandleHover()));
m_applet->installEventFilter(this);
@@ -223,11 +223,7 @@ bool AppletHandle::eventFilter(QObject *
m_drawHandle = true;
resetLayout();
- if (m_handleHoverTimer)
- {
- m_handleHoverTimer->start(250);
- }
- break;
+ break;
}
case QEvent::Leave:
@@ -237,6 +233,11 @@ bool AppletHandle::eventFilter(QObject *
break;
}
+ if (m_handleHoverTimer)
+ {
+ m_handleHoverTimer->start(250);
+ }
+
QWidget* w = dynamic_cast(o);
bool nowDrawIt = false;
@@ -253,11 +254,6 @@ bool AppletHandle::eventFilter(QObject *
if (nowDrawIt != m_drawHandle)
{
- if (m_handleHoverTimer)
- {
- m_handleHoverTimer->stop();
- }
-
m_drawHandle = nowDrawIt;
resetLayout();
}
@@ -345,6 +341,11 @@ void AppletHandle::toggleMenuButtonOff()
m_menuButton->setOn(false);
m_menuButton->setDown(false);
+
+ if (m_handleHoverTimer)
+ {
+ m_handleHoverTimer->start(250);
+ }
}
QPixmap AppletHandle::xpmPixmap( const char* const xpm[], const char* _key )
--- kicker/core/containerarea.cpp (revision 755866)
+++ kicker/core/containerarea.cpp (revision 774644)
@@ -87,7 +87,8 @@ ContainerArea::ContainerArea(KConfig* _c
m_immutable(_c->isImmutable()),
m_updateBackgroundsCalled(false),
m_layout(0),
- m_addAppletDialog(0)
+ m_addAppletDialog(0),
+ _autoScrollTimer(0, "ContainerArea::autoScrollTimer")
{
setBackgroundOrigin( WidgetOrigin );
viewport()->setBackgroundOrigin( AncestorOrigin );
--- kicker/core/Makefile.am (revision 755866)
+++ kicker/core/Makefile.am (revision 774644)
@@ -1,6 +1,6 @@
INCLUDES = -I$(srcdir)/../../libkicker -I../../libkicker \
- -I$(srcdir)/../ui -I$(srcdir)/../buttons -I$(top_srcdir)/libkonq \
- $(all_includes)
+ -I../ui -I$(srcdir)/../ui -I$(srcdir)/../buttons -I$(top_srcdir)/libkonq \
+ $(all_includes) $(LIBBEAGLE_CFLAGS) $(GLIB_CFLAGS)
noinst_LTLIBRARIES = libkicker_core.la
--- kicker/Makefile.am (revision 755866)
+++ kicker/Makefile.am (revision 774644)
@@ -1,6 +1,6 @@
INCLUDES = $(all_includes)
-SUBDIRS = core ui buttons .
+SUBDIRS = core ui buttons interfaces plugins .
bin_PROGRAMS =
lib_LTLIBRARIES =
@@ -9,7 +9,7 @@ kdeinit_LTLIBRARIES = kicker.la
CLEANFILES = dummy.cpp
kicker_la_LIBADD = core/libkicker_core.la buttons/libkicker_buttons.la \
- ui/libkicker_ui.la ../libkicker/libkickermain.la $(LIB_KIO) $(LIB_KUTILS)
+ ui/libkicker_ui.la ../libkicker/libkickermain.la $(LIB_KIO) $(LIB_KUTILS) $(LIB_KABC)
kicker_la_SOURCES = dummy.cpp
kicker_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
--- kicker/ui/browser_mnu.cpp (revision 755866)
+++ kicker/ui/browser_mnu.cpp (revision 774644)
@@ -329,7 +329,7 @@ void PanelBrowserMenu::initialize()
if(_mimemap.count() > 0) {
if(!_mimecheckTimer)
- _mimecheckTimer = new QTimer(this);
+ _mimecheckTimer = new QTimer(this, "_mimecheckTimer");
connect(_mimecheckTimer, SIGNAL(timeout()), SLOT(slotMimeCheck()));
_mimecheckTimer->start(0);
--- kicker/ui/flipscrollview.cpp (revision 0)
+++ kicker/ui/flipscrollview.cpp (revision 774644)
@@ -0,0 +1,324 @@
+/*****************************************************************
+
+Copyright (c) 2006 Will Stephenson
+
+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
+#include
+#include
+#include
+
+#include "itemview.h"
+#include "flipscrollview.h"
+#include "kickerSettings.h"
+
+/* Flip scroll steps, as percentage of itemview width to scroll per
+ * step. Assumes the itemview is scrolled in ten steps */
+
+/* slow start, then fast */
+//static const double scrollSteps[] = { 0.05, 0.05, 0.1125, 0.1125, 0.1125, 0.1125, 0.1125, 0.1125, 0.1125, 0.1125 };
+
+/* slow fast slow */
+//static const double scrollSteps[] = { 0.05, 0.05, 0.13, 0.13, 0.15, 0.13, 0.13, 0.13, 0.05, 0.05 };
+
+/* slow veryfast slow */
+static const double scrollSteps[] = { 0.03, 0.03, 0.147, 0.147, 0.147, 0.147, 0.147, 0.147, 0.03, 0.028 };
+;
+
+BackFrame::BackFrame( QWidget *parent )
+ : QFrame( parent ), mouse_inside( false )
+{
+ setFrameStyle( QFrame::NoFrame );
+ if ( QApplication::reverseLayout() )
+ left_triangle.load( locate( "data", "kicker/pics/right_triangle.png" ) );
+ else
+ left_triangle.load( locate( "data", "kicker/pics/left_triangle.png" ) );
+}
+
+void BackFrame::drawContents( QPainter *p )
+{
+ QColor gray( 230, 230, 230 );
+ if ( mouse_inside )
+ p->fillRect( 3, 3, width() - 6, height() - 6, colorGroup().color( QColorGroup::Highlight ) );
+ else
+ p->fillRect( 3, 3, width() - 6, height() - 6, gray );
+ p->setPen( gray.dark(110) );
+ p->drawRect( 3, 3, width() - 6, height() - 6 );
+
+ int pixsize = ( width() - 6 ) * 3 / 5;
+ QImage i = left_triangle.convertToImage().smoothScale( pixsize, pixsize );
+ QPixmap tri;
+ tri.convertFromImage( i );
+
+ p->drawPixmap( ( width() - tri.width() ) / 2, ( height() - tri.height() ) / 2, tri );
+}
+
+void BackFrame::enterEvent( QEvent *e )
+{
+ mouse_inside = true;
+ update();
+}
+
+void BackFrame::leaveEvent( QEvent *e )
+{
+ mouse_inside = false;
+ update();
+}
+
+void BackFrame::mousePressEvent ( QMouseEvent * e )
+{
+ emit clicked();
+}
+
+FlipScrollView::FlipScrollView( QWidget * parent, const char * name )
+ : QScrollView( parent, name ), mState( StoppedLeft ), mScrollDirection( 1 ), mShowBack( false )
+{
+ setVScrollBarMode( QScrollView::AlwaysOff );
+ setHScrollBarMode( QScrollView::AlwaysOff );
+ setFrameStyle( QFrame::NoFrame );
+ mLeftView = new ItemView( this, "left_view" );
+ addChild( mLeftView );
+
+ mRightView = new ItemView( this, "right_view" );
+ addChild( mRightView );
+
+ mTimer = new QTimer( this, "mTimer" );
+ connect( mTimer, SIGNAL( timeout() ), SLOT( slotScrollTimer() ) );
+
+ connect( mLeftView, SIGNAL( startService(KService::Ptr) ),
+ SIGNAL( startService(KService::Ptr) ) );
+ connect( mLeftView, SIGNAL( startURL(const QString& ) ),
+ SIGNAL( startURL(const QString& ) ) );
+ connect( mLeftView, SIGNAL( rightButtonPressed(QListViewItem*,const QPoint&,int) ),
+ SIGNAL( rightButtonPressed(QListViewItem*,const QPoint&,int) ) );
+ connect( mRightView, SIGNAL( startService(KService::Ptr) ),
+ SIGNAL( startService(KService::Ptr) ) );
+ connect( mRightView, SIGNAL( startURL(const QString& ) ),
+ SIGNAL( startURL(const QString& ) ) );
+ connect( mRightView, SIGNAL( rightButtonPressed(QListViewItem*,const QPoint&,int) ),
+ SIGNAL( rightButtonPressed(QListViewItem*,const QPoint&,int) ) );
+
+ // wild hack to make sure it has correct width
+ mLeftView->setVScrollBarMode( QScrollView::AlwaysOn );
+ mRightView->setVScrollBarMode( QScrollView::AlwaysOn );
+ mLeftView->setVScrollBarMode( QScrollView::Auto );
+ mRightView->setVScrollBarMode( QScrollView::Auto );
+
+ mBackrow = new BackFrame( this );
+ mBackrow->resize( 24, 100 );
+ connect( mBackrow, SIGNAL( clicked() ), SIGNAL( backButtonClicked() ) );
+}
+
+ItemView* FlipScrollView::prepareRightMove()
+{
+ if ( mState != StoppedLeft )
+ {
+ mTimer->stop();
+ ItemView *swap = mLeftView;
+ mLeftView = mRightView;
+ mRightView = swap;
+ moveChild( mLeftView, 0, 0 );
+ moveChild( mRightView, width(), 0 );
+ mBackrow->hide();
+ mRightView->resize( width(), height() );
+ mLeftView->resize( width(), height() );
+ setContentsPos( 0, 0 );
+ }
+
+ mState = StoppedLeft;
+ mRightView->clear();
+ return mRightView;
+}
+
+void FlipScrollView::showBackButton( bool enable )
+{
+ kdDebug() << "FlipScrollView::showBackButton " << enable << endl;
+ mShowBack = enable;
+}
+
+ItemView* FlipScrollView::prepareLeftMove(bool clear)
+{
+ if ( mState != StoppedRight )
+ {
+ mTimer->stop();
+ ItemView *swap = mLeftView;
+ mLeftView = mRightView;
+ mRightView = swap;
+ moveChild( mLeftView, 0, 0 );
+ moveChild( mRightView, width(), 0 );
+ mRightView->resize( width(), height() );
+ mLeftView->resize( width(), height() );
+ mBackrow->hide();
+ setContentsPos( width(), 0 );
+ }
+
+ mState = StoppedRight;
+ if (clear)
+ mLeftView->clear();
+ return mLeftView;
+}
+
+void FlipScrollView::viewportResizeEvent ( QResizeEvent * )
+{
+ mLeftView->resize( size() );
+ mRightView->resize( width() - mBackrow->width(), height() );
+ mBackrow->resize( mBackrow->width(), height() );
+ resizeContents( width() * 2, height() );
+ moveChild( mBackrow, width(), 0 );
+ moveChild( mRightView, width() + mBackrow->width(), 0 );
+ setContentsPos( 0, 0 );
+}
+
+ItemView *FlipScrollView::currentView() const
+{
+ if ( mState == StoppedRight )
+ return mRightView;
+ else
+ return mLeftView;
+}
+
+ItemView *FlipScrollView::leftView() const
+{
+ return mLeftView;
+}
+
+ItemView *FlipScrollView::rightView() const
+{
+ return mRightView;
+}
+
+FlipScrollView::~FlipScrollView() {}
+
+static const int max_steps = 10;
+
+void FlipScrollView::slotScrollTimer()
+{
+ mStepsRemaining--;
+ assert( mStepsRemaining >= 0 && mStepsRemaining < int(sizeof( scrollSteps ) / sizeof( double )) );
+ if (KickerSettings::scrollFlipView())
+ scrollBy( ( int )( mScrollDirection * mLeftView->width() * scrollSteps[ mStepsRemaining ] ), 0 );
+ else
+ scrollBy( ( int )( mScrollDirection * mLeftView->width()), 0 );
+
+ if ( mStepsRemaining == 0 )
+ {
+ if ( mState == ScrollingRight )
+ {
+ mState = StoppedRight;
+ setContentsPos( width(), 0 );
+ } else {
+ mState = StoppedLeft;
+ setContentsPos( 0, 0 );
+ }
+
+ kdDebug() << "slotScrollTimer " << mShowBack << endl;
+
+ if ( mShowBack )
+ {
+ mBackrow->show();
+ if ( mState == StoppedRight )
+ {
+
+ if ( QApplication::reverseLayout() )
+ moveChild( mRightView, width(), 0 );
+ else
+ moveChild( mRightView, width() + mBackrow->width(), 0 );
+ mRightView->resize( width() - mBackrow->width(), height() );
+ mLeftView->resize( width(), height() );
+ if ( QApplication::reverseLayout() )
+ moveChild( mBackrow, width() + mRightView->width(), 0 );
+ else
+ moveChild( mBackrow, width(), 0 );
+ moveChild( mLeftView, 0, 0 );
+ } else
+ {
+ moveChild( mRightView, width(), 0 );
+ mRightView->resize( width(), height() );
+ mLeftView->resize( width() - mBackrow->width(), height() );
+ if ( QApplication::reverseLayout() )
+ {
+ moveChild( mBackrow, mLeftView->width(), 0 );
+ moveChild( mLeftView, 0, 0 );
+ }
+ else
+ {
+ moveChild( mBackrow, 0, 0 );
+ moveChild( mLeftView, mBackrow->width(), 0 );
+ }
+ }
+ } else
+ mBackrow->hide();
+
+ if (!mSelectMenuPath.isEmpty()) {
+ if (mSelectMenuPath=="kicker:/goup/") {
+ currentView()->setSelected(currentView()->firstChild(),true);
+ currentView()->firstChild()->repaint();
+ }
+ else {
+ QListViewItem * child = currentView()->firstChild();
+ while( child ) {
+ KMenuItem* kitem = dynamic_cast(child);
+ if (kitem && kitem->menuPath()==mSelectMenuPath) {
+ currentView()->setSelected(child,true);
+ kdDebug() << "child repaint\n";
+ child->repaint();
+ break;
+ }
+ child = child->nextSibling();
+ }
+ }
+ }
+ mLeftView->setVScrollBarMode( QScrollView::Auto );
+ mRightView->setVScrollBarMode( QScrollView::Auto );
+ mTimer->stop();
+ mLeftView->setMouseMoveSelects( true );
+ mRightView->setMouseMoveSelects( true );
+ }
+}
+
+void FlipScrollView::flipScroll(const QString& selectMenuPath)
+{
+ if ( mState == StoppedLeft )
+ {
+ mState = ScrollingRight;
+ mScrollDirection = 1;
+ }
+ else
+ {
+ mState = ScrollingLeft;
+ mScrollDirection = -1;
+ }
+
+ mLeftView->setVScrollBarMode( QScrollView::AlwaysOff );
+ mRightView->setVScrollBarMode( QScrollView::AlwaysOff );
+ if (KickerSettings::scrollFlipView())
+ mStepsRemaining = max_steps;
+ else
+ mStepsRemaining = 1;
+ mTimer->start( 30 );
+ mSelectMenuPath = selectMenuPath;
+ if (!mSelectMenuPath.isEmpty()) {
+ mLeftView->setMouseMoveSelects( false );
+ mRightView->setMouseMoveSelects( false );
+ }
+}
+
+#include "flipscrollview.moc"
--- kicker/ui/query.cpp (revision 0)
+++ kicker/ui/query.cpp (revision 774644)
@@ -0,0 +1,136 @@
+/*****************************************************************
+
+ Copyright (c) 2006 Stephan Binner
+
+ 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 "query.h"
+#include
+
+Query::Query()
+{
+ alternatives.setAutoDelete(true);
+}
+
+void Query::clear()
+{
+ query_term = QString::null;
+ alternatives.clear();
+}
+
+void Query::set(const QString &term)
+{
+ query_term = term;
+ alternatives.clear();
+
+ current_alternative = new Alternative;
+ current_part = QString::null;
+ within_quotes = false;
+ exclude_part = false;
+
+ for (uint index=0;indexexcludes+=current_part.lower();
+ else
+ current_alternative->includes+=current_part.lower();
+ }
+ within_quotes = false;
+ exclude_part = false;
+ current_part = QString::null;
+}
+
+QString Query::get() const
+{
+ return query_term;
+}
+
+bool Query::matches(const QString &term)
+{
+ QString lower_term = term.lower();
+
+ for (Alternative* alt=alternatives.first(); alt; alt=alternatives.next()) {
+ if (!alt->includes.count())
+ continue;
+
+ bool next_alternative = false;
+
+ for ( QStringList::ConstIterator it = alt->excludes.begin(); it != alt->excludes.end(); ++it ) {
+ if ( lower_term.find(*it)!=-1 ) {
+ next_alternative = true;
+ continue;
+ }
+ }
+ if (next_alternative)
+ continue;
+
+ for ( QStringList::ConstIterator it = alt->includes.begin(); it != alt->includes.end(); ++it ) {
+ if ( lower_term.find(*it)==-1 ) {
+ next_alternative = true;
+ continue;
+ }
+ }
+ if (next_alternative)
+ continue;
+
+//kdDebug() << "Found hit in '" << term << "'" << endl;
+ return true;
+ }
+
+ return false;
+}
--- kicker/ui/k_new_mnu.cpp (revision 0)
+++ kicker/ui/k_new_mnu.cpp (revision 774644)
@@ -0,0 +1,3779 @@
+/*****************************************************************
+
+ Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+ Copyright (c) 2006 Debajyoti Bera
+ Copyright (c) 2006 Dirk Mueller
+
+ 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
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "client_mnu.h"
+#include "container_base.h"
+#include "global.h"
+#include "knewbutton.h"
+#include "kicker.h"
+#include "kickerSettings.h"
+#include "konqbookmarkmanager.h"
+#include "menuinfo.h"
+#include "menumanager.h"
+#include "popupmenutitle.h"
+#include "quickbrowser_mnu.h"
+#include "recentapps.h"
+#include "flipscrollview.h"
+#include "itemview.h"
+#include
+#include
+#include
+
+#include "media_watcher.h"
+#include "k_mnu.h"
+#include "k_new_mnu.h"
+#include "k_new_mnu.moc"
+#include "kickoff_bar.h"
+
+#define WAIT_BEFORE_QUERYING 700
+
+#define IDS_PER_CATEGORY 20
+#define ACTIONS_ID_BASE 10
+#define APP_ID_BASE 10 + IDS_PER_CATEGORY
+#define BOOKMARKS_ID_BASE 10 + (IDS_PER_CATEGORY * 2)
+#define NOTES_ID_BASE 10 + (IDS_PER_CATEGORY * 3)
+#define MAIL_ID_BASE 10 + (IDS_PER_CATEGORY * 4)
+#define FILE_ID_BASE 10 + (IDS_PER_CATEGORY * 5)
+#define MUSIC_ID_BASE 10 + (IDS_PER_CATEGORY * 6)
+#define WEBHIST_ID_BASE 10 + (IDS_PER_CATEGORY * 7)
+#define CHAT_ID_BASE 10 + (IDS_PER_CATEGORY * 8)
+#define FEED_ID_BASE 10 + (IDS_PER_CATEGORY * 9)
+#define PIC_ID_BASE 10 + (IDS_PER_CATEGORY * 10)
+#define VIDEO_ID_BASE 10 + (IDS_PER_CATEGORY * 11)
+#define DOC_ID_BASE 10 + (IDS_PER_CATEGORY * 12)
+#define OTHER_ID_BASE 10 + (IDS_PER_CATEGORY * 13)
+
+static QString calculate(const QString &exp)
+{
+ QString result, cmd;
+ const QString bc = KStandardDirs::findExe("bc");
+ if ( !bc.isEmpty() )
+ cmd = QString("echo %1 | %2").arg(KProcess::quote(exp), KProcess::quote(bc));
+ else
+ cmd = QString("echo $((%1))").arg(exp);
+ FILE *fs = popen(QFile::encodeName(cmd).data(), "r");
+ if (fs)
+ {
+ QTextStream ts(fs, IO_ReadOnly);
+ result = ts.read().stripWhiteSpace();
+ pclose(fs);
+ }
+ return result;
+}
+
+static QString workaroundStringFreeze(const QString& str)
+{
+ QString s = str;
+
+ s.replace("","&");
+ QRegExp re("<[^>]+>");
+ re.setMinimal(true);
+ re.setCaseSensitive(false);
+
+ s.replace(re, "");
+ s = s.simplifyWhiteSpace();
+
+ return s;
+}
+
+int base_category_id[] = {ACTIONS_ID_BASE, APP_ID_BASE, BOOKMARKS_ID_BASE, NOTES_ID_BASE, MAIL_ID_BASE,
+ FILE_ID_BASE, MUSIC_ID_BASE, WEBHIST_ID_BASE, CHAT_ID_BASE, FEED_ID_BASE,
+ PIC_ID_BASE, VIDEO_ID_BASE, DOC_ID_BASE, OTHER_ID_BASE};
+
+#include
+
+static int used_size( QLabel *label, int oldsize )
+{
+ QSimpleRichText st( label->text(), KGlobalSettings::toolBarFont() );
+ st.setWidth( oldsize );
+ return QMAX( st.widthUsed(), oldsize );
+}
+
+KMenu::KMenu()
+ : KMenuBase(0, "SUSE::Kickoff::KMenu")
+ , m_sloppyTimer(0, "KNewMenu::sloppyTimer"), m_mediaFreeTimer(0, "KNewMenu::mediaFreeTimer"),
+ m_iconName(QString::null), m_orientation(UnDetermined), m_search_plugin( 0 )
+{
+ setMouseTracking(true);
+ connect(&m_sloppyTimer, SIGNAL(timeout()), SLOT(slotSloppyTimeout()));
+
+ // set the first client id to some arbitrarily large value.
+ client_id = 10000;
+ // Don't automatically clear the main menu.
+ actionCollection = new KActionCollection(this);
+
+ connect(Kicker::the(), SIGNAL(configurationChanged()),
+ this, SLOT(configChanged()));
+
+ KUser * user = new KUser();
+
+ char hostname[256];
+ hostname[0] = '\0';
+ if (!gethostname( hostname, sizeof(hostname) ))
+ hostname[sizeof(hostname)-1] = '\0';
+
+ m_userInfo->setText( i18n( "User %1 on %2" )
+ .arg( user->loginName() ).arg( hostname ) );
+ setupUi();
+
+ m_userInfo->setBackgroundMode( PaletteBase );
+ QColor userInfoColor = QApplication::palette().color( QPalette::Normal, QColorGroup::Mid );
+ if ( qGray( userInfoColor.rgb() ) > 120 )
+ userInfoColor = userInfoColor.dark( 200 );
+ else
+ userInfoColor = userInfoColor.light( 200 );
+ m_userInfo->setPaletteForegroundColor( userInfoColor );
+
+ m_tabBar = new KickoffTabBar(this, "m_tabBar");
+ connect(m_tabBar, SIGNAL(tabClicked(QTab*)), SLOT(tabClicked(QTab*)));
+
+ const int tab_icon_size = 32;
+
+ m_tabs[FavoriteTab] = new QTab;
+ m_tabBar->addTab(m_tabs[FavoriteTab]);
+ m_tabBar->setToolTip(FavoriteTab, "" + i18n( "Most commonly used applications and documents" ) + "" );
+ m_tabs[ApplicationsTab] = new QTab;
+ m_tabBar->addTab(m_tabs[ApplicationsTab]);
+ m_tabBar->setToolTip(ApplicationsTab, "" + i18n( "List of installed applications" ) +
+ "" );
+
+ m_tabs[ComputerTab] = new QTab;
+ m_tabBar->addTab(m_tabs[ComputerTab]);
+ m_tabBar->setToolTip(ComputerTab, "" + i18n( "Information and configuration of your "
+ "system, access to personal files, network resources and connected disk drives")
+ + "");
+#if 0
+ m_tabs[SearchTab] = new QTab;
+ m_tabBar->addTab(m_tabs[SearchTab]);
+#endif
+ m_tabs[HistoryTab] = new QTab;
+ m_tabBar->addTab(m_tabs[HistoryTab]);
+ m_tabBar->setToolTip(HistoryTab, "" + i18n( "Recently used applications and documents" ) +
+ "" );
+ m_tabs[LeaveTab] = new QTab;
+ m_tabBar->addTab(m_tabs[LeaveTab]);
+ m_tabBar->setToolTip(LeaveTab, i18n("Logout, switch user, switch off or reset,"
+ " suspend of the system" ) + "" );
+
+ if (KickerSettings::kickoffTabBarFormat() != KickerSettings::IconOnly) {
+ m_tabs[FavoriteTab]->setText(workaroundStringFreeze(i18n(" Favorites
")));
+ m_tabs[HistoryTab]->setText(workaroundStringFreeze(i18n("History
")));
+ m_tabs[ComputerTab]->setText(
+ workaroundStringFreeze(i18n(" Computer
")));
+ m_tabs[ApplicationsTab]->setText(workaroundStringFreeze(i18n("Applications
")));
+ m_tabs[LeaveTab]->setText(
+ workaroundStringFreeze(i18n("Leave
")));
+ }
+
+ if (KickerSettings::kickoffTabBarFormat() != KickerSettings::LabelOnly) {
+ m_tabs[FavoriteTab]->setIconSet(BarIcon("bookmark", tab_icon_size));
+ m_tabs[HistoryTab]->setIconSet(BarIcon("recently_used", tab_icon_size));
+ m_tabs[ComputerTab]->setIconSet(BarIcon("system", tab_icon_size));
+ m_tabs[ApplicationsTab]->setIconSet(BarIcon("player_playlist", tab_icon_size));
+ m_tabs[LeaveTab]->setIconSet(BarIcon("leave", tab_icon_size));
+ }
+
+ connect(m_tabBar, SIGNAL(selected(int)), m_stacker, SLOT(raiseWidget(int)));
+ connect(m_stacker, SIGNAL(aboutToShow(int)), m_tabBar, SLOT(setCurrentTab(int)));
+
+ m_favoriteView = new FavoritesItemView (m_stacker, "m_favoriteView");
+ m_favoriteView->setAcceptDrops(true);
+ m_favoriteView->setItemsMovable(true);
+ m_stacker->addWidget(m_favoriteView, FavoriteTab);
+
+ m_recentlyView = new ItemView (m_stacker, "m_recentlyView");
+ m_stacker->addWidget(m_recentlyView, HistoryTab);
+
+ m_systemView = new ItemView(m_stacker, "m_systemView");
+ m_stacker->addWidget(m_systemView, ComputerTab );
+
+ m_browserView = new FlipScrollView(m_stacker, "m_browserView");
+ m_stacker->addWidget(m_browserView, ApplicationsTab);
+ connect( m_browserView, SIGNAL( backButtonClicked() ), SLOT( slotGoBack() ) );
+
+ m_exitView = new FlipScrollView(m_stacker, "m_exitView");
+ m_stacker->addWidget(m_exitView, LeaveTab);
+ connect( m_exitView, SIGNAL( backButtonClicked() ), SLOT( slotGoExitMainMenu() ) );
+
+ m_searchWidget = new QVBox (m_stacker, "m_searchWidget");
+ m_searchWidget->setSpacing(0);
+ m_stacker->addWidget(m_searchWidget, 5);
+
+ // search provider icon
+ QPixmap icon;
+ KURIFilterData data;
+ QStringList list;
+ data.setData( QString("some keyword") );
+ list << "kurisearchfilter" << "kuriikwsfilter";
+
+ if ( KURIFilter::self()->filterURI(data, list) ) {
+ QString iconPath = locate("cache", KMimeType::favIconForURL(data.uri()) + ".png");
+ if ( iconPath.isEmpty() )
+ icon = SmallIcon("enhanced_browsing");
+ else
+ icon = QPixmap( iconPath );
+ }
+ else
+ icon = SmallIcon("enhanced_browsing");
+
+ m_searchResultsWidget = new ItemView (m_searchWidget, "m_searchResultsWidget");
+ m_searchResultsWidget->setItemMargin(4);
+ m_searchResultsWidget->setIconSize(16);
+ m_searchActions = new ItemView (m_searchWidget, "m_searchActions");
+ m_searchActions->setFocusPolicy(QWidget::NoFocus);
+ m_searchActions->setItemMargin(4);
+ m_searchInternet = new QListViewItem(m_searchActions, i18n("Search Internet"));
+ m_searchInternet->setPixmap(0,icon);
+ setTabOrder(m_kcommand, m_searchResultsWidget);
+
+ m_kerryInstalled = !KStandardDirs::findExe(QString::fromLatin1("kerry")).isEmpty();
+ m_isShowing = false;
+
+ if (!m_kerryInstalled) {
+ m_searchIndex = 0;
+ m_searchActions->setMaximumHeight(5+m_searchInternet->height());
+ }
+ else {
+ m_searchIndex = new QListViewItem(m_searchActions, i18n("Search Index"));
+ m_searchIndex->setPixmap(0,SmallIcon("kerry"));
+ m_searchActions->setMaximumHeight(5+m_searchIndex->height()*2);
+ }
+ connect(m_searchActions, SIGNAL(clicked(QListViewItem*)), SLOT(searchActionClicked(QListViewItem*)));
+ connect(m_searchActions, SIGNAL(returnPressed(QListViewItem*)), SLOT(searchActionClicked(QListViewItem*)));
+ connect(m_searchActions, SIGNAL(spacePressed(QListViewItem*)), SLOT(searchActionClicked(QListViewItem*)));
+
+ connect(m_searchResultsWidget, SIGNAL(startService(KService::Ptr)), SLOT(slotStartService(KService::Ptr)));
+ connect(m_searchResultsWidget, SIGNAL(startURL(const QString&)), SLOT(slotStartURL(const QString&)));
+ connect(m_searchResultsWidget, SIGNAL(rightButtonPressed( QListViewItem*, const QPoint &, int )), SLOT(slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
+
+ connect(m_recentlyView, SIGNAL(startService(KService::Ptr)), SLOT(slotStartService(KService::Ptr)));
+ connect(m_recentlyView, SIGNAL(startURL(const QString&)), SLOT(slotStartURL(const QString&)));
+ connect(m_recentlyView, SIGNAL(rightButtonPressed( QListViewItem*, const QPoint &, int )), SLOT(slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
+
+ connect(m_favoriteView, SIGNAL(startService(KService::Ptr)), SLOT(slotStartService(KService::Ptr)));
+ connect(m_favoriteView, SIGNAL(startURL(const QString&)), SLOT(slotStartURL(const QString&)));
+ connect(m_favoriteView, SIGNAL(rightButtonPressed( QListViewItem*, const QPoint &, int )), SLOT(slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
+ connect(m_favoriteView, SIGNAL(moved(QListViewItem*, QListViewItem*, QListViewItem*)), SLOT(slotFavoritesMoved( QListViewItem*, QListViewItem*, QListViewItem* )));
+
+ connect(m_systemView, SIGNAL(startURL(const QString&)), SLOT(slotStartURL(const QString&)));
+ connect(m_systemView, SIGNAL(startService(KService::Ptr)), SLOT(slotStartService(KService::Ptr)));
+ connect(m_systemView, SIGNAL(rightButtonPressed( QListViewItem*, const QPoint &, int )), SLOT(slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
+
+ connect(m_browserView, SIGNAL(startURL(const QString&)), SLOT(slotGoSubMenu(const QString&)));
+ connect(m_browserView, SIGNAL(startService(KService::Ptr)), SLOT(slotStartService(KService::Ptr)));
+ connect(m_browserView, SIGNAL(rightButtonPressed( QListViewItem*, const QPoint &, int )), SLOT(slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
+
+ connect(m_exitView, SIGNAL(startURL(const QString&)), SLOT(slotStartURL(const QString&)));
+ connect(m_exitView, SIGNAL(rightButtonPressed( QListViewItem*, const QPoint &, int )), SLOT(slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
+
+ m_kcommand->setDuplicatesEnabled( false );
+ m_kcommand->setLineEdit(new KLineEdit(m_kcommand, "m_kcommand-lineedit"));
+ m_kcommand->setCompletionMode( KGlobalSettings::CompletionAuto );
+ connect(m_kcommand, SIGNAL(cleared()), SLOT(clearedHistory()));
+ connect(m_kcommand->lineEdit(), SIGNAL(returnPressed()), SLOT(searchAccept()));
+ connect(m_kcommand->lineEdit(), SIGNAL(textChanged(const QString &)), SLOT(searchChanged(const QString &)));
+
+ // URI Filter meta object...
+ m_filterData = new KURIFilterData();
+
+ max_category_id = new int [num_categories];
+ categorised_hit_total = new int [num_categories];
+
+ input_timer = new QTimer (this, "input_timer");
+ connect( input_timer, SIGNAL(timeout()), this, SLOT(doQuery()) );
+
+ init_search_timer = new QTimer (this, "init_search_timer");
+ connect( init_search_timer, SIGNAL(timeout()), this, SLOT(initSearch()) );
+ init_search_timer->start(2000, true);
+
+ connect( m_favoriteView, SIGNAL( dropped (QDropEvent *, QListViewItem * ) ),
+ SLOT( slotFavDropped( QDropEvent *, QListViewItem * ) ) );
+
+ this->installEventFilter(this);
+ m_tabBar->installEventFilter(this);
+ m_favoriteView->installEventFilter(this);
+ m_recentlyView->installEventFilter(this);
+ m_browserView->leftView()->installEventFilter(this);
+ m_browserView->rightView()->installEventFilter(this);
+ m_systemView->installEventFilter(this);
+ m_exitView->leftView()->installEventFilter(this);
+ m_exitView->rightView()->installEventFilter(this);
+ m_kcommand->lineEdit()->installEventFilter(this);
+ m_searchLabel->installEventFilter(this);
+ m_searchPixmap->installEventFilter(this);
+ m_stacker->installEventFilter(this);
+
+ emailRegExp = QRegExp("^([\\w\\-]+\\.)*[\\w\\-]+@([\\w\\-]+\\.)*[\\w\\-]+$");
+ authRegExp = QRegExp("^[a-zA-Z]+://\\w+(:\\w+)?@([\\w\\-]+\\.)*[\\w\\-]+(:\\d+)?(/.*)?$");
+ uriRegExp = QRegExp("^[a-zA-Z]+://([\\w\\-]+\\.)*[\\w\\-]+(:\\d+)?(/.*)?$");
+ uri2RegExp = QRegExp("^([\\w\\-]+\\.)+[\\w\\-]+(:\\d+)?(/.*)?$");
+
+ m_resizeHandle = new QLabel(this);
+ m_resizeHandle->setBackgroundOrigin( QLabel::ParentOrigin );
+ m_resizeHandle->setScaledContents(true);
+ m_resizeHandle->setFixedSize( 16, 16 );
+ m_searchFrame->stackUnder( m_resizeHandle );
+ m_isresizing = false;
+
+ m_searchPixmap->setPixmap( BarIcon( "find", 32 ) );
+
+ QFont f = font();
+ f.setPointSize( kMax( 7, (f.pointSize() * 4 / 5 ) + KickerSettings::kickoffFontPointSizeOffset() ) );
+ m_tabBar->setFont ( f );
+ f.setPointSize( kMax( 7, (f.pointSize() * 3 / 2 ) + KickerSettings::kickoffFontPointSizeOffset() ) );
+ m_searchLabel->setFont( f );
+
+ static_cast(m_kcommand->lineEdit())->setClickMessage(i18n( "Applications, Contacts and Documents" ) );
+
+ bookmarkManager = 0;
+ m_addressBook = 0;
+ m_popupMenu = 0;
+
+ main_border_tl.load( locate("data", "kicker/pics/main_corner_tl.png" ) );
+ main_border_tr.load( locate("data", "kicker/pics/main_corner_tr.png" ) );
+
+ search_tab_left.load( locate("data", "kicker/pics/search-tab-left.png" ) );
+ search_tab_right.load( locate("data", "kicker/pics/search-tab-right.png" ) );
+ search_tab_center.load( locate("data", "kicker/pics/search-tab-center.png" ) );
+
+ search_tab_top_left.load( locate("data", "kicker/pics/search-tab-top-left.png" ) );
+ search_tab_top_right.load( locate("data", "kicker/pics/search-tab-top-right.png" ) );
+ search_tab_top_center.load( locate("data", "kicker/pics/search-tab-top-center.png" ) );
+}
+
+void KMenu::setupUi()
+{
+ m_stacker = new QWidgetStack( this, "m_stacker" );
+ m_stacker->setGeometry( QRect( 90, 260, 320, 220 ) );
+ m_stacker->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)3, (QSizePolicy::SizeType)3, 1, 1, m_stacker->sizePolicy().hasHeightForWidth() ) );
+ m_stacker->setPaletteBackgroundColor( QColor( 255, 255, 255 ) );
+ // m_stacker->setFocusPolicy( QWidget::StrongFocus );
+ m_stacker->setLineWidth( 0 );
+ m_stacker->setFocusPolicy(QWidget::NoFocus);
+ connect(m_stacker, SIGNAL(aboutToShow(QWidget*)), SLOT(stackWidgetRaised(QWidget*)));
+
+ m_kcommand->setName("m_kcommand");
+}
+
+KMenu::~KMenu()
+{
+ saveConfig();
+
+ clearSubmenus();
+ delete m_filterData;
+}
+
+bool KMenu::eventFilter ( QObject * receiver, QEvent* e)
+{
+//kdDebug() << "eventFilter receiver=" << receiver->name() << " type=" << e->type() << endl;
+ QWidget* raiseWidget = 0;
+ QRect raiseRect;
+
+ if (e->type() == QEvent::KeyPress ||
+ e->type() == QEvent::MouseButtonPress ||
+ e->type() == QEvent::MouseMove
+ || e->type() == QEvent::FocusIn
+ || e->type() == QEvent::Wheel) {
+ QPoint p;
+
+ if (e->type() == QEvent::MouseMove || e->type() == QEvent::MouseButtonPress) {
+ QMouseEvent* me = static_cast(e);
+ p = me->globalPos();
+ }
+ else if (e->type() == QEvent::Wheel) {
+ QWheelEvent* we = static_cast(e);
+ p = we->globalPos();
+ }
+
+ while (receiver) {
+ if (receiver == m_tabBar && (e->type()!=QEvent::MouseMove || KickerSettings::kickoffSwitchTabsOnHover() ) ) {
+ QTab* s = m_tabBar->selectTab(m_tabBar->mapFromGlobal(p));
+ if (s && s->identifier() == ApplicationsTab)
+ raiseWidget = m_browserView;
+ if (s && s->identifier() == FavoriteTab)
+ raiseWidget = m_favoriteView;
+ if (s && s->identifier() == HistoryTab)
+ raiseWidget = m_recentlyView;
+ if (s && s->identifier() == ComputerTab)
+ raiseWidget = m_systemView;
+ if (s && s->identifier() == LeaveTab)
+ raiseWidget = m_exitView;
+
+ if (raiseWidget)
+ raiseRect = QRect( m_tabBar->mapToGlobal(s->rect().topLeft()),
+ s->rect().size());
+ }
+
+ /* we do not want hover activation for the search line edit as this can be
+ * pretty disturbing */
+ if ( (receiver == m_searchPixmap ||
+ ( ( receiver == m_searchLabel || receiver==m_kcommand->lineEdit() ) &&
+ ( e->type() == QEvent::KeyPress || e->type() == QEvent::Wheel
+ || e->type() == QEvent::MouseButtonPress ) ) ) &&
+ !m_isShowing) {
+ raiseWidget = m_searchWidget;
+ raiseRect = QRect( m_searchFrame->mapToGlobal(m_searchFrame->rect().topLeft()),
+ m_searchFrame->size());
+ }
+
+ if(raiseWidget)
+ break;
+ if(receiver->isWidgetType())
+ receiver = static_cast(receiver)->parentWidget(true);
+ else
+ break;
+ }
+
+ if (e->type() == QEvent::FocusIn && receiver && raiseWidget) {
+ m_searchResultsWidget->setFocusPolicy(QWidget::StrongFocus);
+ m_searchActions->setFocusPolicy(raiseWidget == m_searchWidget ?
+ QWidget::StrongFocus : QWidget::NoFocus);
+ setTabOrder(raiseWidget, m_searchResultsWidget);
+ if (raiseWidget != m_stacker->visibleWidget()
+ && static_cast(receiver)->focusPolicy() == QWidget::NoFocus
+ && m_stacker->id(raiseWidget) >= 0) {
+
+ m_stacker->raiseWidget(raiseWidget);
+ return true;
+ }
+
+ if (raiseWidget->focusPolicy() != QWidget::NoFocus)
+ return false;
+ }
+
+ if (m_sloppyRegion.contains(p)) {
+ if (e->type() == QEvent::MouseButtonPress /*&& m_sloppyTimer.isActive()*/)
+ m_sloppySourceClicked = true;
+
+ if (!m_sloppyTimer.isActive() || m_sloppySource != raiseRect) {
+ int timeout= style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay);
+ if (m_sloppySourceClicked)
+ timeout = 3000;
+ m_sloppyTimer.start(timeout);
+ }
+
+ m_sloppyWidget = raiseWidget;
+ m_sloppySource = raiseRect;
+ return false;
+ }
+ }
+
+ if(e->type() == QEvent::Enter && receiver->isWidgetType()) {
+ static_cast(receiver)->setMouseTracking(true);
+ QToolTip::hide();
+ }
+
+ if ( ( e->type() == QEvent::DragEnter || e->type() == QEvent::DragMove ) &&
+ raiseWidget == m_favoriteView )
+ {
+ m_stacker->raiseWidget(m_favoriteView);
+
+ return false;
+ }
+
+ // This is a nightmare of a hack, look away. Logic needs
+ // to be moved to the stacker and all widgets in the stacker
+ // must have focusNextPrevChild() overwritten to do nothing
+ if (e->type() == QEvent::KeyPress && !raiseRect.isNull()) {
+ ItemView* view;
+ if (m_browserView==m_stacker->visibleWidget())
+ view = m_browserView->currentView();
+ else if (m_exitView==m_stacker->visibleWidget())
+ view = m_exitView->currentView();
+ else
+ view = dynamic_cast(m_stacker->visibleWidget());
+
+ if (view)
+ {
+ bool handled = true;
+ switch (static_cast(e)->key()) {
+ case Key_Up:
+ if (view->selectedItem()) {
+ view->setSelected(view->selectedItem()->itemAbove(),true);
+ }
+ else {
+ view->setSelected(view->lastItem(),true);
+ }
+ break;
+ case Key_Down:
+ if (view->selectedItem()) {
+ view->setSelected(view->selectedItem()->itemBelow(),true);
+ }
+ else {
+ if (view->firstChild() && view->firstChild()->isSelectable())
+ view->setSelected(view->firstChild(),true);
+ else if (view->childCount()>2)
+ view->setSelected(view->firstChild()->itemBelow(),true);
+ }
+ break;
+ case Key_Right:
+ if (view->selectedItem() && !static_cast(view->selectedItem())->hasChildren())
+ break;
+ // nobreak
+ case Key_Enter:
+ case Key_Return:
+ if (view->selectedItem())
+ view->slotItemClicked(view->selectedItem());
+
+ break;
+ case Key_Left:
+ if (m_browserView == m_stacker->visibleWidget() || m_exitView == m_stacker->visibleWidget()) {
+ FlipScrollView* flip = dynamic_cast(m_stacker->visibleWidget());
+ if (flip->showsBackButton()) {
+ if (m_browserView == m_stacker->visibleWidget())
+ goSubMenu( m_browserView->currentView()->backPath(), true );
+ else
+ view->slotItemClicked(view->firstChild());
+ }
+ break;
+ }
+ // nobreak
+ case Key_Backspace:
+ if (m_browserView == m_stacker->visibleWidget() || m_exitView == m_stacker->visibleWidget()) {
+ FlipScrollView* flip = dynamic_cast(m_stacker->visibleWidget());
+ if (flip->showsBackButton()) {
+ if (m_browserView == m_stacker->visibleWidget())
+ goSubMenu( m_browserView->currentView()->backPath(), true );
+ else
+ view->slotItemClicked(view->firstChild());
+ }
+ }
+
+ break;
+ default:
+ handled = false;
+ }
+
+ if (handled)
+ view->ensureItemVisible(view->selectedItem());
+
+ return handled;
+ }
+ }
+
+ bool r = KMenuBase::eventFilter(receiver, e);
+
+ if (!r && raiseWidget)
+ m_stacker->raiseWidget(raiseWidget);
+
+ if (e->type() == QEvent::Wheel && raiseWidget )
+ {
+ // due to an ugly Qt bug we have to kill wheel events
+ // that cause focus switches
+ r = true;
+ }
+
+ if (e->type() == QEvent::Enter && receiver == m_stacker)
+ {
+ QRect r(m_stacker->mapToGlobal(QPoint(-8,-32)), m_stacker->size());
+ r.setSize(r.size()+QSize(16,128));
+
+ m_sloppyRegion = QRegion(r);
+ }
+
+ // redo the sloppy region
+ if (e->type() == QEvent::MouseMove && !r && raiseWidget)
+ {
+ QPointArray points(4);
+
+ // hmm, eventually this should be mouse position + 10px, not
+ // just worst case. but worst case seems to work fine enough.
+ QPoint edge(raiseRect.topLeft());
+ edge.setX(edge.x()+raiseRect.center().x());
+
+ if (m_orientation == BottomUp)
+ {
+ points.setPoint(0, m_stacker->mapToGlobal(m_stacker->rect().bottomLeft()));
+ points.setPoint(1, m_stacker->mapToGlobal(m_stacker->rect().bottomRight()));
+
+ edge.setY(edge.y()+raiseRect.height());
+ points.setPoint(2, edge+QPoint(+raiseRect.width()/4,0));
+ points.setPoint(3, edge+QPoint(-raiseRect.width()/4,0));
+ }
+ else
+ {
+ points.setPoint(0, m_stacker->mapToGlobal(m_stacker->rect().topLeft()));
+ points.setPoint(1, m_stacker->mapToGlobal(m_stacker->rect().topRight()));
+ points.setPoint(2, edge+QPoint(-raiseRect.width()/4,0));
+ points.setPoint(3, edge+QPoint(+raiseRect.width()/4,0));
+ }
+
+ m_sloppyRegion = QRegion(points);
+ }
+
+ return r;
+}
+
+void KMenu::slotSloppyTimeout()
+{
+ if (m_sloppyRegion.contains(QCursor::pos()) && !m_sloppySource.isNull())
+ {
+ if ( m_sloppySource.contains(QCursor::pos()))
+ {
+ m_stacker->raiseWidget(m_sloppyWidget);
+
+ m_sloppyWidget = 0;
+ m_sloppySource = QRect();
+ m_sloppyRegion = QRegion();
+ m_sloppySourceClicked = false;
+ }
+ }
+ m_sloppyTimer.stop();
+}
+
+void KMenu::paintSearchTab( bool active )
+{
+ QPixmap canvas( m_searchFrame->size() );
+ QPainter p( &canvas );
+
+ QPixmap pix;
+
+ if ( m_orientation == BottomUp )
+ pix.load( locate("data", "kicker/pics/search-gradient.png" ) );
+ else
+ pix.load( locate("data", "kicker/pics/search-gradient-topdown.png" ) );
+
+ pix.convertFromImage( pix.convertToImage().scale(pix.width(), m_searchFrame->height()));
+ p.drawTiledPixmap( 0, 0, m_searchFrame->width(), m_searchFrame->height(), pix );
+
+ if ( active ) {
+
+ m_tabBar->deactivateTabs(true);
+
+ p.setBrush( Qt::white );
+ p.setPen( Qt::NoPen );
+
+ if ( m_orientation == BottomUp ) {
+ search_tab_center.convertFromImage( search_tab_center.convertToImage().scale(search_tab_center.width(), m_searchFrame->height()));
+ p.drawTiledPixmap( search_tab_left.width(), 0, m_searchFrame->width()-search_tab_left.width()-search_tab_right.width(), m_searchFrame->height(), search_tab_center );
+
+ search_tab_left.convertFromImage( search_tab_left.convertToImage().scale(search_tab_left.width(), m_searchFrame->height()));
+ p.drawPixmap( 0, 0, search_tab_left );
+
+ search_tab_right.convertFromImage( search_tab_right.convertToImage().scale(search_tab_right.width(), m_searchFrame->height()));
+ p.drawPixmap( m_searchFrame->width()-search_tab_right.width(), 0, search_tab_right );
+ }
+ else {
+ search_tab_top_center.convertFromImage( search_tab_top_center.convertToImage().scale(search_tab_top_center.width(), m_searchFrame->height()));
+ p.drawTiledPixmap( search_tab_top_left.width(), 0, m_searchFrame->width()-search_tab_top_left.width()-search_tab_top_right.width(), m_searchFrame->height(), search_tab_top_center );
+
+ search_tab_top_left.convertFromImage( search_tab_top_left.convertToImage().scale(search_tab_top_left.width(), m_searchFrame->height()));
+ p.drawPixmap( 0, 0, search_tab_top_left );
+
+ search_tab_top_right.convertFromImage( search_tab_top_right.convertToImage().scale(search_tab_top_right.width(), m_searchFrame->height()));
+ p.drawPixmap( m_searchFrame->width()-search_tab_top_right.width(), 0, search_tab_top_right );
+ }
+ }
+ else
+ m_tabBar->deactivateTabs(false);
+
+ p.end();
+ m_searchFrame->setPaletteBackgroundPixmap( canvas );
+}
+
+void KMenu::stackWidgetRaised(QWidget* raiseWidget)
+{
+ paintSearchTab(raiseWidget == m_searchWidget);
+
+ if (raiseWidget == m_browserView) {
+ if ( m_tabBar->currentTab() == ApplicationsTa