• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Applets

simpleapplet.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2007 Robert Knight <robertknight@gmail.com>
00003     Copyright 2008 Sebastian Sauer <mail@dipe.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 // Own
00022 #include "simpleapplet/simpleapplet.h"
00023 #include "simpleapplet/menuview.h"
00024 
00025 // Qt
00026 #include <QtGui/QLabel>
00027 #include <QtGui/QComboBox>
00028 #include <QtGui/QSpinBox>
00029 #include <QtGui/QGridLayout>
00030 #include <QtGui/QGraphicsView>
00031 #include <QtCore/QMetaObject>
00032 #include <QtCore/QMetaEnum>
00033 #include <QtCore/QPointer>
00034 #include <QtGui/QGraphicsLinearLayout>
00035 #include <QtGui/QSpacerItem>
00036 
00037 // KDE
00038 #include <KIcon>
00039 #include <KConfigDialog>
00040 #include <KMenu>
00041 #include <KProcess>
00042 #include <KActionCollection>
00043 #include <KBookmarkMenu>
00044 #include <KRun>
00045 
00046 // Plasma
00047 #include <Plasma/IconWidget>
00048 #include <Plasma/Containment>
00049 #include <Plasma/ToolTipManager>
00050 
00051 // Local
00052 #include "core/itemhandlers.h"
00053 #include "core/models.h"
00054 #include "core/applicationmodel.h"
00055 #include "core/favoritesmodel.h"
00056 #include "core/systemmodel.h"
00057 #include "core/recentlyusedmodel.h"
00058 #include "core/recentapplications.h"
00059 #include "core/leavemodel.h"
00060 #include "core/urlitemlauncher.h"
00061 
00062 class BookmarkOwner : public KBookmarkOwner
00063 {
00064 public:
00065     BookmarkOwner() : KBookmarkOwner() {}
00066     virtual bool enableOption(BookmarkOption) const {
00067         return false;
00068     }
00069     virtual bool supportsTabs() const {
00070         return false;
00071     }
00072     virtual void openBookmark(const KBookmark& b, Qt::MouseButtons, Qt::KeyboardModifiers) {
00073         new KRun(b.url(), (QWidget*)0);
00074     }
00075 };
00076 
00078 class MenuLauncherApplet::Private
00079 {
00080 public:
00081     QPointer<Kickoff::MenuView> menuview;
00082     Plasma::IconWidget *icon;
00083     QPointer<Kickoff::UrlItemLauncher> launcher;
00084 
00085     KActionCollection* collection;
00086     BookmarkOwner* bookmarkowner;
00087     KBookmarkMenu* bookmarkmenu;
00088 
00089     MenuLauncherApplet::ViewType viewtype;
00090     MenuLauncherApplet::FormatType formattype;
00091     int maxRecentApps;
00092 
00093     QComboBox *viewComboBox;
00094     QComboBox *formatComboBox;
00095     QSpinBox *recentApplicationsSpinBox;
00096 
00097     QList<QAction*> actions;
00098     QAction* switcher;
00099 
00100     Private()
00101             : menuview(0),
00102             icon(0),
00103             launcher(0),
00104             collection(0),
00105             bookmarkowner(0),
00106             bookmarkmenu(0),
00107             viewComboBox(0),
00108             formatComboBox(0),
00109             switcher(0) {}
00110     ~Private() {
00111         delete bookmarkmenu;
00112         delete bookmarkowner;
00113         delete menuview;
00114     }
00115 
00116     void setMaxRecentApps(int num) {
00117         maxRecentApps = qMax(0, num);
00118         if (maxRecentApps > Kickoff::RecentApplications::self()->maximum()) {
00119             Kickoff::RecentApplications::self()->setMaximum(maxRecentApps);
00120         }
00121     }
00122 
00123     void addItem(QComboBox* combo, const QString& caption, int index, const QString& icon = QString()) {
00124         if (icon.isEmpty()) {
00125             combo->addItem(caption, index);
00126         } else {
00127             combo->addItem(KIcon(icon), caption, index);
00128         }
00129     }
00130 
00131     void setCurrentItem(QComboBox* combo, int currentIndex) {
00132         for (int i = combo->count() - 1; i >= 0; --i) {
00133             if (combo->itemData(i).toInt() == currentIndex) {
00134                 combo->setCurrentIndex(i);
00135                 return;
00136             }
00137         }
00138         if (combo->count() > 0) {
00139             combo->setCurrentIndex(0);
00140         }
00141     }
00142 
00143     Kickoff::MenuView *createMenuView(QAbstractItemModel *model = 0) {
00144         Kickoff::MenuView *view = new Kickoff::MenuView(menuview);
00145         view->setFormatType((Kickoff::MenuView::FormatType) formattype);
00146         if (model) {
00147             view->setModel(model);
00148         }
00149         return view;
00150     }
00151 
00152     void addMenu(Kickoff::MenuView *view, bool mergeFirstLevel) {
00153         QList<QAction*> actions = view->actions();
00154         foreach(QAction *action, actions) {
00155             if (action->menu() && mergeFirstLevel) {
00156                 QMetaObject::invokeMethod(action->menu(), "aboutToShow"); //fetch the children
00157                 if (actions.count() > 1 && action->menu()->actions().count() > 0) {
00158                     menuview->addTitle(action->text());
00159                 }
00160                 foreach(QAction *a, action->menu()->actions()) {
00161                     a->setVisible(a->menu() || ! view->indexForAction(a).data(Kickoff::UrlRole).isNull());
00162                     menuview->addAction(a);
00163                 }
00164             } else {
00165                 action->setVisible(action->menu() || ! view->indexForAction(action).data(Kickoff::UrlRole).isNull());
00166                 menuview->addAction(action);
00167             }
00168         }
00169 
00170         // if the model asks us for a reset we can't do much except to invalidate our
00171         // menuview to be able to rebuild it what is needed to prevent dealing with
00172         // invalid items.
00173         // the problem here is, that if the menu is currently displayed, it will just
00174         // close itself what is evil++ but still better than crashes. anyway, the
00175         // right(TM) solution would be to introduce logic to update the content of the
00176         // menu even on a reset.
00177         connect(view->model(), SIGNAL(modelReset()), menuview, SLOT(deleteLater()));
00178     }
00179 
00180     QString viewIcon() {
00181         switch (viewtype) {
00182         case Combined:
00183             return "start-here-kde";
00184         case Favorites:
00185             return "bookmarks";
00186         case Bookmarks:
00187             return "folder-bookmarks";
00188         case Applications:
00189             return "applications-other";
00190         case Computer:
00191             return "computer";
00192         case RecentlyUsed:
00193             return "document-open-recent";
00194         case Leave:
00195             return "application-exit";
00196         }
00197         return QString();
00198     }
00199     
00200 
00201 };
00202 
00203 MenuLauncherApplet::MenuLauncherApplet(QObject *parent, const QVariantList &args)
00204         : Plasma::Applet(parent, args),
00205         d(new Private)
00206 {
00207     KGlobal::locale()->insertCatalog("plasma_applet_launcher");
00208 
00209     setHasConfigurationInterface(true);
00210     setBackgroundHints(NoBackground);
00211 
00212     resize(IconSize(KIconLoader::Desktop) * 2, IconSize(KIconLoader::Desktop) * 2);
00213 
00214     d->icon = new Plasma::IconWidget(QString(), this);
00215     d->icon->setFlag(ItemIsMovable, false);
00216     connect(d->icon, SIGNAL(pressed(bool)), this, SLOT(toggleMenu(bool)));
00217     connect(this, SIGNAL(activate()), this, SLOT(toggleMenu()));
00218 
00219     d->viewtype = Combined;
00220     d->formattype = NameDescription;
00221 }
00222 
00223 MenuLauncherApplet::~MenuLauncherApplet()
00224 {
00225     delete d;
00226 }
00227 
00228 void MenuLauncherApplet::init()
00229 {
00230     QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
00231     layout->setContentsMargins(0, 0, 0, 0);
00232     layout->setSpacing(0);
00233 
00234     layout->addItem(d->icon);
00235 
00236     KConfigGroup cg = config();
00237 
00238     QMetaEnum vte = metaObject()->enumerator(metaObject()->indexOfEnumerator("ViewType"));
00239     QByteArray vtb = cg.readEntry("view", QByteArray(vte.valueToKey(d->viewtype)));
00240     d->viewtype = (MenuLauncherApplet::ViewType) vte.keyToValue(vtb);
00241 
00242     QMetaEnum fte = metaObject()->enumerator(metaObject()->indexOfEnumerator("FormatType"));
00243     QByteArray ftb = cg.readEntry("format", QByteArray(fte.valueToKey(d->formattype)));
00244     d->formattype = (MenuLauncherApplet::FormatType) fte.keyToValue(ftb);
00245 
00246     d->setMaxRecentApps(cg.readEntry("maxRecentApps", qMin(5, Kickoff::RecentApplications::self()->maximum())));
00247 
00248     d->icon->setIcon(KIcon(d->viewIcon()));
00249     //d->icon->setIcon(KIcon(cg.readEntry("icon","start-here-kde")));
00250     //setMinimumContentSize(d->icon->iconSize()); //setSize(d->icon->iconSize())
00251 
00252     setAspectRatioMode(Plasma::ConstrainedSquare);
00253 
00254     Kickoff::UrlItemLauncher::addGlobalHandler(Kickoff::UrlItemLauncher::ExtensionHandler, "desktop", new Kickoff::ServiceItemHandler);
00255     Kickoff::UrlItemLauncher::addGlobalHandler(Kickoff::UrlItemLauncher::ProtocolHandler, "leave", new Kickoff::LeaveItemHandler);
00256 
00257     if (KService::serviceByStorageId("kde4-kmenuedit.desktop")) {
00258         QAction* menueditor = new QAction(i18n("Menu Editor"), this);
00259         d->actions.append(menueditor);
00260         connect(menueditor, SIGNAL(triggered(bool)), this, SLOT(startMenuEditor()));
00261     }
00262 
00263     Q_ASSERT(! d->switcher);
00264     d->switcher = new QAction(i18n("Switch to Kickoff Menu Style"), this);
00265     d->actions.append(d->switcher);
00266     connect(d->switcher, SIGNAL(triggered(bool)), this, SLOT(switchMenuStyle()));
00267 
00268     constraintsEvent(Plasma::ImmutableConstraint);
00269 }
00270 
00271 void MenuLauncherApplet::constraintsEvent(Plasma::Constraints constraints)
00272 {
00273     setBackgroundHints(NoBackground);
00274     if (constraints & Plasma::FormFactorConstraint) {
00275         if (formFactor() == Plasma::Planar ||
00276                 formFactor() == Plasma::MediaCenter) {
00277             //FIXME set correct minimum size
00278             //setMinimumContentSize(d->icon->sizeFromIconSize(IconSize(KIconLoader::Desktop)));
00279         } else {
00280             //setMinimumContentSize(d->icon->sizeFromIconSize(IconSize(KIconLoader::Small)));
00281         }
00282     }
00283 
00284     if ((constraints & Plasma::ImmutableConstraint) && d->switcher) {
00285         d->switcher->setVisible(immutability() == Plasma::Mutable);
00286     }
00287 }
00288 
00289 void MenuLauncherApplet::switchMenuStyle()
00290 {
00291     if (containment()) {
00292         containment()->addApplet("launcher", QVariantList(), geometry());
00293         destroy();
00294     }
00295 }
00296 
00297 void MenuLauncherApplet::startMenuEditor()
00298 {
00299     KProcess::execute("kmenuedit");
00300 }
00301 
00302 void MenuLauncherApplet::createConfigurationInterface(KConfigDialog *parent)
00303 {
00304     QWidget *p = new QWidget(parent);
00305     QGridLayout *l = new QGridLayout(p);
00306     p->setLayout(l);
00307 
00308     QLabel *viewLabel = new QLabel(i18nc("@label:listbox Which category of items to view in a KMenu-like menu", "View:"), p);
00309     l->addWidget(viewLabel, 0, 0, Qt::AlignRight);
00310     d->viewComboBox = new QComboBox(p);
00311     viewLabel->setBuddy(d->viewComboBox);
00312     d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Standard"), MenuLauncherApplet::Combined, "start-here-kde");
00313     d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Favorites"), MenuLauncherApplet::Favorites, "bookmarks");
00314     d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Bookmarks"), MenuLauncherApplet::Bookmarks, "folder-bookmarks");
00315     d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Applications"), MenuLauncherApplet::Applications, "applications-other");
00316     d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Computer"), MenuLauncherApplet::Computer, "computer");
00317     d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Recently Used"), MenuLauncherApplet::RecentlyUsed, "document-open-recent");
00318     d->addItem(d->viewComboBox, i18nc("@item:inlistbox View:", "Leave"), MenuLauncherApplet::Leave, "application-exit");
00319     l->addWidget(d->viewComboBox, 0, 1);
00320 
00321     QLabel *formatLabel = new QLabel(i18nc("@label:listbox How to present applications in a KMenu-like menu", "Format:"), p);
00322     l->addWidget(formatLabel, 1, 0, Qt::AlignRight);
00323     d->formatComboBox = new QComboBox(p);
00324     formatLabel->setBuddy(d->formatComboBox);
00325     d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Name Only"), MenuLauncherApplet::Name);
00326     d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Description Only"), MenuLauncherApplet::Description);
00327     d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Name Description"), MenuLauncherApplet::NameDescription);
00328     d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Description (Name)"), MenuLauncherApplet::DescriptionName);
00329     d->addItem(d->formatComboBox, i18nc("@item:inlistbox Format:", "Name - Description"), MenuLauncherApplet::NameDashDescription);
00330     l->addWidget(d->formatComboBox, 1, 1);
00331 
00332     QLabel *recentLabel = new QLabel(i18n("Recent Applications:"), p);
00333     l->addWidget(recentLabel, 2, 0, Qt::AlignRight);
00334     d->recentApplicationsSpinBox = new QSpinBox(p);
00335     d->recentApplicationsSpinBox->setMaximum(10);
00336     d->recentApplicationsSpinBox->setMinimum(0);
00337     d->recentApplicationsSpinBox->setValue(d->maxRecentApps);
00338     recentLabel->setBuddy(d->recentApplicationsSpinBox);
00339     l->addWidget(d->recentApplicationsSpinBox, 2, 1);
00340 
00341     l->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 3, 0, 1, 2);
00342     l->setColumnStretch(1, 1);
00343 
00344     d->setCurrentItem(d->viewComboBox, d->viewtype);
00345     d->setCurrentItem(d->formatComboBox, d->formattype);
00346 
00347     connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
00348     connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
00349     parent->addPage(p, i18n("General"), icon());
00350 }
00351 
00352 void MenuLauncherApplet::configAccepted()
00353 {
00354     bool needssaving = false;
00355     KConfigGroup cg = config();
00356 
00357     const int vt = d->viewComboBox->itemData(d->viewComboBox->currentIndex()).toInt();
00358     if (vt != d->viewtype) {
00359         d->viewtype = (MenuLauncherApplet::ViewType) vt;
00360         needssaving = true;
00361 
00362         QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("ViewType"));
00363         cg.writeEntry("view", QByteArray(e.valueToKey(d->viewtype)));
00364 
00365         d->icon->setIcon(KIcon(d->viewIcon()));
00366         d->icon->update();
00367     }
00368 
00369     const int ft = d->formatComboBox->itemData(d->formatComboBox->currentIndex()).toInt();
00370     if (ft != d->formattype) {
00371         d->formattype = (MenuLauncherApplet::FormatType) ft;
00372         needssaving = true;
00373 
00374         QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("FormatType"));
00375         cg.writeEntry("format", QByteArray(e.valueToKey(d->formattype)));
00376     }
00377 
00378     const int maxRecentApps = d->recentApplicationsSpinBox->value();
00379     if (maxRecentApps != d->maxRecentApps) {
00380         needssaving = true;
00381         d->setMaxRecentApps(maxRecentApps);
00382         cg.writeEntry("maxRecentApps", maxRecentApps);
00383     }
00384 
00385     if (needssaving) {
00386         emit configNeedsSaving();
00387 
00388         delete d->menuview;
00389         d->menuview = 0;
00390     }
00391 }
00392 
00393 void MenuLauncherApplet::toggleMenu(bool pressed)
00394 {
00395     if (pressed) {
00396         toggleMenu();
00397     }
00398 }
00399 
00400 void MenuLauncherApplet::toggleMenu()
00401 {
00402     if (!d->menuview) {
00403         d->menuview = new Kickoff::MenuView();
00404         connect(d->menuview, SIGNAL(triggered(QAction*)), this, SLOT(actionTriggered(QAction*)));
00405         connect(d->menuview, SIGNAL(aboutToHide()), d->icon, SLOT(setUnpressed()));
00406         connect(d->menuview, SIGNAL(aboutToHide()), d->menuview, SLOT(deleteLater()));
00407 
00408         switch (d->viewtype) {
00409         case Combined: {
00410 //if (Kickoff::RecentApplications::self()->recentApplications().size() > 0) {
00411             if (d->maxRecentApps > 0) {
00412                 d->menuview->addTitle(i18n("Recently Used Applications"));
00413                 Kickoff::RecentlyUsedModel* recentlymodel = new Kickoff::RecentlyUsedModel(d->menuview, Kickoff::RecentlyUsedModel::ApplicationsOnly, d->maxRecentApps);
00414                 Kickoff::MenuView *recentlyview = d->createMenuView(recentlymodel);
00415                 d->addMenu(recentlyview, true);
00416             }
00417 
00418             d->menuview->addTitle(i18n("All Applications"));
00419             Kickoff::ApplicationModel *appModel = new Kickoff::ApplicationModel(d->menuview);
00420             appModel->setDuplicatePolicy(Kickoff::ApplicationModel::ShowLatestOnlyPolicy);
00421             appModel->setSystemApplicationPolicy(Kickoff::ApplicationModel::ShowApplicationAndSystemPolicy);
00422             Kickoff::MenuView *appview = d->createMenuView(appModel);
00423             d->addMenu(appview, false);
00424 
00425             d->menuview->addSeparator();
00426             Kickoff::MenuView *favview = d->createMenuView(new Kickoff::FavoritesModel(d->menuview));
00427             d->addMenu(favview, false);
00428 
00429             d->menuview->addTitle(i18n("Actions"));
00430             QAction *runaction = d->menuview->addAction(KIcon("system-run"), i18n("Run Command..."));
00431             runaction->setData(KUrl("leave:/run"));
00432             d->menuview->addSeparator();
00433             QAction *switchaction = d->menuview->addAction(KIcon("system-switch-user"), i18n("Switch User"));
00434             switchaction->setData(KUrl("leave:/switch"));
00435             QAction *lockaction = d->menuview->addAction(KIcon("system-lock-screen"), i18n("Lock Screen"));
00436             lockaction->setData(KUrl("leave:/lock"));
00437             QAction *logoutaction = d->menuview->addAction(KIcon("system-shutdown"), i18n("Leave..."));
00438             logoutaction->setData(KUrl("leave:/logout"));
00439         }
00440         break;
00441         case Favorites: {
00442             Kickoff::MenuView *favview = d->createMenuView(new Kickoff::FavoritesModel(d->menuview));
00443             d->addMenu(favview, true);
00444         }
00445         break;
00446         case Applications: {
00447             Kickoff::ApplicationModel *appModel = new Kickoff::ApplicationModel(d->menuview);
00448             appModel->setDuplicatePolicy(Kickoff::ApplicationModel::ShowLatestOnlyPolicy);
00449             Kickoff::MenuView *appview = d->createMenuView(appModel);
00450             d->addMenu(appview, false);
00451         }
00452         break;
00453         case Computer: {
00454             Kickoff::MenuView *systemview = d->createMenuView(new Kickoff::SystemModel(d->menuview));
00455             d->addMenu(systemview, true);
00456         }
00457         break;
00458         case RecentlyUsed: {
00459             Kickoff::MenuView *recentlyview = d->createMenuView(new Kickoff::RecentlyUsedModel(d->menuview));
00460             d->addMenu(recentlyview, true);
00461         }
00462         break;
00463         case Bookmarks: {
00464             KBookmarkManager* mgr = KBookmarkManager::userBookmarksManager();
00465             if (! d->collection) {
00466                 d->collection = new KActionCollection(this);
00467                 d->bookmarkowner = new BookmarkOwner();
00468             }
00469             delete d->bookmarkmenu;
00470             d->bookmarkmenu = new KBookmarkMenu(mgr, d->bookmarkowner, d->menuview, d->collection);
00471         }
00472         break;
00473         case Leave: {
00474             Kickoff::MenuView *leaveview = d->createMenuView(new Kickoff::LeaveModel(d->menuview));
00475             d->addMenu(leaveview, true);
00476         }
00477         break;
00478         }
00479     }
00480 
00481     d->menuview->setAttribute(Qt::WA_DeleteOnClose);
00482     d->menuview->popup(popupPosition(d->menuview->sizeHint()));
00483     d->icon->setPressed();
00484 }
00485 
00486 void MenuLauncherApplet::actionTriggered(QAction *action)
00487 {
00488     KUrl url = action->data().value<KUrl>();
00489     if (url.scheme() == "leave") {
00490         if (! d->launcher) {
00491             d->launcher = new Kickoff::UrlItemLauncher(d->menuview);
00492         }
00493         d->launcher->openUrl(url.url());
00494         return;
00495     }
00496     for (QWidget* w = action->parentWidget(); w; w = w->parentWidget()) {
00497         if (Kickoff::MenuView *view = dynamic_cast<Kickoff::MenuView*>(w)) {
00498             view->actionTriggered(action);
00499             break;
00500         }
00501     }
00502 }
00503 
00504 QList<QAction*> MenuLauncherApplet::contextualActions()
00505 {
00506     return d->actions;
00507 }
00508 
00509 
00510 #include "simpleapplet.moc"

Applets

Skip menu "Applets"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal