00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "simpleapplet/simpleapplet.h"
00023 #include "simpleapplet/menuview.h"
00024
00025
00026 #include <QLabel>
00027 #include <QComboBox>
00028 #include <QGridLayout>
00029 #include <QGraphicsView>
00030 #include <QMetaObject>
00031 #include <QMetaEnum>
00032 #include <QPointer>
00033 #include <QGraphicsLinearLayout>
00034
00035
00036 #include <KIcon>
00037 #include <KConfigDialog>
00038 #include <KMenu>
00039 #include <KProcess>
00040
00041
00042 #include <plasma/widgets/icon.h>
00043 #include <plasma/containment.h>
00044
00045
00046 #include "core/itemhandlers.h"
00047 #include "core/models.h"
00048 #include "core/applicationmodel.h"
00049 #include "core/favoritesmodel.h"
00050 #include "core/systemmodel.h"
00051 #include "core/recentlyusedmodel.h"
00052 #include "core/leavemodel.h"
00053 #include "core/urlitemlauncher.h"
00054
00056 class MenuLauncherApplet::Private
00057 {
00058 public:
00059 QPointer<Kickoff::MenuView> menuview;
00060 Plasma::Icon *icon;
00061 QPointer<Kickoff::UrlItemLauncher> launcher;
00062
00063 MenuLauncherApplet::ViewType viewtype;
00064 MenuLauncherApplet::FormatType formattype;
00065
00066 QComboBox *viewComboBox, *formatComboBox;
00067
00068 QList<QAction*> actions;
00069 QAction* switcher;
00070
00071 Private() : menuview(0), launcher(0), switcher(0) {}
00072 ~Private() { delete menuview; }
00073
00074 void addItem(QComboBox* combo, const QString& caption, int index, const QString& icon = QString()) {
00075 if( icon.isNull() ) {
00076 combo->addItem(caption, index);
00077 }
00078 else {
00079 combo->addItem(KIcon(icon), caption, index);
00080 }
00081 }
00082
00083 void setCurrentItem(QComboBox* combo, int currentIndex) {
00084 for(int i = combo->count() - 1; i >= 0; --i) {
00085 if( combo->itemData(i).toInt() == currentIndex ) {
00086 combo->setCurrentIndex(i);
00087 return;
00088 }
00089 }
00090 if( combo->count() > 0 ) {
00091 combo->setCurrentIndex(0);
00092 }
00093 }
00094
00095 Kickoff::MenuView *createMenuView(QAbstractItemModel *model = 0) {
00096 Kickoff::MenuView *view = new Kickoff::MenuView(menuview);
00097 view->setFormatType( (Kickoff::MenuView::FormatType) formattype );
00098 if( model ) {
00099 view->setModel(model);
00100 }
00101 return view;
00102 }
00103
00104 void addMenu(Kickoff::MenuView *view, bool mergeFirstLevel) {
00105 QList<QAction*> actions = view->actions();
00106 foreach(QAction *action, actions) {
00107 if( action->menu() && mergeFirstLevel ) {
00108 QMetaObject::invokeMethod(action->menu(),"aboutToShow");
00109 if( actions.count() > 1 && action->menu()->actions().count() > 0 ) {
00110 menuview->addTitle(action->text());
00111 }
00112 foreach(QAction *a, action->menu()->actions()) {
00113 a->setVisible(a->menu() || ! view->indexForAction(a).data(Kickoff::UrlRole).isNull());
00114 menuview->addAction(a);
00115 }
00116 }
00117 else {
00118 action->setVisible(action->menu() || ! view->indexForAction(action).data(Kickoff::UrlRole).isNull());
00119 menuview->addAction(action);
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130 connect(view->model(), SIGNAL(modelReset()), menuview, SLOT(deleteLater()));
00131 }
00132
00133 QString viewIcon() {
00134 switch( viewtype ) {
00135 case Combined:
00136 return "start-here-kde";
00137 case Favorites:
00138 return "bookmarks";
00139 case Applications:
00140 return "applications-other";
00141 case Computer:
00142 return "computer";
00143 case RecentlyUsed:
00144 return "document-open-recent";
00145 case Leave:
00146 return "application-exit";
00147 }
00148 return QString();
00149 }
00150
00151 };
00152
00153 MenuLauncherApplet::MenuLauncherApplet(QObject *parent, const QVariantList &args)
00154 : Plasma::Applet(parent,args),
00155 d(new Private)
00156 {
00157 KGlobal::locale()->insertCatalog("plasma_applet_launcher");
00158
00159 setHasConfigurationInterface(true);
00160 setBackgroundHints(NoBackground);
00161
00162 d->icon = new Plasma::Icon(QString(), this);
00163 d->icon->setFlag(ItemIsMovable, false);
00164 connect(d->icon, SIGNAL(pressed(bool)), this, SLOT(toggleMenu(bool)));
00165 connect(this, SIGNAL(activate()), this, SLOT(toggleMenu()));
00166
00167 d->viewtype = Combined;
00168 d->formattype = NameDescription;
00169
00170 resize(d->icon->sizeFromIconSize(IconSize(KIconLoader::Desktop)));
00171 }
00172
00173 MenuLauncherApplet::~MenuLauncherApplet()
00174 {
00175 delete d;
00176 }
00177
00178 void MenuLauncherApplet::init()
00179 {
00180 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
00181 layout->setContentsMargins(0, 0, 0, 0);
00182 layout->setSpacing(0);
00183
00184 layout->addItem(d->icon);
00185
00186 KConfigGroup cg = config();
00187
00188 {
00189 QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("ViewType"));
00190 QByteArray ba = cg.readEntry("view", QByteArray(e.valueToKey(d->viewtype)));
00191 d->viewtype = (MenuLauncherApplet::ViewType) e.keyToValue(ba);
00192 }
00193 {
00194 QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("FormatType"));
00195 QByteArray ba = cg.readEntry("format", QByteArray(e.valueToKey(d->formattype)));
00196 d->formattype = (MenuLauncherApplet::FormatType) e.keyToValue(ba);
00197 }
00198
00199 d->icon->setIcon(KIcon(d->viewIcon()));
00200
00201
00202
00203 setAspectRatioMode(Plasma::ConstrainedSquare);
00204
00205 Kickoff::UrlItemLauncher::addGlobalHandler(Kickoff::UrlItemLauncher::ExtensionHandler,"desktop",new Kickoff::ServiceItemHandler);
00206 Kickoff::UrlItemLauncher::addGlobalHandler(Kickoff::UrlItemLauncher::ProtocolHandler, "leave", new Kickoff::LeaveItemHandler);
00207
00208 if (KService::serviceByStorageId("kde4-kmenuedit.desktop")) {
00209 QAction* menueditor = new QAction(i18n("Menu Editor"), this);
00210 d->actions.append(menueditor);
00211 connect(menueditor, SIGNAL(triggered(bool)), this, SLOT(startMenuEditor()));
00212 }
00213
00214 Q_ASSERT( ! d->switcher );
00215 d->switcher = new QAction(i18n("Switch to Kickoff Menu Style"), this);
00216 d->actions.append(d->switcher);
00217 connect(d->switcher, SIGNAL(triggered(bool)), this, SLOT(switchMenuStyle()));
00218
00219 constraintsEvent(Plasma::ImmutableConstraint);
00220 }
00221
00222 void MenuLauncherApplet::constraintsEvent(Plasma::Constraints constraints)
00223 {
00224 setBackgroundHints(NoBackground);
00225 if (constraints & Plasma::FormFactorConstraint) {
00226 if (formFactor() == Plasma::Planar ||
00227 formFactor() == Plasma::MediaCenter) {
00228
00229
00230 } else {
00231
00232 }
00233 }
00234
00235 if (constraints & Plasma::ImmutableConstraint) {
00236 d->switcher->setVisible(immutability() == Plasma::Mutable);
00237 }
00238 }
00239
00240 void MenuLauncherApplet::switchMenuStyle()
00241 {
00242 if (containment()) {
00243 containment()->addApplet("launcher", QVariantList(), geometry());
00244 destroy();
00245 }
00246 }
00247
00248 void MenuLauncherApplet::startMenuEditor()
00249 {
00250 KProcess::execute("kmenuedit");
00251 }
00252
00253 void MenuLauncherApplet::createConfigurationInterface(KConfigDialog *parent)
00254 {
00255 QWidget *p = new QWidget;
00256 QGridLayout *l = new QGridLayout(p);
00257 p->setLayout(l);
00258
00259 QLabel *viewLabel = new QLabel(i18nc("@label:listbox Which category of items to view in a KMenu-like menu", "View:"), p);
00260 l->addWidget(viewLabel, 0, 0);
00261 d->viewComboBox = new QComboBox(p);
00262 viewLabel->setBuddy(d->viewComboBox);
00263 d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Standard"), MenuLauncherApplet::Combined, "start-here-kde");
00264 d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Favorites"), MenuLauncherApplet::Favorites, "bookmarks");
00265 d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Applications"), MenuLauncherApplet::Applications, "applications-other");
00266 d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Computer"), MenuLauncherApplet::Computer, "computer");
00267 d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Recently Used"), MenuLauncherApplet::RecentlyUsed, "document-open-recent");
00268 d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Leave"), MenuLauncherApplet::Leave, "application-exit");
00269 l->addWidget(d->viewComboBox, 0, 1);
00270
00271 QLabel *formatLabel = new QLabel(i18nc("@label:listbox How to present applications in a KMenu-like menu", "Format:"), p);
00272 l->addWidget(formatLabel, 1, 0);
00273 d->formatComboBox = new QComboBox(p);
00274 formatLabel->setBuddy(d->formatComboBox);
00275 d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Name Only"), MenuLauncherApplet::Name);
00276 d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Description Only"), MenuLauncherApplet::Description);
00277 d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Name Description"), MenuLauncherApplet::NameDescription);
00278 d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Description (Name)"), MenuLauncherApplet::DescriptionName);
00279 l->addWidget(d->formatComboBox, 1, 1);
00280
00281 l->setColumnStretch(1,1);
00282
00283 d->setCurrentItem(d->viewComboBox, d->viewtype);
00284 d->setCurrentItem(d->formatComboBox, d->formattype);
00285
00286 parent->setButtons(KDialog::Ok | KDialog::Cancel | KDialog::Apply);
00287 connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
00288 connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
00289 parent->addPage(p, parent->windowTitle(), icon());
00290 }
00291
00292 void MenuLauncherApplet::configAccepted()
00293 {
00294 bool needssaving = false;
00295 KConfigGroup cg = config();
00296
00297 int vt = d->viewComboBox->itemData(d->viewComboBox->currentIndex()).toInt();
00298 if( vt != d->viewtype ) {
00299 d->viewtype = (MenuLauncherApplet::ViewType) vt;
00300 needssaving = true;
00301
00302 QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("ViewType"));
00303 cg.writeEntry("view", QByteArray(e.valueToKey(d->viewtype)));
00304
00305 d->icon->setIcon(KIcon(d->viewIcon()));
00306 d->icon->update();
00307 }
00308
00309 int ft = d->formatComboBox->itemData(d->formatComboBox->currentIndex()).toInt();
00310 if( ft != d->formattype ) {
00311 d->formattype = (MenuLauncherApplet::FormatType) ft;
00312 needssaving = true;
00313
00314 QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("FormatType"));
00315 cg.writeEntry("format", QByteArray(e.valueToKey(d->formattype)));
00316 }
00317
00318 if( needssaving ) {
00319 emit configNeedsSaving();
00320
00321 delete d->menuview;
00322 d->menuview = 0;
00323 }
00324 }
00325
00326 void MenuLauncherApplet::toggleMenu(bool pressed)
00327 {
00328 if (pressed) {
00329 toggleMenu();
00330 }
00331 }
00332
00333 void MenuLauncherApplet::toggleMenu()
00334 {
00335 if (!d->menuview) {
00336 d->menuview = new Kickoff::MenuView();
00337 connect(d->menuview, SIGNAL(triggered(QAction*)), this, SLOT(actionTriggered(QAction*)));
00338 connect(d->menuview, SIGNAL(aboutToHide()), d->icon, SLOT(setUnpressed()));
00339 connect(d->menuview, SIGNAL(aboutToHide()), d->menuview, SLOT(deleteLater()));
00340
00341 switch( d->viewtype ) {
00342 case Combined: {
00343 Kickoff::ApplicationModel *appModel = new Kickoff::ApplicationModel(d->menuview);
00344 appModel->setDuplicatePolicy(Kickoff::ApplicationModel::ShowLatestOnlyPolicy);
00345 Kickoff::MenuView *appview = d->createMenuView(appModel);
00346 d->addMenu(appview, false);
00347
00348 d->menuview->addSeparator();
00349 Kickoff::MenuView *favview = d->createMenuView(new Kickoff::FavoritesModel(d->menuview));
00350 d->addMenu(favview, false);
00351
00352 d->menuview->addSeparator();
00353 QAction *switchaction = d->menuview->addAction(KIcon("system-switch-user"),i18n("Switch User"));
00354 switchaction->setData(KUrl("leave:/switch"));
00355 QAction *lockaction = d->menuview->addAction(KIcon("system-lock-screen"),i18n("Lock"));
00356 lockaction->setData(KUrl("leave:/lock"));
00357 QAction *logoutaction = d->menuview->addAction(KIcon("system-shutdown"),i18n("Leave"));
00358 logoutaction->setData(KUrl("leave:/logout"));
00359 } break;
00360 case Favorites: {
00361 Kickoff::MenuView *favview = d->createMenuView(new Kickoff::FavoritesModel(d->menuview));
00362 d->addMenu(favview, true);
00363 } break;
00364 case Applications: {
00365 Kickoff::ApplicationModel *appModel = new Kickoff::ApplicationModel(d->menuview);
00366 appModel->setDuplicatePolicy(Kickoff::ApplicationModel::ShowLatestOnlyPolicy);
00367 Kickoff::MenuView *appview = d->createMenuView(appModel);
00368 d->addMenu(appview, false);
00369 } break;
00370 case Computer: {
00371 Kickoff::MenuView *systemview = d->createMenuView(new Kickoff::SystemModel(d->menuview));
00372 d->addMenu(systemview, true);
00373 } break;
00374 case RecentlyUsed: {
00375 Kickoff::MenuView *recentlyview = d->createMenuView(new Kickoff::RecentlyUsedModel(d->menuview));
00376 d->addMenu(recentlyview, true);
00377 } break;
00378 case Leave: {
00379 Kickoff::MenuView *leaveview = d->createMenuView(new Kickoff::LeaveModel(d->menuview));
00380 d->addMenu(leaveview, true);
00381 } break;
00382 }
00383 }
00384
00385 d->menuview->setAttribute(Qt::WA_DeleteOnClose);
00386 d->menuview->popup(popupPosition(d->menuview->sizeHint()));
00387 d->icon->setPressed();
00388 }
00389
00390 void MenuLauncherApplet::actionTriggered(QAction *action)
00391 {
00392 KUrl url = action->data().value<KUrl>();
00393 if (url.scheme() == "leave") {
00394 if ( ! d->launcher ) {
00395 d->launcher = new Kickoff::UrlItemLauncher(d->menuview);
00396 }
00397 d->launcher->openUrl(url.url());
00398 return;
00399 }
00400 for(QWidget* w = action->parentWidget(); w; w = w->parentWidget()) {
00401 if (Kickoff::MenuView *view = dynamic_cast<Kickoff::MenuView*>(w)) {
00402 view->actionTriggered(action);
00403 break;
00404 }
00405 }
00406 }
00407
00408 QList<QAction*> MenuLauncherApplet::contextualActions()
00409 {
00410 return d->actions;
00411 }
00412
00413 #include "simpleapplet.moc"