2 Copyright 2007 Robert Knight <robertknight@gmail.com>
3 Copyright 2007 Kevin Ottens <ervin@kde.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #include "ui/launcher.h"
27 #include <QApplication>
30 #include <QMouseEvent>
32 #include <QStackedWidget>
34 #include <QToolButton>
35 #include <QVBoxLayout>
36 #include <QStyleOptionSizeGrip>
40 #include <KLocalizedString>
42 #include <KStandardDirs>
44 #include <Plasma/Theme>
45 #include <Plasma/Delegate>
46 #include <solid/device.h>
47 #include <solid/deviceinterface.h>
48 #include <KColorScheme>
51 #include "core/favoritesmodel.h"
52 #include "core/recentlyusedmodel.h"
53 #include "core/applicationmodel.h"
54 #include "core/leavemodel.h"
55 #include "core/itemhandlers.h"
56 #include "core/searchmodel.h"
57 #include "core/systemmodel.h"
59 #include "ui/itemdelegate.h"
60 #include "ui/brandingbutton.h"
61 #include "ui/contextmenufactory.h"
62 #include "ui/urlitemview.h"
63 #include "ui/flipscrollview.h"
64 #include "ui/searchbar.h"
65 #include "ui/tabbar.h"
66 #include "ui/contentareacap.h"
68 using namespace Kickoff
;
70 class Launcher::Private
73 Private(Launcher
*launcher
)
76 , urlLauncher(new UrlItemLauncher(launcher
))
81 , contentAreaHeader(0)
83 , contentAreaFooter(0)
87 , contextMenuFactory(0)
89 , visibleItemCount(10)
90 , placement(Plasma::TopPosedLeftAlignedPopup
)
91 , panelEdge(Plasma::BottomEdge
) {
97 enum TabOrder
{ NormalTabOrder
, ReverseTabOrder
};
99 void setupEventHandler(QAbstractItemView
*view
) {
100 view
->viewport()->installEventFilter(q
);
101 view
->installEventFilter(q
);
104 void addView(const QString
& name
, const QIcon
& icon
,
105 QAbstractItemModel
*model
= 0, QAbstractItemView
*view
= 0) {
106 view
->setFrameStyle(QFrame::NoFrame
);
107 // prevent the view from stealing focus from the search bar
108 view
->setFocusPolicy(Qt::NoFocus
);
109 view
->setContextMenuPolicy(Qt::CustomContextMenu
);
110 view
->setSelectionMode(QAbstractItemView::SingleSelection
);
111 view
->setDragEnabled(true);
112 view
->setAcceptDrops(true);
113 view
->setDropIndicatorShown(true);
114 if (name
== "Favorites") {
115 view
->setDragDropMode(QAbstractItemView::DragDrop
);
116 } else if(name
== "Applications" || name
== "Computer" ||
117 name
== "Recently Used") {
118 view
->setDragDropMode(QAbstractItemView::DragOnly
);
120 view
->setModel(model
);
121 //view->setCurrentIndex(QModelIndex());
122 setupEventHandler(view
);
124 connect(view
, SIGNAL(customContextMenuRequested(QPoint
)), q
, SLOT(showViewContextMenu(QPoint
)));
126 contentSwitcher
->addTab(icon
, name
);
127 contentArea
->addWidget(view
);
132 setupFavoritesView();
135 setupAllProgramsView();
140 // Recently Used view
150 void setupLeaveView() {
151 leaveModel
= new LeaveModel(q
);
152 leaveModel
->updateModel();
153 UrlItemView
*view
= new UrlItemView();
154 ItemDelegate
*delegate
= new ItemDelegate(q
);
155 delegate
->setRoleMapping(Plasma::Delegate::SubTitleRole
, SubTitleRole
);
156 delegate
->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole
, SubTitleMandatoryRole
);
157 view
->setItemDelegate(delegate
);
158 view
->setItemStateProvider(delegate
);
159 addView(i18n("Leave"), KIcon("system-shutdown"), leaveModel
, view
);
162 void setupFavoritesView() {
163 FavoritesModel
*model
= new FavoritesModel(q
);
164 UrlItemView
*view
= new UrlItemView();
165 ItemDelegate
*delegate
= new ItemDelegate(q
);
166 delegate
->setRoleMapping(Plasma::Delegate::SubTitleRole
, SubTitleRole
);
167 delegate
->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole
, SubTitleMandatoryRole
);
168 view
->setItemDelegate(delegate
);
169 view
->setItemStateProvider(delegate
);
170 addView(i18n("Favorites"), KIcon("bookmarks"), model
, view
);
172 QAction
*sortAscendingAction
= new QAction(KIcon("view-sort-ascending"),
173 i18n("Sort Alphabetically (A to Z)"), q
);
175 QAction
*sortDescendingAction
= new QAction(KIcon("view-sort-descending"),
176 i18n("Sort Alphabetically (Z to A)"), q
);
179 connect(model
, SIGNAL(rowsInserted(QModelIndex
, int, int)), q
, SLOT(focusFavoritesView()));
180 connect(sortAscendingAction
, SIGNAL(triggered()), model
, SLOT(sortFavoritesAscending()));
181 connect(sortDescendingAction
, SIGNAL(triggered()), model
, SLOT(sortFavoritesDescending()));
183 favoritesView
= view
;
184 QList
<QAction
*> actions
;
185 actions
<< sortAscendingAction
<< sortDescendingAction
;
186 contextMenuFactory
->setViewActions(view
, actions
);
189 void setupAllProgramsView() {
190 ApplicationModel
*applicationModel
= new ApplicationModel(q
);
191 applicationModel
->setDuplicatePolicy(ApplicationModel::ShowLatestOnlyPolicy
);
193 applicationView
= new FlipScrollView();
194 ItemDelegate
*delegate
= new ItemDelegate(q
);
195 delegate
->setRoleMapping(Plasma::Delegate::SubTitleRole
, SubTitleRole
);
196 delegate
->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole
, SubTitleMandatoryRole
);
197 applicationView
->setItemDelegate(delegate
);
199 addView(i18n("Applications"), KIcon("applications-other"),
200 applicationModel
, applicationView
);
203 void setupRecentView() {
204 RecentlyUsedModel
*model
= new RecentlyUsedModel(q
);
205 UrlItemView
*view
= new UrlItemView();
206 ItemDelegate
*delegate
= new ItemDelegate(q
);
207 delegate
->setRoleMapping(Plasma::Delegate::SubTitleRole
, SubTitleRole
);
208 delegate
->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole
, SubTitleMandatoryRole
);
209 view
->setItemDelegate(delegate
);
210 view
->setItemStateProvider(delegate
);
211 addView(i18n("Recently Used"), KIcon("document-open-recent"), model
, view
);
213 QAction
*clearApplications
= new QAction(KIcon("edit-clear-history"), i18n("Clear Recent Applications"), q
);
214 QAction
*clearDocuments
= new QAction(KIcon("edit-clear-history"), i18n("Clear Recent Documents"), q
);
216 connect(clearApplications
, SIGNAL(triggered()), model
, SLOT(clearRecentApplications()));
217 connect(clearDocuments
, SIGNAL(triggered()), model
, SLOT(clearRecentDocuments()));
219 contextMenuFactory
->setViewActions(view
, QList
<QAction
*>() << clearApplications
<< clearDocuments
);
222 void setupSystemView() {
223 SystemModel
*model
= new SystemModel(q
);
224 UrlItemView
*view
= new UrlItemView();
225 ItemDelegate
*delegate
= new ItemDelegate(q
);
226 delegate
->setRoleMapping(Plasma::Delegate::SubTitleRole
, SubTitleRole
);
227 delegate
->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole
, SubTitleMandatoryRole
);
228 view
->setItemDelegate(delegate
);
229 view
->setItemStateProvider(delegate
);
231 addView(i18n("Computer"), systemIcon(), model
, view
);
234 void setupSearchView() {
235 searchModel
= new SearchModel(q
);
236 UrlItemView
*view
= new UrlItemView();
237 ItemDelegate
*delegate
= new ItemDelegate(q
);
238 delegate
->setRoleMapping(Plasma::Delegate::SubTitleRole
, SubTitleRole
);
239 delegate
->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole
, SubTitleMandatoryRole
);
240 view
->setItemDelegate(delegate
);
241 view
->setItemStateProvider(delegate
);
242 view
->setModel(searchModel
);
243 view
->setFrameStyle(QFrame::NoFrame
);
244 // prevent view from stealing focus from the search bar
245 view
->setFocusPolicy(Qt::NoFocus
);
246 view
->setDragEnabled(true);
247 setupEventHandler(view
);
249 connect(searchModel
, SIGNAL(resultsAvailable()), q
, SLOT(resultsAvailable()));
251 connect(searchBar
, SIGNAL(queryChanged(QString
)), searchModel
, SLOT(setQuery(QString
)));
252 connect(searchBar
, SIGNAL(queryChanged(QString
)), q
, SLOT(focusSearchView(QString
)));
254 view
->setContextMenuPolicy(Qt::CustomContextMenu
);
255 connect(view
, SIGNAL(customContextMenuRequested(QPoint
)), q
, SLOT(showViewContextMenu(QPoint
)));
257 contentArea
->addWidget(view
);
261 void registerUrlHandlers() {
262 UrlItemLauncher::addGlobalHandler(UrlItemLauncher::ExtensionHandler
, "desktop", new ServiceItemHandler
);
263 UrlItemLauncher::addGlobalHandler(UrlItemLauncher::ProtocolHandler
, "leave", new LeaveItemHandler
);
267 QList
<Solid::Device
> batteryList
= Solid::Device::listFromType(Solid::DeviceInterface::Battery
, QString());
269 if (batteryList
.isEmpty()) {
270 return KIcon("computer");
272 return KIcon("computer-laptop");
276 void setNorthLayout(TabOrder tabOrder
) {
277 contentSwitcher
->setShape(QTabBar::RoundedNorth
);
278 QLayout
* layout
= q
->layout();
280 layout
= new QVBoxLayout();
281 layout
->addWidget(contentSwitcher
);
282 layout
->addWidget(contentAreaHeader
);
283 layout
->addWidget(contentArea
);
284 layout
->addWidget(contentAreaFooter
);
285 layout
->addWidget(searchBar
);
286 layout
->addWidget(footer
);
287 layout
->setSpacing(0);
288 layout
->setMargin(0);
289 q
->setLayout(layout
);
290 setTabOrder(tabOrder
);
293 void setSouthLayout(TabOrder tabOrder
) {
294 contentSwitcher
->setShape(QTabBar::RoundedSouth
);
295 QLayout
* layout
= q
->layout();
297 layout
= new QVBoxLayout();
298 layout
->addWidget(footer
);
299 layout
->addWidget(searchBar
);
300 layout
->addWidget(contentAreaHeader
);
301 layout
->addWidget(contentArea
);
302 layout
->addWidget(contentAreaFooter
);
303 layout
->addWidget(contentSwitcher
);
304 layout
->setSpacing(0);
305 layout
->setMargin(0);
306 q
->setLayout(layout
);
307 setTabOrder(tabOrder
);
310 void setWestLayout(TabOrder tabOrder
) {
311 contentSwitcher
->setShape(QTabBar::RoundedWest
);
312 QLayout
* layout
= q
->layout();
314 layout
= new QHBoxLayout();
315 layout
->addWidget(contentSwitcher
);
316 layout
->addWidget(contentArea
);
317 QBoxLayout
* layout2
= new QVBoxLayout();
318 if (tabOrder
== NormalTabOrder
) {
319 layout2
->addLayout(layout
);
320 layout2
->addWidget(searchBar
);
321 layout2
->addWidget(footer
);
323 layout2
->addWidget(footer
);
324 layout2
->addWidget(searchBar
);
325 layout2
->addLayout(layout
);
327 layout
->setSpacing(0);
328 layout
->setMargin(0);
329 layout2
->setSpacing(0);
330 layout2
->setMargin(0);
331 q
->setLayout(layout2
);
332 setTabOrder(tabOrder
);
335 void setEastLayout(TabOrder tabOrder
) {
336 contentSwitcher
->setShape(QTabBar::RoundedEast
);
337 QLayout
* layout
= q
->layout();
339 layout
= new QHBoxLayout();
340 layout
->addWidget(contentArea
);
341 layout
->addWidget(contentSwitcher
);
342 QBoxLayout
* layout2
= new QVBoxLayout();
343 if (tabOrder
== NormalTabOrder
) {
344 layout2
->addLayout(layout
);
345 layout2
->addWidget(searchBar
);
346 layout2
->addWidget(footer
);
348 layout2
->addWidget(footer
);
349 layout2
->addWidget(searchBar
);
350 layout2
->addLayout(layout
);
352 layout
->setSpacing(0);
353 layout
->setMargin(0);
354 layout2
->setSpacing(0);
355 layout2
->setMargin(0);
356 q
->setLayout(layout2
);
357 setTabOrder(tabOrder
);
360 void setTabOrder(TabOrder newOrder
) {
361 // identify current TabOrder, assumes favoritesView is first in normal order
363 if (contentArea
->widget(0) == favoritesView
) {
364 oldOrder
= NormalTabOrder
;
366 oldOrder
= ReverseTabOrder
;
368 if (newOrder
== oldOrder
) {
371 // remove the and widgets and store their data in a separate structure
372 // remove this first so we can cleanly remove the widgets controlled by contentSwitcher
373 contentArea
->removeWidget(searchView
);
374 Q_ASSERT(contentArea
->count() == contentSwitcher
->count());
376 QList
<WidgetTabData
> removedTabs
;
377 for (int i
= contentSwitcher
->count() - 1; i
>= 0 ; i
--) {
379 wtd
.tabText
= contentSwitcher
->tabText(i
);
380 wtd
.tabToolTip
= contentSwitcher
->tabToolTip(i
);
381 wtd
.tabWhatsThis
= contentSwitcher
->tabWhatsThis(i
);
382 wtd
.tabIcon
= contentSwitcher
->tabIcon(i
);
383 wtd
.widget
= contentArea
->widget(i
);
384 removedTabs
.append(wtd
);
386 contentSwitcher
->removeTab(i
);
387 contentArea
->removeWidget(contentArea
->widget(i
));
389 // then reinsert them in reversed order
391 foreach(const WidgetTabData
&wtd
, removedTabs
) {
392 contentSwitcher
->addTab(wtd
.tabIcon
, wtd
.tabText
);
393 contentSwitcher
->setTabToolTip(i
, wtd
.tabToolTip
);
394 contentSwitcher
->setTabWhatsThis(i
, wtd
.tabWhatsThis
);
395 contentArea
->addWidget(wtd
.widget
);
398 //finally replace the searchView
399 contentArea
->addWidget(searchView
);
402 struct WidgetTabData
{
405 QString tabWhatsThis
;
411 Plasma::Applet
*applet
;
412 UrlItemLauncher
*urlLauncher
;
413 SearchModel
*searchModel
;
414 LeaveModel
*leaveModel
;
415 SearchBar
*searchBar
;
418 ContentAreaCap
*contentAreaHeader
;
419 QStackedWidget
*contentArea
;
420 ContentAreaCap
*contentAreaFooter
;
421 TabBar
*contentSwitcher
;
422 FlipScrollView
*applicationView
;
423 QAbstractItemView
*searchView
;
424 QAbstractItemView
*favoritesView
;
425 ContextMenuFactory
*contextMenuFactory
;
427 int visibleItemCount
;
428 Plasma::PopupPlacement placement
;
429 Plasma::Location panelEdge
;
432 Launcher::Launcher(QWidget
*parent
)
433 : QWidget(parent
, Qt::Window
)
434 , d(new Private(this))
439 Launcher::Launcher(Plasma::Applet
*applet
)
440 : QWidget(0, Qt::Window
)
441 , d(new Private(this))
447 void Launcher::init()
449 QVBoxLayout
*layout
= new QVBoxLayout
;
450 layout
->setSpacing(0);
451 layout
->setMargin(0);
453 const int rightHeaderMargin
= style()->pixelMetric(QStyle::PM_ScrollBarExtent
);
455 d
->searchBar
= new SearchBar(this);
456 if (layoutDirection() == Qt::LeftToRight
) {
457 d
->searchBar
->setContentsMargins(0, 0, rightHeaderMargin
, 0);
459 d
->searchBar
->setContentsMargins(rightHeaderMargin
, 0, 0, 0);
461 d
->searchBar
->installEventFilter(this);
462 d
->contentAreaHeader
= new ContentAreaCap(this);
463 d
->contentArea
= new QStackedWidget(this);
465 d
->contentAreaFooter
= new ContentAreaCap(this, flipCap
);
466 d
->contentSwitcher
= new TabBar(this);
467 d
->contentSwitcher
->installEventFilter(this);
468 d
->contentSwitcher
->setIconSize(QSize(48, 48));
469 d
->contentSwitcher
->setShape(QTabBar::RoundedSouth
);
470 connect(d
->contentSwitcher
, SIGNAL(currentChanged(int)),
471 d
->contentArea
, SLOT(setCurrentIndex(int)));
472 d
->contextMenuFactory
= new ContextMenuFactory(this);
475 d
->registerUrlHandlers();
477 // Add status information footer
478 d
->footer
= new QWidget
;
482 if (!gethostname(hostname
, sizeof(hostname
))) {
483 hostname
[sizeof(hostname
)-1] = '\0';
486 QString fullName
= user
.property(KUser::FullName
).toString();
488 if (fullName
.isEmpty()) {
489 labelText
= i18nc("login name, hostname", "User <b>%1</b> on <b>%2</b>", user
.loginName(), hostname
);
491 labelText
= i18nc("full name, login name, hostname", "<b>%1 (%2)</b> on <b>%3</b>", fullName
, user
.loginName(), hostname
);
494 d
->userinfo
= new QLabel(labelText
);
496 QToolButton
*branding
= new BrandingButton(this);
497 branding
->setAutoRaise(false);
498 branding
->setToolButtonStyle(Qt::ToolButtonIconOnly
);
499 connect(branding
, SIGNAL(clicked()), this, SIGNAL(aboutToHide()));
501 QHBoxLayout
*brandingLayout
= new QHBoxLayout
;
502 brandingLayout
->setMargin(3);
503 brandingLayout
->addSpacing(ItemDelegate::ITEM_LEFT_MARGIN
- 3);
504 brandingLayout
->addWidget(d
->userinfo
);
505 brandingLayout
->addStretch(2);
506 brandingLayout
->addWidget(branding
);
507 brandingLayout
->addSpacing(rightHeaderMargin
);
508 d
->footer
->setLayout(brandingLayout
);
510 layout
->addWidget(d
->footer
);
511 layout
->addWidget(d
->searchBar
);
512 layout
->addWidget(d
->contentAreaHeader
);
513 layout
->addWidget(d
->contentArea
);
514 layout
->addWidget(d
->contentAreaFooter
);
515 layout
->addWidget(d
->contentSwitcher
);
518 //setBackgroundRole(QPalette::AlternateBase);
519 //setAutoFillBackground(true);
521 updateThemedPalette();
522 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()),
523 this, SLOT(updateThemedPalette()));
526 void Launcher::updateThemedPalette()
528 QColor color
= Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
);
529 QPalette p
= d
->userinfo
->palette();
530 p
.setColor(QPalette::Normal
, QPalette::WindowText
, color
);
531 p
.setColor(QPalette::Inactive
, QPalette::WindowText
, color
);
532 d
->userinfo
->setPalette(p
);
535 QSize
Launcher::minimumSizeHint() const
539 switch (d
->panelEdge
) {
540 case Plasma::LeftEdge
:
541 case Plasma::RightEdge
:
542 size
.rheight() = d
->searchBar
->sizeHint().height() +
543 d
->footer
->sizeHint().height() +
544 qMax(d
->favoritesView
->sizeHintForRow(0) * 3 + ItemDelegate::HEADER_HEIGHT
, d
->contentSwitcher
->sizeHint().height());
545 size
.rwidth() = d
->contentSwitcher
->sizeHint().width() + d
->favoritesView
->sizeHint().width();
547 case Plasma::TopEdge
:
548 case Plasma::BottomEdge
:
550 size
.rheight() = d
->searchBar
->sizeHint().height() +
551 d
->contentSwitcher
->sizeHint().height() + d
->footer
->sizeHint().height() +
552 d
->favoritesView
->sizeHintForRow(0) * 3 + ItemDelegate::HEADER_HEIGHT
;
553 size
.rwidth() = d
->contentSwitcher
->sizeHint().width();
560 QSize
Launcher::sizeHint() const
562 return QSize(minimumSizeHint().width(), 500);
565 void Launcher::setAutoHide(bool hide
)
570 bool Launcher::autoHide() const
575 void Launcher::setSwitchTabsOnHover(bool switchOnHover
)
577 d
->contentSwitcher
->setSwitchTabsOnHover(switchOnHover
);
580 bool Launcher::switchTabsOnHover() const
582 return d
->contentSwitcher
->switchTabsOnHover();
585 void Launcher::setVisibleItemCount(int count
)
587 d
->visibleItemCount
= count
;
590 int Launcher::visibleItemCount() const
592 return d
->visibleItemCount
;
595 void Launcher::setApplet(Plasma::Applet
*applet
)
598 d
->contextMenuFactory
->setApplet(applet
);
600 KConfigGroup cg
= applet
->globalConfig();
601 setSwitchTabsOnHover(cg
.readEntry("SwitchTabsOnHover", switchTabsOnHover()));
603 cg
= applet
->config();
604 setVisibleItemCount(cg
.readEntry("VisibleItemsCount", visibleItemCount()));
607 void Launcher::reset()
609 d
->contentSwitcher
->setCurrentIndexWithoutAnimation(d
->contentArea
->indexOf(d
->favoritesView
));
610 d
->contentArea
->setCurrentWidget(d
->favoritesView
);
611 d
->searchBar
->clear();
612 d
->applicationView
->viewRoot();
613 d
->leaveModel
->updateModel();
616 Launcher::~Launcher()
621 void Launcher::focusSearchView(const QString
& query
)
623 bool queryEmpty
= query
.isEmpty();
625 d
->contentSwitcher
->setVisible(queryEmpty
);
628 d
->contentArea
->setCurrentWidget(d
->searchView
);
630 focusFavoritesView();
634 void Launcher::focusFavoritesView()
636 d
->contentSwitcher
->setCurrentIndex(d
->contentArea
->indexOf(d
->favoritesView
));
637 d
->contentArea
->setCurrentWidget(d
->favoritesView
);
640 bool Launcher::eventFilter(QObject
*object
, QEvent
*event
)
642 // deliver unhandled key presses from the search bar
643 // (mainly arrow keys, enter) to the active view
644 if ((object
== d
->contentSwitcher
|| object
== d
->searchBar
) && event
->type() == QEvent::KeyPress
) {
645 // we want left/right to still nav the tabbar
646 QKeyEvent
*keyEvent
= static_cast<QKeyEvent
*>(event
);
647 if (keyEvent
->modifiers() == Qt::NoModifier
&&
648 (keyEvent
->key() == Qt::Key_Left
||
649 keyEvent
->key() == Qt::Key_Right
)) {
650 if (object
== d
->contentSwitcher
) {
653 QCoreApplication::sendEvent(d
->contentSwitcher
, event
);
658 QAbstractItemView
*activeView
= qobject_cast
<QAbstractItemView
*>(d
->contentArea
->currentWidget());
660 QCoreApplication::sendEvent(activeView
, event
);
666 // the mouse events we are interested in are delivered to the viewport,
667 // other events are delivered to the view itself.
668 QAbstractItemView
*view
= qobject_cast
<QAbstractItemView
*>(object
);
670 view
= qobject_cast
<QAbstractItemView
*>(object
->parent());
674 QModelIndex openIndex
;
675 if (event
->type() == QEvent::MouseButtonRelease
) {
676 QMouseEvent
*mouseEvent
= (QMouseEvent
*)event
;
677 const QModelIndex index
= view
->indexAt(mouseEvent
->pos());
678 if (index
.isValid() &&
679 index
.model()->hasChildren(index
) == false &&
680 mouseEvent
->button() == Qt::LeftButton
) {
683 } else if (event
->type() == QEvent::KeyPress
) {
684 QKeyEvent
*keyEvent
= (QKeyEvent
*)event
;
685 const QModelIndex index
= view
->currentIndex();
686 if (index
.isValid() && index
.model()->hasChildren(index
) == false &&
687 (keyEvent
->key() == Qt::Key_Enter
|| keyEvent
->key() == Qt::Key_Return
)) {
691 if (openIndex
.isValid()) {
692 d
->urlLauncher
->openItem(openIndex
);
693 // Clear the search bar when enter was pressed
694 if (event
->type() == QEvent::KeyPress
) {
695 d
->searchBar
->clear();
703 return QWidget::eventFilter(object
, event
);
706 void Launcher::showViewContextMenu(const QPoint
& pos
)
708 QAbstractItemView
*view
= qobject_cast
<QAbstractItemView
*>(sender());
710 d
->contextMenuFactory
->showContextMenu(view
, pos
);
714 void Launcher::hideEvent(QHideEvent
*event
)
720 void Launcher::keyPressEvent(QKeyEvent
*event
)
722 if (event
->key() == Qt::Key_Escape
) {
726 // allow tab switching by pressing the left or right arrow keys
727 if (event
->key() == Qt::Key_Left
&& d
->contentSwitcher
->currentIndex() > 0) {
728 d
->contentSwitcher
->setCurrentIndex(d
->contentSwitcher
->currentIndex() - 1);
729 } else if (event
->key() == Qt::Key_Right
&&
730 d
->contentSwitcher
->currentIndex() < d
->contentSwitcher
->count() - 1) {
731 d
->contentSwitcher
->setCurrentIndex(d
->contentSwitcher
->currentIndex() + 1);
736 void Launcher::showEvent(QShowEvent
*e
)
738 d
->searchBar
->setFocus();
740 QWidget::showEvent(e
);
743 void Launcher::resultsAvailable()
745 const QModelIndex root
= d
->searchModel
->index(0, 0);
746 d
->searchView
->setCurrentIndex(d
->searchModel
->index(0, 0, root
));
749 void Launcher::setLauncherOrigin(const Plasma::PopupPlacement placement
, Plasma::Location location
)
751 if (d
->placement
!= placement
) {
752 d
->placement
= placement
;
755 case Plasma::TopPosedRightAlignedPopup
:
756 d
->setSouthLayout(Private::ReverseTabOrder
);
758 case Plasma::LeftPosedTopAlignedPopup
:
759 d
->setEastLayout(Private::NormalTabOrder
);
761 case Plasma::LeftPosedBottomAlignedPopup
:
762 d
->setEastLayout(Private::ReverseTabOrder
);
764 case Plasma::BottomPosedLeftAlignedPopup
:
765 d
->setNorthLayout(Private::NormalTabOrder
);
767 case Plasma::BottomPosedRightAlignedPopup
:
768 d
->setNorthLayout(Private::ReverseTabOrder
);
770 case Plasma::RightPosedTopAlignedPopup
:
771 d
->setWestLayout(Private::NormalTabOrder
);
773 case Plasma::RightPosedBottomAlignedPopup
:
774 d
->setWestLayout(Private::ReverseTabOrder
);
776 case Plasma::TopPosedLeftAlignedPopup
:
778 d
->setSouthLayout(Private::NormalTabOrder
);
782 d
->panelEdge
= location
;
785 #include "launcher.moc"