00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ui/launcher.h"
00022
00023
00024 #include <unistd.h>
00025
00026
00027 #include <QApplication>
00028 #include <QDesktopWidget>
00029 #include <QKeyEvent>
00030 #include <QLabel>
00031 #include <QMouseEvent>
00032 #include <QPainter>
00033 #include <QStackedWidget>
00034 #include <QTabBar>
00035 #include <QToolButton>
00036 #include <QVBoxLayout>
00037 #include <QStyleOptionSizeGrip>
00038
00039
00040 #include <KDebug>
00041 #include <KLocalizedString>
00042 #include <KIcon>
00043 #include <KStandardDirs>
00044 #include <ktoolinvocation.h>
00045 #include <kuser.h>
00046 #include <plasma/theme.h>
00047 #include <plasma/delegate.h>
00048 #include <solid/device.h>
00049 #include <solid/deviceinterface.h>
00050 #include <KColorScheme>
00051
00052
00053 #include "core/favoritesmodel.h"
00054 #include "core/recentlyusedmodel.h"
00055 #include "core/applicationmodel.h"
00056 #include "core/leavemodel.h"
00057 #include "core/itemhandlers.h"
00058 #include "core/searchmodel.h"
00059 #include "core/systemmodel.h"
00060
00061 #include "ui/itemdelegate.h"
00062 #include "ui/brandingbutton.h"
00063 #include "ui/contextmenufactory.h"
00064 #include "ui/urlitemview.h"
00065 #include "ui/flipscrollview.h"
00066 #include "ui/searchbar.h"
00067 #include "ui/tabbar.h"
00068
00069 using namespace Kickoff;
00070
00071 class Launcher::Private
00072 {
00073 public:
00074 class ResizeHandle;
00075 enum CompassDirection { North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest };
00076
00077 Private(Launcher *launcher)
00078 : q(launcher)
00079 , applet(0)
00080 , urlLauncher(new UrlItemLauncher(launcher))
00081 , resizeHandle(0)
00082 , searchModel(0)
00083 , searchBar(0)
00084 , footer(0)
00085 , contentArea(0)
00086 , contentSwitcher(0)
00087 , searchView(0)
00088 , favoritesView(0)
00089 , contextMenuFactory(0)
00090 , autoHide(false)
00091 , visibleItemCount(10)
00092 , launcherOrigin(QPoint(-1, -1))
00093 , isResizing(false)
00094 , resizePlacement( NorthEast )
00095 , panelEdge( Plasma::LeftEdge )
00096 {
00097 }
00098 ~Private()
00099 {
00100 }
00101
00102 enum TabOrder { NormalTabOrder, ReverseTabOrder };
00103
00104 void setupEventHandler(QAbstractItemView *view)
00105 {
00106 view->viewport()->installEventFilter(q);
00107 view->installEventFilter(q);
00108 }
00109
00110 void addView(const QString& name, const QIcon& icon,
00111 QAbstractItemModel *model = 0, QAbstractItemView *view = 0)
00112 {
00113 view->setFrameStyle(QFrame::NoFrame);
00114
00115 view->setFocusPolicy(Qt::NoFocus);
00116 view->setContextMenuPolicy(Qt::CustomContextMenu);
00117 view->setSelectionMode(QAbstractItemView::SingleSelection);
00118 view->setDragEnabled(true);
00119 view->setAcceptDrops(true);
00120 view->setDropIndicatorShown(true);
00121 view->setDragDropMode(QAbstractItemView::InternalMove);
00122 view->setModel(model);
00123
00124 setupEventHandler(view);
00125
00126 connect(view, SIGNAL(customContextMenuRequested(QPoint)), q, SLOT(showViewContextMenu(QPoint)));
00127
00128 contentSwitcher->addTab(icon, name);
00129 contentArea->addWidget(view);
00130 }
00131
00132 void initTabs()
00133 {
00134
00135 setupFavoritesView();
00136
00137
00138 setupAllProgramsView();
00139
00140
00141 setupSystemView();
00142
00143
00144 setupRecentView();
00145
00146
00147 setupLeaveView();
00148
00149
00150 setupSearchView();
00151 }
00152
00153 void setupLeaveView()
00154 {
00155 LeaveModel *model = new LeaveModel(q);
00156 UrlItemView *view = new UrlItemView;
00157 ItemDelegate *delegate = new ItemDelegate(q);
00158 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, SubTitleRole);
00159 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
00160 view->setItemDelegate(delegate);
00161 view->setItemStateProvider(delegate);
00162 addView(i18n("Leave"), KIcon("system-shutdown"), model, view);
00163 }
00164
00165 void setupFavoritesView()
00166 {
00167 FavoritesModel *model = new FavoritesModel(q);
00168 UrlItemView *view = new UrlItemView;
00169 ItemDelegate *delegate = new ItemDelegate(q);
00170 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, SubTitleRole);
00171 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
00172 view->setItemDelegate(delegate);
00173 view->setItemStateProvider(delegate);
00174 addView(i18n("Favorites"), KIcon("bookmarks"), model, view);
00175
00176 connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), q, SLOT(focusFavoritesView()));
00177
00178 favoritesView = view;
00179 }
00180
00181 void setupAllProgramsView()
00182 {
00183 ApplicationModel *applicationModel = new ApplicationModel(q);
00184 applicationModel->setDuplicatePolicy(ApplicationModel::ShowLatestOnlyPolicy);
00185
00186 applicationView = new FlipScrollView();
00187 ItemDelegate *delegate = new ItemDelegate(q);
00188 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, SubTitleRole);
00189 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
00190 applicationView->setItemDelegate(delegate);
00191
00192 addView(i18n("Applications"), KIcon("applications-other"),
00193 applicationModel, applicationView);
00194 }
00195
00196 void setupRecentView()
00197 {
00198 RecentlyUsedModel *model = new RecentlyUsedModel(q);
00199 UrlItemView *view = new UrlItemView;
00200 ItemDelegate *delegate = new ItemDelegate(q);
00201 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, SubTitleRole);
00202 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
00203 view->setItemDelegate(delegate);
00204 view->setItemStateProvider(delegate);
00205 addView(i18n("Recently Used"), KIcon("document-open-recent"), model, view);
00206
00207 QAction *clearApplications = new QAction(KIcon("edit-clear-history"), i18n("Clear Recent Applications"), q);
00208 QAction *clearDocuments = new QAction(KIcon("edit-clear-history"), i18n("Clear Recent Documents"), q);
00209
00210 connect(clearApplications, SIGNAL(triggered()), model, SLOT(clearRecentApplications()));
00211 connect(clearDocuments, SIGNAL(triggered()), model, SLOT(clearRecentDocuments()));
00212
00213 contextMenuFactory->setViewActions(view, QList<QAction*>() << clearApplications << clearDocuments);
00214 }
00215
00216 void setupSystemView()
00217 {
00218 SystemModel *model = new SystemModel(q);
00219 UrlItemView *view = new UrlItemView;
00220 ItemDelegate *delegate = new ItemDelegate(q);
00221 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, SubTitleRole);
00222 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
00223 view->setItemDelegate(delegate);
00224 view->setItemStateProvider(delegate);
00225
00226 addView(i18n("Computer"), systemIcon(), model, view);
00227 }
00228
00229 void setupSearchView()
00230 {
00231 searchModel = new SearchModel(q);
00232 UrlItemView *view = new UrlItemView;
00233 ItemDelegate *delegate = new ItemDelegate(q);
00234 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, SubTitleRole);
00235 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
00236 view->setItemDelegate(delegate);
00237 view->setItemStateProvider(delegate);
00238 view->setModel(searchModel);
00239 view->setFrameStyle(QFrame::NoFrame);
00240
00241 view->setFocusPolicy(Qt::NoFocus);
00242 view->setDragEnabled(true);
00243 setupEventHandler(view);
00244
00245 connect(searchModel, SIGNAL(resultsAvailable()), q, SLOT(resultsAvailable()));
00246
00247 connect(searchBar, SIGNAL(queryChanged(QString)), searchModel, SLOT(setQuery(QString)));
00248 connect(searchBar, SIGNAL(queryChanged(QString)), q, SLOT(focusSearchView(QString)));
00249
00250 view->setContextMenuPolicy(Qt::CustomContextMenu);
00251 connect(view, SIGNAL(customContextMenuRequested(QPoint)), q, SLOT(showViewContextMenu(QPoint)));
00252
00253 contentArea->addWidget(view);
00254 searchView = view;
00255 }
00256
00257 void registerUrlHandlers()
00258 {
00259 UrlItemLauncher::addGlobalHandler(UrlItemLauncher::ExtensionHandler, "desktop", new ServiceItemHandler);
00260 UrlItemLauncher::addGlobalHandler(UrlItemLauncher::ProtocolHandler, "leave", new LeaveItemHandler);
00261 }
00262
00263 QIcon systemIcon()
00264 {
00265 QList<Solid::Device> batteryList = Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString());
00266
00267 if (batteryList.isEmpty()) {
00268 return KIcon("computer");
00269 } else {
00270 return KIcon("computer-laptop");
00271 }
00272 }
00273
00274 void setNorthLayout(TabOrder tabOrder)
00275 {
00276 contentSwitcher->setShape( QTabBar::RoundedNorth );
00277 QLayout * layout = q->layout();
00278 delete layout;
00279 layout = new QVBoxLayout();
00280 layout->addWidget(contentSwitcher);
00281 layout->addWidget(contentArea);
00282 layout->addWidget(searchBar);
00283 layout->addWidget(footer);
00284 layout->setSpacing(0);
00285 layout->setMargin(0);
00286 q->setLayout(layout);
00287 setTabOrder( tabOrder );
00288 }
00289
00290 void setSouthLayout(TabOrder tabOrder)
00291 {
00292 contentSwitcher->setShape( QTabBar::RoundedSouth );
00293 QLayout * layout = q->layout();
00294 delete layout;
00295 layout = new QVBoxLayout();
00296 layout->addWidget(footer);
00297 layout->addWidget(searchBar);
00298 layout->addWidget(contentArea);
00299 layout->addWidget(contentSwitcher);
00300 layout->setSpacing(0);
00301 layout->setMargin(0);
00302 q->setLayout(layout);
00303 setTabOrder( tabOrder );
00304 }
00305
00306 void setWestLayout(TabOrder tabOrder)
00307 {
00308 contentSwitcher->setShape( QTabBar::RoundedWest );
00309 QLayout * layout = q->layout();
00310 delete layout;
00311 layout = new QHBoxLayout();
00312 layout->addWidget(contentSwitcher);
00313 layout->addWidget(contentArea);
00314 QBoxLayout * layout2 = new QVBoxLayout();
00315 if ( tabOrder == NormalTabOrder ) {
00316 layout2->addLayout(layout);
00317 layout2->addWidget(searchBar);
00318 layout2->addWidget(footer);
00319 } else {
00320 layout2->addWidget(footer);
00321 layout2->addWidget(searchBar);
00322 layout2->addLayout(layout);
00323 }
00324 layout->setSpacing(0);
00325 layout->setMargin(0);
00326 layout2->setSpacing(0);
00327 layout2->setMargin(0);
00328 q->setLayout(layout2);
00329 setTabOrder( tabOrder );
00330 }
00331
00332 void setEastLayout(TabOrder tabOrder)
00333 {
00334 contentSwitcher->setShape( QTabBar::RoundedEast );
00335 QLayout * layout = q->layout();
00336 delete layout;
00337 layout = new QHBoxLayout();
00338 layout->addWidget(contentArea);
00339 layout->addWidget(contentSwitcher);
00340 QBoxLayout * layout2 = new QVBoxLayout();
00341 if ( tabOrder == NormalTabOrder ) {
00342 layout2->addLayout(layout);
00343 layout2->addWidget(searchBar);
00344 layout2->addWidget(footer);
00345 } else {
00346 layout2->addWidget(footer);
00347 layout2->addWidget(searchBar);
00348 layout2->addLayout(layout);
00349 }
00350 layout->setSpacing(0);
00351 layout->setMargin(0);
00352 layout2->setSpacing(0);
00353 layout2->setMargin(0);
00354 q->setLayout(layout2);
00355 setTabOrder(tabOrder);
00356 }
00357
00358 void setTabOrder(TabOrder newOrder)
00359 {
00360
00361 TabOrder oldOrder;
00362 if ( contentArea->widget( 0 ) == favoritesView ) {
00363 oldOrder = NormalTabOrder;
00364 } else {
00365 oldOrder = ReverseTabOrder;
00366 }
00367 if ( newOrder == oldOrder ) {
00368 return;
00369 }
00370
00371
00372 contentArea->removeWidget( searchView );
00373 Q_ASSERT( contentArea->count() == contentSwitcher->count() );
00374
00375 QList<WidgetTabData> removedTabs;
00376 for ( int i = contentSwitcher->count() - 1; i >= 0 ; i-- ) {
00377 WidgetTabData wtd;
00378 wtd.tabText = contentSwitcher->tabText( i );
00379 wtd.tabToolTip = contentSwitcher->tabToolTip( i );
00380 wtd.tabWhatsThis = contentSwitcher->tabWhatsThis( i );
00381 wtd.tabIcon = contentSwitcher->tabIcon( i );
00382 wtd.widget = contentArea->widget( i );
00383 removedTabs.append( wtd );
00384
00385 contentSwitcher->removeTab( i );
00386 contentArea->removeWidget( contentArea->widget( i ) );
00387 }
00388
00389 int i = 0;
00390 foreach (const WidgetTabData &wtd, removedTabs) {
00391 contentSwitcher->addTab( wtd.tabIcon, wtd.tabText );
00392 contentSwitcher->setTabToolTip( i, wtd.tabToolTip );
00393 contentSwitcher->setTabWhatsThis( i, wtd.tabWhatsThis );
00394 contentArea->addWidget( wtd.widget );
00395 ++i;
00396 }
00397
00398 contentArea->addWidget( searchView );
00399 }
00400
00401 inline void adjustResizeHandlePosition();
00402
00403 struct WidgetTabData
00404 {
00405 QString tabText;
00406 QString tabToolTip;
00407 QString tabWhatsThis;
00408 QIcon tabIcon;
00409 QWidget * widget;
00410 };
00411 Launcher * const q;
00412 Plasma::Applet *applet;
00413 UrlItemLauncher *urlLauncher;
00414 ResizeHandle *resizeHandle;
00415 SearchModel *searchModel;
00416 SearchBar *searchBar;
00417 QWidget *footer;
00418 QStackedWidget *contentArea;
00419 TabBar *contentSwitcher;
00420 FlipScrollView *applicationView;
00421 QAbstractItemView *searchView;
00422 QAbstractItemView *favoritesView;
00423 ContextMenuFactory *contextMenuFactory;
00424 bool autoHide;
00425 int visibleItemCount;
00426 QPoint launcherOrigin;
00427 bool isResizing;
00428 CompassDirection resizePlacement;
00429 Plasma::Location panelEdge;
00430 };
00431
00432 class Launcher::Private::ResizeHandle
00433 : public QWidget
00434 {
00435 public:
00436 ResizeHandle(QWidget *parent = 0)
00437 : QWidget(parent),
00438 m_placement(NorthEast)
00439 {
00440 }
00441
00442 ~ResizeHandle()
00443 {
00444 }
00445
00446 void setPlacement(CompassDirection dir)
00447 {
00448 m_placement = dir;
00449 switch (m_placement) {
00450 case NorthEast:
00451 default:
00452 setCursor(Qt::SizeBDiagCursor);
00453 break;
00454 case SouthEast:
00455 setCursor(Qt::SizeFDiagCursor);
00456 break;
00457 case SouthWest:
00458 setCursor(Qt::SizeBDiagCursor);
00459 break;
00460 case NorthWest:
00461 setCursor(Qt::SizeFDiagCursor);
00462 break;
00463 }
00464 }
00465
00466 protected:
00467 void paintEvent(QPaintEvent *event)
00468 {
00469 QPainter p(this);
00470 QStyleOptionSizeGrip opt;
00471 opt.initFrom(this);
00472 switch (m_placement) {
00473 case NorthEast:
00474 default:
00475 opt.corner = Qt::TopRightCorner;
00476 break;
00477 case SouthEast:
00478 opt.corner = Qt::BottomRightCorner;
00479 break;
00480 case SouthWest:
00481 opt.corner = Qt::BottomLeftCorner;
00482 break;
00483 case NorthWest:
00484 opt.corner = Qt::TopLeftCorner;
00485 break;
00486 }
00487 style()->drawControl(QStyle::CE_SizeGrip, &opt, &p);
00488 p.end();
00489 }
00490
00491 private:
00492 CompassDirection m_placement;
00493 };
00494
00495 void Launcher::Private::adjustResizeHandlePosition()
00496 {
00497 const int margin = 1;
00498 switch (resizePlacement) {
00499 case NorthEast:
00500 resizeHandle->move(q->width()-resizeHandle->width() - margin,
00501 margin);
00502 break;
00503 case SouthEast:
00504 resizeHandle->move(q->width()-resizeHandle->width() - margin,
00505 q->height()-resizeHandle->height() - margin);
00506 break;
00507 case SouthWest:
00508 resizeHandle->move(margin, q->height()-resizeHandle->height() - margin);
00509 break;
00510 case NorthWest:
00511 resizeHandle->move(margin, margin);
00512 break;
00513 default:
00514 break;
00515 }
00516
00517 resizeHandle->setPlacement(resizePlacement);
00518 }
00519
00520 Launcher::Launcher(QWidget *parent)
00521 : QWidget(parent, Qt::Window)
00522 , d(new Private(this))
00523 {
00524 init();
00525 }
00526
00527 Launcher::Launcher(Plasma::Applet *applet)
00528 : QWidget(0, Qt::Window)
00529 , d(new Private(this))
00530 {
00531 init();
00532 setApplet(applet);
00533 }
00534
00535 void Launcher::init()
00536 {
00537 QVBoxLayout *layout = new QVBoxLayout;
00538 layout->setSpacing(0);
00539 layout->setMargin(0);
00540
00541 const int rightHeaderMargin = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
00542
00543 d->searchBar = new SearchBar(this);
00544 if (layoutDirection() == Qt::LeftToRight) {
00545 d->searchBar->setContentsMargins(0, 0, rightHeaderMargin, 0);
00546 } else {
00547 d->searchBar->setContentsMargins(rightHeaderMargin, 0, 0, 0);
00548 }
00549 d->searchBar->installEventFilter(this);
00550 d->contentArea = new QStackedWidget(this);
00551 d->contentSwitcher = new TabBar(this);
00552 d->contentSwitcher->installEventFilter(this);
00553 d->contentSwitcher->setIconSize(QSize(48,48));
00554 d->contentSwitcher->setShape(QTabBar::RoundedSouth);
00555 connect(d->contentSwitcher, SIGNAL(currentChanged(int)),
00556 d->contentArea, SLOT(setCurrentIndex(int)) );
00557 d->contextMenuFactory = new ContextMenuFactory(this);
00558
00559 d->initTabs();
00560 d->registerUrlHandlers();
00561
00562
00563 d->footer = new QWidget;
00564
00565 char hostname[256];
00566 hostname[0] = '\0';
00567 if (!gethostname( hostname, sizeof(hostname) )) {
00568 hostname[sizeof(hostname)-1] = '\0';
00569 }
00570 QLabel *userinfo = new QLabel(i18n("User <b>%1</b> on <b>%2</b>", KUser().loginName(), hostname));
00571 QPalette palette;
00572 palette.setColor( QPalette::Foreground, KColorScheme(QPalette::Active).foreground(KColorScheme::InactiveText).color() );
00573 userinfo->setPalette( palette );
00574
00575 QToolButton *branding = new BrandingButton(this);
00576 branding->setAutoRaise(false);
00577 branding->setToolButtonStyle(Qt::ToolButtonIconOnly);
00578 connect( branding, SIGNAL(clicked()), SLOT(openHomepage()));
00579
00580 d->resizeHandle = new Private::ResizeHandle(this);
00581 d->resizeHandle->setFixedSize(16, 16);
00582 d->resizeHandle->setCursor(Qt::SizeBDiagCursor);
00583 setMouseTracking(true);
00584
00585 QHBoxLayout *brandingLayout = new QHBoxLayout;
00586 brandingLayout->setMargin(3);
00587 brandingLayout->addSpacing(ItemDelegate::ITEM_LEFT_MARGIN - 3);
00588 brandingLayout->addWidget(userinfo);
00589 brandingLayout->addStretch(2);
00590 brandingLayout->addWidget(branding);
00591 brandingLayout->addSpacing(rightHeaderMargin);
00592 d->footer->setLayout(brandingLayout);
00593
00594 layout->addWidget(d->footer);
00595 layout->addWidget(d->searchBar);
00596 layout->addWidget(d->contentArea);
00597 layout->addWidget(d->contentSwitcher);
00598
00599 setLayout(layout);
00600 setBackgroundRole(QPalette::AlternateBase);
00601 setAutoFillBackground(true);
00602 d->resizePlacement = Private::NorthEast;
00603 }
00604
00605 QSize Launcher::minimumSizeHint() const
00606 {
00607 QSize size = QWidget::sizeHint();
00608
00609
00610 const int CONTENT_MARGIN_WIDTH = 2;
00611
00612 size.rwidth() += CONTENT_MARGIN_WIDTH;
00613
00614 switch ( d->panelEdge ) {
00615 case Plasma::LeftEdge:
00616 case Plasma::RightEdge:
00617 size.rheight() = d->searchBar->sizeHint().height() +
00618 d->footer->sizeHint().height() +
00619 qMax( d->favoritesView->sizeHintForRow(0)*3 + ItemDelegate::HEADER_HEIGHT, d->contentSwitcher->sizeHint().height() );
00620 break;
00621 case Plasma::TopEdge:
00622 case Plasma::BottomEdge:
00623 default:
00624 size.rheight() = d->searchBar->sizeHint().height() +
00625 d->contentSwitcher->sizeHint().height() + d->footer->sizeHint().height() +
00626 d->favoritesView->sizeHintForRow(0)*3 + ItemDelegate::HEADER_HEIGHT;
00627 break;
00628 }
00629 return size;
00630 }
00631
00632 QSize Launcher::sizeHint() const
00633 {
00634 KConfigGroup sizeGroup;
00635 if (d->applet) {
00636 sizeGroup = d->applet->config();
00637 } else {
00638 sizeGroup = componentData().config()->group("Size");
00639 }
00640 const int width = qMin(sizeGroup.readEntry("Width", 0), QApplication::desktop()->screen()->width()-50);
00641 const int height = qMin(sizeGroup.readEntry("Height", 0), QApplication::desktop()->screen()->height()-50);
00642 QSize wanted(width, height);
00643 bool isDefault = wanted.isNull();
00644 wanted = wanted.expandedTo(minimumSizeHint());
00645 if (isDefault) {
00646 wanted.setHeight( wanted.height() + ( d->favoritesView->sizeHintForRow(0) * (d->visibleItemCount - 3) ) );
00647 }
00648
00649 return wanted;
00650 }
00651
00652 void Launcher::setAutoHide(bool hide)
00653 {
00654 d->autoHide = hide;
00655 }
00656
00657 bool Launcher::autoHide() const
00658 {
00659 return d->autoHide;
00660 }
00661
00662 void Launcher::setSwitchTabsOnHover(bool switchOnHover)
00663 {
00664 d->contentSwitcher->setSwitchTabsOnHover(switchOnHover);
00665 }
00666
00667 bool Launcher::switchTabsOnHover() const
00668 {
00669 return d->contentSwitcher->switchTabsOnHover();
00670 }
00671
00672 void Launcher::setVisibleItemCount(int count)
00673 {
00674 d->visibleItemCount = count;
00675 }
00676
00677 int Launcher::visibleItemCount() const
00678 {
00679 return d->visibleItemCount;
00680 }
00681
00682 void Launcher::setApplet(Plasma::Applet *applet)
00683 {
00684 d->applet = applet;
00685 d->contextMenuFactory->setApplet(applet);
00686
00687 KConfigGroup cg = applet->config();
00688 setSwitchTabsOnHover(cg.readEntry("SwitchTabsOnHover", switchTabsOnHover()));
00689 setVisibleItemCount(cg.readEntry("VisibleItemsCount", visibleItemCount()));
00690 }
00691
00692 void Launcher::reset()
00693 {
00694 d->contentSwitcher->setCurrentIndexWithoutAnimation(d->contentArea->indexOf(d->favoritesView));
00695 d->contentArea->setCurrentWidget(d->favoritesView);
00696 d->searchBar->clear();
00697 d->applicationView->viewRoot();
00698 }
00699
00700 Launcher::~Launcher()
00701 {
00702 delete d;
00703 }
00704
00705 void Launcher::focusSearchView(const QString& query)
00706 {
00707 bool queryEmpty = query.isEmpty();
00708
00709 d->contentSwitcher->setVisible(queryEmpty);
00710
00711 if (!queryEmpty) {
00712 d->contentArea->setCurrentWidget(d->searchView);
00713 } else {
00714 focusFavoritesView();
00715 }
00716 }
00717
00718 void Launcher::focusFavoritesView()
00719 {
00720 d->contentSwitcher->setCurrentIndex(d->contentArea->indexOf(d->favoritesView));
00721 d->contentArea->setCurrentWidget(d->favoritesView);
00722 }
00723
00724 bool Launcher::eventFilter(QObject *object, QEvent *event)
00725 {
00726
00727
00728 if ((object == d->contentSwitcher || object == d->searchBar) && event->type() == QEvent::KeyPress) {
00729
00730 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
00731 if (keyEvent->modifiers() == Qt::NoModifier &&
00732 (keyEvent->key() == Qt::Key_Left ||
00733 keyEvent->key() == Qt::Key_Right)) {
00734 if (object == d->contentSwitcher) {
00735 return false;
00736 } else {
00737 QCoreApplication::sendEvent(d->contentSwitcher, event);
00738 return true;
00739 }
00740 }
00741
00742 QAbstractItemView *activeView = qobject_cast<QAbstractItemView*>(d->contentArea->currentWidget());
00743 if (activeView) {
00744 QCoreApplication::sendEvent(activeView, event);
00745 return true;
00746 }
00747 }
00748
00749
00750
00751
00752 QAbstractItemView *view = qobject_cast<QAbstractItemView*>(object);
00753 if(!view) {
00754 view = qobject_cast<QAbstractItemView*>(object->parent());
00755 }
00756
00757 if (view) {
00758 QModelIndex openIndex;
00759 if (event->type() == QEvent::MouseButtonRelease) {
00760 QMouseEvent *mouseEvent = (QMouseEvent*)event;
00761 const QModelIndex index = view->indexAt(mouseEvent->pos());
00762 if (index.isValid() &&
00763 index.model()->hasChildren(index) == false &&
00764 mouseEvent->button() == Qt::LeftButton) {
00765 openIndex = index;
00766 }
00767 } else if (event->type() == QEvent::KeyPress) {
00768 QKeyEvent *keyEvent = (QKeyEvent*)event;
00769 const QModelIndex index = view->currentIndex();
00770 if (index.isValid() && index.model()->hasChildren(index) == false &&
00771 (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)) {
00772 openIndex = index;
00773 }
00774 }
00775 if (openIndex.isValid()) {
00776 d->urlLauncher->openItem(openIndex);
00777
00778 if (event->type() == QEvent::KeyPress) {
00779 d->searchBar->clear();
00780 }
00781 if (d->autoHide) {
00782 hide();
00783 }
00784 return true;
00785 }
00786 }
00787 return QWidget::eventFilter(object, event);
00788 }
00789
00790 void Launcher::showViewContextMenu(const QPoint& pos)
00791 {
00792 QAbstractItemView *view = qobject_cast<QAbstractItemView*>(sender());
00793 if (view) {
00794 d->contextMenuFactory->showContextMenu(view, d->contentArea->mapFromParent(pos));
00795 }
00796 }
00797
00798 void Launcher::keyPressEvent(QKeyEvent *event)
00799 {
00800 if (event->key() == Qt::Key_Escape) {
00801 hide();
00802 }
00803 #if 0
00804
00805 if (event->key() == Qt::Key_Left && d->contentSwitcher->currentIndex() > 0) {
00806 d->contentSwitcher->setCurrentIndex(d->contentSwitcher->currentIndex()-1);
00807 } else if (event->key() == Qt::Key_Right &&
00808 d->contentSwitcher->currentIndex() < d->contentSwitcher->count()-1) {
00809 d->contentSwitcher->setCurrentIndex(d->contentSwitcher->currentIndex()+1);
00810 }
00811 #endif
00812 }
00813
00814 void Launcher::moveEvent(QMoveEvent *e)
00815 {
00816
00817 int leftMargin = 1;
00818 int rightMargin = 1;
00819 int topMargin = 1;
00820 int bottomMargin = 1;
00821
00822 QRect r(QApplication::desktop()->screenGeometry(this));
00823 QRect g(geometry());
00824
00825 if (g.left() == r.left()) {
00826 leftMargin = 0;
00827 }
00828
00829 if (g.right() == r.right()) {
00830 rightMargin = 0;
00831 }
00832
00833 if (g.top() == r.top()) {
00834 topMargin = 0;
00835 }
00836
00837 if (g.bottom() == r.bottom()) {
00838 bottomMargin = 0;
00839 }
00840
00841 setContentsMargins(leftMargin, rightMargin, topMargin, rightMargin);
00842 QWidget::moveEvent(e);
00843 }
00844
00845 void Launcher::showEvent(QShowEvent *e)
00846 {
00847 d->searchBar->setFocus();
00848 d->resizeHandle->raise();
00849 QWidget::showEvent(e);
00850 }
00851
00852 void Launcher::hideEvent(QHideEvent *e)
00853 {
00854 emit aboutToHide();
00855 QWidget::hideEvent(e);
00856 }
00857
00858 void Launcher::paintEvent(QPaintEvent*)
00859 {
00860
00861 QPainter p(this);
00862 p.setPen(QPen(palette().mid(), 0));
00863 p.drawRect(rect().adjusted(0, 0, -1, -1));
00864 }
00865
00866 void Launcher::openHomepage()
00867 {
00868 hide();
00869 KToolInvocation::invokeBrowser("http://www.kde.org/");
00870 }
00871
00872 void Launcher::resultsAvailable()
00873 {
00874 const QModelIndex root = d->searchModel->index(0, 0);
00875 d->searchView->setCurrentIndex(d->searchModel->index(0, 0, root));
00876 }
00877
00878 void Launcher::setLauncherOrigin( QPoint origin, Plasma::Location location )
00879 {
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912 if (d->launcherOrigin == origin && d->panelEdge == location) {
00913 return;
00914 }
00915 d->launcherOrigin = origin;
00916 d->panelEdge = location;
00917 QPoint relativePosition = pos() - d->launcherOrigin;
00918 int rx = relativePosition.x();
00919 int ry = relativePosition.y();
00920 if ( rx < 0 ) {
00921 if ( ry < 0 ) {
00922 if ( location == Plasma::RightEdge ) {
00923
00924 kDebug() << "menu position " << 7;
00925 d->resizePlacement = Private::NorthWest;
00926 d->setEastLayout( Private::ReverseTabOrder );
00927 } else {
00928
00929 kDebug() << "menu position " << 6;
00930 d->resizePlacement = Private::NorthWest;
00931 d->setSouthLayout( Private::ReverseTabOrder );
00932 }
00933 } else if ( ry == 0 ) {
00934
00935 kDebug() << "menu position " << 4;
00936 d->resizePlacement = Private::SouthWest;
00937 d->setEastLayout( Private::NormalTabOrder );
00938 } else {
00939
00940 kDebug() << "menu position " << 5;
00941 d->resizePlacement = Private::SouthWest;
00942 d->setNorthLayout( Private::ReverseTabOrder );
00943 }
00944 } else if ( rx == 0 ) {
00945 if ( ry < 0 ) {
00946
00947 kDebug() << "menu position " << 1;
00948 d->resizePlacement = Private::NorthEast;
00949 d->setSouthLayout( Private::NormalTabOrder );
00950 } else {
00951
00952 kDebug() << "menu position " << 2;
00953 d->resizePlacement = Private::SouthEast;
00954 d->setNorthLayout( Private::NormalTabOrder );
00955 }
00956 } else {
00957 if ( ry == 0 ) {
00958
00959 kDebug() << "menu position " << 3;
00960 d->resizePlacement = Private::SouthEast;
00961 d->setWestLayout( Private::NormalTabOrder );
00962 } else {
00963
00964 kDebug() << "menu position " << 8;
00965 d->resizePlacement = Private::NorthEast;
00966 d->setWestLayout( Private::ReverseTabOrder );
00967 }
00968 }
00969 d->adjustResizeHandlePosition();
00970 }
00971
00972 QPoint Launcher::launcherOrigin() const
00973 {
00974 return d->launcherOrigin;
00975 }
00976
00977 void Launcher::resizeEvent(QResizeEvent *e)
00978 {
00979 d->adjustResizeHandlePosition();
00980 QWidget::resizeEvent(e);
00981 }
00982
00983 void Launcher::mousePressEvent(QMouseEvent *e)
00984 {
00985 if ( d->resizeHandle->geometry().contains( e->pos() ) ) {
00986 d->isResizing = true;
00987 }
00988 QWidget::mousePressEvent(e);
00989 }
00990
00991 void Launcher::mouseReleaseEvent(QMouseEvent *e)
00992 {
00993 if (d->isResizing) {
00994 d->isResizing = false;
00995 KConfigGroup sizeGroup;
00996 if (d->applet) {
00997 sizeGroup = d->applet->config();
00998 } else {
00999 sizeGroup = componentData().config()->group("Size");
01000 }
01001 sizeGroup.writeEntry("Height", height());
01002 sizeGroup.writeEntry("Width", width());
01003 emit configNeedsSaving();
01004 }
01005 QWidget::mouseReleaseEvent(e);
01006 }
01007
01008 void Launcher::mouseMoveEvent(QMouseEvent *e)
01009 {
01010
01011 if ( hasMouseTracking() && d->isResizing ) {
01012 int newX, newY, newWidth, newHeight;
01013 kDebug() << "x: " << x() << " y: " << y();
01014 kDebug() << "width: " << width() << " height: " << height();
01015 kDebug() << "e-x: " << e->x() << " e->y: " << e->y();
01016 switch (d->resizePlacement) {
01017 case Private::NorthEast:
01018 newWidth = qMax( e->x(), minimumSizeHint().width() );
01019 newHeight = qMax( height() - e->y(), minimumSizeHint().height() );
01020 newX = x();
01021 newY = y() + height() - newHeight;
01022 kDebug() << "Foot of menu to newY + newHeight";
01023 kDebug() << "= " << newY << " + " << newHeight << " = " << (newY + newHeight);
01024 break;
01025 case Private::SouthEast:
01026 newWidth = qMax( e->x(), minimumSizeHint().width() );
01027 newHeight = qMax( e->y(), minimumSizeHint().height() );
01028 newX = x();
01029 newY = y();
01030 break;
01031 case Private::SouthWest:
01032 newWidth = qMax( width() - e->x(), minimumSizeHint().width() );
01033 newHeight = qMax( e->y(), minimumSizeHint().height() );
01034 newX = x() + width() - newWidth;
01035 newY = y();
01036 break;
01037 case Private::NorthWest:
01038 newWidth = qMax( width() - e->x(), minimumSizeHint().width() );
01039 newHeight = qMax( height() - e->y(), minimumSizeHint().height() );
01040 newX = x() + width() - newWidth;
01041 newY = y() + height() - newHeight;
01042 kDebug() << "Foot of menu to newY + newHeight";
01043 kDebug() << "= " << newY << " + " << newHeight << " = " << (newY + newHeight);
01044 break;
01045 default:
01046 break;
01047 }
01048 kDebug() << "newX: " << newX << "newY: " << newY << "newW: " << newWidth << "newH: " << newHeight;
01049 setGeometry( newX, newY, newWidth, newHeight);
01050 }
01051 QWidget::mouseMoveEvent(e);
01052 }
01053
01054 #include "launcher.moc"
01055