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

Applets

quicklaunchApplet.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2008 by Lukas Appelhans                                 *
00003  *   l.appelhans@gmx.de                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program 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         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
00019  ***************************************************************************/
00020 #include "quicklaunchApplet.h"
00021 
00022 #include <KConfigDialog>
00023 #include <KDesktopFile>
00024 #include <QGraphicsSceneDragDropEvent>
00025 #include <QGraphicsWidget>
00026 #include <QDrag>
00027 #include <QMouseEvent>
00028 #include <QMimeData>
00029 #include <QToolButton>
00030 
00031 #include <KDialog>
00032 #include <KMimeType>
00033 #include <KStandardDirs>
00034 #include <KWindowSystem>
00035 
00036 #include <plasma/containment.h>
00037 #include <plasma/dialog.h>
00038 #include <plasma/corona.h>
00039 
00040 #include "math.h"
00041 
00042 static const int s_defaultIconSize = 16;
00043 static const int s_defaultSpacing = 2;
00044 
00045 QuicklaunchApplet::QuicklaunchApplet(QObject *parent, const QVariantList &args)
00046   : Plasma::Applet(parent, args),
00047     m_visibleIcons(6),
00048     m_rowCount(2),
00049     m_dialogRowCount(2),
00050     m_dialog(0),
00051     m_dialogWidget(0),
00052     m_dialogLayout(0),
00053     m_addDialog(0),
00054     m_rightClickedIcon(0),
00055     m_addAction(0),
00056     m_removeAction(0)
00057 {
00058     setHasConfigurationInterface(true);
00059     setAcceptDrops(true);
00060     setAspectRatioMode(Plasma::IgnoreAspectRatio);
00061 
00062     // set our default size here
00063     resize((m_visibleIcons / m_rowCount) * s_defaultIconSize +
00064             (s_defaultSpacing * (m_visibleIcons + 1)),
00065            m_rowCount * 22 + s_defaultSpacing * 3);
00066 }
00067 
00068 QuicklaunchApplet::~QuicklaunchApplet()
00069 {
00070     if (m_dialog) {
00071         m_dialog->close();
00072         delete m_dialog;
00073     }
00074 
00075     delete m_dialogWidget;
00076 }
00077 
00078 void QuicklaunchApplet::saveState(KConfigGroup &config) const
00079 {
00080     QStringList iconUrls;
00081     foreach (QuicklaunchIcon * container, m_icons) {
00082         iconUrls.append(container->url().prettyUrl());
00083     }
00084 
00085     config.writeEntry("iconUrls", iconUrls);
00086 }
00087 
00088 void QuicklaunchApplet::init()
00089 {
00090     KConfigGroup cg = config();
00091     m_rowCount = qMax(1, cg.readEntry("rowCount", m_rowCount));
00092     m_visibleIcons = qMax(1, cg.readEntry("visibleIcons", m_visibleIcons));
00093     m_dialogRowCount = qMax(1, cg.readEntry("dialogRowCount", m_dialogRowCount));
00094 
00095     // Initialize outer layout
00096     m_layout = new QGraphicsLinearLayout(this);
00097     m_layout->setContentsMargins(0, 0, 0, 0);
00098     m_layout->setSpacing(0);
00099     setLayout(m_layout);
00100 
00101     // Initialize inner layout
00102     m_innerLayout = new QuicklaunchLayout(0, m_rowCount);
00103     m_innerLayout->setContentsMargins(0, 0, 0, 0);
00104     m_innerLayout->setSpacing(0);
00105     m_layout->addItem(m_innerLayout);
00106 
00107     // Initial "more icons" arrow
00108     m_arrow = new Plasma::IconWidget(this);
00109     m_arrow->setIcon(KIcon("arrow-right"));
00110     connect(m_arrow, SIGNAL(clicked()), SLOT(showDialog()));
00111 
00112     QStringList desktopFiles = cg.readEntry("iconUrls", QStringList());
00113 
00114     if (desktopFiles.isEmpty()) {
00115         QStringList defaultApps;
00116         defaultApps << "konqbrowser" << "dolphin" << "kopete";
00117 
00118         foreach (const QString &defaultApp, defaultApps) {
00119             KService::Ptr service = KService::serviceByStorageId(defaultApp);
00120             if (service && service->isValid()) {
00121                 QString path = service->entryPath();
00122                 kDebug() << path;
00123                 if (!path.isEmpty() && QDir::isAbsolutePath(path)) {
00124                     desktopFiles << path;
00125                 }
00126             }
00127         }
00128         kDebug() << desktopFiles;
00129     }
00130 
00131     loadPrograms(desktopFiles);
00132     refactorUi();
00133 }
00134 
00135 QSizeF QuicklaunchApplet::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
00136 {
00137     if (which == Qt::PreferredSize) {
00138         QSizeF sizeHint = size();
00139         if (m_icons.size() > m_visibleIcons) {
00140             sizeHint.setWidth(sizeHint.height() / m_innerLayout->rowCount() * m_innerLayout->columnCount() + size().height());
00141         } else {
00142             sizeHint.setWidth(sizeHint.height() / m_innerLayout->rowCount() * m_innerLayout->columnCount());
00143         }
00144         return sizeHint;
00145     }
00146     return QGraphicsWidget::sizeHint(which, constraint);
00147 }
00148 
00149 void QuicklaunchApplet::constraintsEvent(Plasma::Constraints constraints)
00150 {
00151     if (constraints & Plasma::SizeConstraint) {
00152         //TODO: don't call so often
00153         refactorUi();
00154     }
00155 }
00156 
00157 void QuicklaunchApplet::refactorUi()
00158 {
00159     clearLayout(m_innerLayout);
00160 
00161     if (m_dialogLayout) {
00162         clearLayout(m_dialogLayout);
00163         m_dialogLayout->setRowCount(m_dialogRowCount);
00164     }
00165     int rowCount;
00166     int iconWidth;
00167     if (formFactor() == Plasma::Vertical) {
00168         rowCount = qMin(m_rowCount, int(size().width()) / (s_defaultIconSize + s_defaultSpacing));
00169         // prevent possible division by zero if size().width() is 0
00170         rowCount = qMax(1, rowCount );
00171         iconWidth = size().width() / rowCount;
00172     } else {
00173         rowCount = qMin(m_rowCount, int(size().height()) / (s_defaultIconSize + s_defaultSpacing));
00174         // prevent possible division by zero if size().height() is 0
00175         rowCount = qMax(1, rowCount );
00176         iconWidth = qMax(s_defaultIconSize, int(size().height()) / rowCount);
00177     }
00178 
00179     m_innerLayout->setRowCount(rowCount);
00180     const QSizeF minSize = QSizeF(iconWidth, iconWidth);
00181     const QSizeF maxSize = QSizeF(iconWidth, iconWidth);
00182     int count = 0;
00183     kDebug() << m_icons.count() << iconWidth << "pixel icons in" << rowCount
00184              << "rows, with a max of" << m_visibleIcons << "visible";
00185     foreach (QuicklaunchIcon *icon, m_icons) {
00186         //icon->setMinimumSize(minSize);
00187         //icon->setMaximumSize(maxSize);
00188         icon->resize(minSize);
00189 
00190         if (count < m_visibleIcons || m_visibleIcons == -1) {
00191             icon->show();
00192             m_innerLayout->addItem(icon);
00193         } else if (m_dialogLayout) {
00194             icon->setMinimumSize(minSize);
00195             icon->setMaximumSize(maxSize);
00196             icon->show();
00197             m_dialogLayout->addItem(icon);
00198         } else {
00199             icon->hide();
00200         }
00201 
00202         ++count;
00203     }
00204 
00205     m_layout->removeItem(m_arrow);
00206     if (count > m_visibleIcons && m_visibleIcons != -1) {
00207         //m_arrow->setMinimumSize(minSize);
00208         //m_arrow->setMaximumSize(maxSize);
00209         m_arrow->resize(minSize);
00210         m_layout->addItem(m_arrow);
00211         m_arrow->show();
00212     } else {
00213         m_arrow->hide();
00214     }
00215 
00216     if (m_dialog) {
00217         m_dialog->close();
00218         m_dialogLayout->updateGeometry();
00219         m_dialog->adjustSize();
00220     }
00221     m_innerLayout->updateGeometry();
00222     m_layout->updateGeometry();
00223 }
00224 
00225 void QuicklaunchApplet::showDialog()
00226 {
00227     if (!m_dialog) {
00228         m_dialogWidget = new QGraphicsWidget(this);
00229         m_dialogWidget->setAcceptDrops(true);
00230         m_dialogWidget->installEventFilter(this);
00231         qobject_cast<Plasma::Corona*>(m_dialogWidget->scene())->addOffscreenWidget(m_dialogWidget);
00232 
00233         // Initialize "more icons" dialog
00234         m_dialog = new Plasma::Dialog(0, Qt::X11BypassWindowManagerHint);
00235         m_dialog->setAcceptDrops(true);
00236         //m_dialog->installEventFilter(this);
00237         m_dialog->setContextMenuPolicy(Qt::ActionsContextMenu);
00238         m_dialogLayout = new QuicklaunchLayout(m_dialogWidget, m_dialogRowCount);
00239         m_dialogWidget->setLayout(m_dialogLayout);
00240         refactorUi();
00241         m_dialog->setGraphicsWidget(m_dialogWidget);
00242     }
00243 
00244     if (m_dialog->isVisible()) {
00245         m_dialog->hide();
00246     } else {
00247         m_dialog->resize(m_dialogLayout->preferredSize().toSize());
00248         //m_dialog->updateGeometry();
00249         if(containment() && containment()->corona()) {
00250             kDebug() << "position:" << containment()->corona()->popupPosition(m_arrow, m_dialog->size()) << "dialog size:" << m_dialog->size() << "layout preferred-size:" << m_dialogLayout->preferredSize().toSize();
00251             m_dialog->move(containment()->corona()->popupPosition(m_arrow, m_dialog->size()));
00252         }
00253         KWindowSystem::setState(m_dialog->winId(), NET::SkipTaskbar);
00254         //QPoint(popupPosition(m_dialog->sizeHint()).x() + (m_visibleIcons) * size().height() / m_rowCount, 
00255         //               popupPosition(m_dialog->sizeHint()).y()));
00256         m_dialog->show();
00257     }
00258 }
00259 
00260 void QuicklaunchApplet::createConfigurationInterface(KConfigDialog *parent)
00261 {
00262     QWidget *widget = new QWidget(parent);
00263     uiConfig.setupUi(widget);
00264     connect(parent, SIGNAL(accepted()), SLOT(configAccepted()));
00265     uiConfig.rowCount->setValue(m_rowCount);
00266     uiConfig.dialogRowCount->setValue(m_dialogRowCount);
00267     uiConfig.dialogRowCount->hide();
00268     uiConfig.dialogrowLabel->hide();
00269     uiConfig.icons->setValue(m_visibleIcons);
00270     parent->addPage(widget, i18n("General"), icon());
00271 }
00272 
00273 void QuicklaunchApplet::configAccepted()
00274 {
00275     bool changed = false;
00276     int temp = uiConfig.rowCount->value();
00277 
00278     KConfigGroup cg = config();
00279     if (temp != m_rowCount) {
00280         m_rowCount = temp;
00281         cg.writeEntry("rowCount", m_rowCount);
00282         changed = true;
00283     }
00284 
00285     temp = uiConfig.icons->value();
00286     if (temp != m_visibleIcons) {
00287         m_visibleIcons = temp;
00288         cg.writeEntry("visibleIcons", m_visibleIcons);
00289         changed = true;
00290     }
00291 
00292     temp = uiConfig.dialogRowCount->value();
00293     if (temp != m_dialogRowCount) {
00294         m_dialogRowCount = temp;
00295         cg.writeEntry("dialogRowCount", m_dialogRowCount);
00296         changed = true;
00297     }
00298 
00299     if (changed) {
00300         emit configNeedsSaving();
00301         refactorUi();
00302     }
00303 }
00304 
00305 QList<QAction*> QuicklaunchApplet::contextActions(QuicklaunchIcon *icon)
00306 {
00307     QList<QAction*> tempActions;
00308     if (!m_addAction) {
00309         m_addAction = new QAction(KIcon("list-add"), i18n("Add Icon..."), this);
00310         connect(m_addAction, SIGNAL(triggered(bool)), this, SLOT(showAddInterface()));
00311     }
00312 
00313     tempActions << m_addAction;
00314 
00315     if (icon) {
00316         m_rightClickedIcon = icon;
00317         if (!m_removeAction) {
00318             m_removeAction = new QAction(KIcon("list-remove"), i18n("Remove Icon"), this);
00319             connect(m_removeAction, SIGNAL(triggered(bool)), this, SLOT(removeCurrentIcon()));
00320         }
00321         tempActions << m_removeAction;
00322     }
00323 
00324     return tempActions;
00325 }
00326 
00327 bool QuicklaunchApplet::eventFilter(QObject * object, QEvent * event)
00328 {
00329     Q_UNUSED(object)
00330     if (event->type() == QEvent::GraphicsSceneDrop) {
00331         dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(event));
00332         return true;
00333     }
00334     return QObject::eventFilter(object, event);
00335 }
00336 
00337 void QuicklaunchApplet::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
00338 {
00339     event->setDropAction(Qt::MoveAction);
00340     event->setAccepted(event->mimeData()->hasUrls());
00341 }
00342 
00343 void QuicklaunchApplet::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
00344 {
00345     event->setDropAction(Qt::MoveAction);
00346     event->setAccepted(event->mimeData()->hasUrls());
00347 }
00348 
00349 void QuicklaunchApplet::dropEvent(QGraphicsSceneDragDropEvent *event)
00350 {
00351     // Calculate position
00352     QPointF point = mapFromScene(event->scenePos());
00353     int rowCount = m_innerLayout->rowCount();
00354     int cols = static_cast<int>(ceil(1.0 * qMin(m_icons.size(), m_visibleIcons) / rowCount));
00355     int col = static_cast<int>((round(point.x()) * cols / m_innerLayout->geometry().width()));
00356     col = (col >= cols) ? col - 1 : col;
00357     int row = static_cast<int>(floor(point.y() * rowCount / m_innerLayout->geometry().height()));
00358     row = (row >= m_rowCount) ? row - 1 : row;
00359     int pos = row * cols + col;
00360 
00361     if (pos >= m_icons.size()) {
00362         pos = m_icons.size() - 1;
00363     }
00364 
00365     if (dropHandler(pos, event->mimeData())) {
00366         event->setDropAction(Qt::MoveAction);
00367         event->accept();
00368         saveConfig();
00369         refactorUi();
00370     }
00371 }
00372 
00373 void QuicklaunchApplet::addProgram(int index, const QString &url)
00374 {
00375     if (index < 0 || index > m_icons.size()) {
00376         index = m_icons.size();
00377     }
00378     if( url.isEmpty() )
00379         return;
00380     KUrl appUrl = KUrl(url);
00381     KIcon icon;
00382 
00383     if (appUrl.isLocalFile() && KDesktopFile::isDesktopFile(appUrl.toLocalFile())) {
00384         KDesktopFile *f = new KDesktopFile(appUrl.toLocalFile());
00385         icon = KIcon(f->readIcon());
00386         delete f;
00387     } else {
00388         icon = KIcon(KMimeType::iconNameForUrl(appUrl));
00389     }
00390 
00391     if (icon.isNull()) {
00392         icon = KIcon("unknown");
00393     }
00394 
00395     QuicklaunchIcon *container = new QuicklaunchIcon(appUrl, icon, this);
00396     container->installEventFilter(this);
00397     m_icons.insert(index, container);
00398 }
00399 
00400 void QuicklaunchApplet::loadPrograms(const QStringList &desktopFiles)
00401 {
00402     foreach (const QString &desktopFile, desktopFiles) {
00403         addProgram(-1, desktopFile);
00404     }
00405 }
00406 
00407 void QuicklaunchApplet::clearLayout(QGraphicsLayout *layout)
00408 {
00409     while (layout->count() > 0) {
00410         layout->removeAt(0);
00411     }
00412 }
00413 
00414 void QuicklaunchApplet::removeCurrentIcon()
00415 {
00416     m_icons.removeAll(m_rightClickedIcon);
00417     m_rightClickedIcon->hide();
00418     m_rightClickedIcon->deleteLater();
00419     refactorUi();
00420 }
00421 
00422 bool QuicklaunchApplet::dropHandler(const int pos, const QMimeData *mimedata)
00423 {
00424     if (!KUrl::List::canDecode(mimedata)) {
00425         return false;
00426     }
00427 
00428     KUrl::List urls = KUrl::List::fromMimeData(mimedata);
00429 
00430     if (!urls.count()) {
00431         return false;
00432     }
00433 
00434     //if there are more than one the last is junk
00435     if (urls.count() > 1) {
00436         urls.removeLast();
00437     }
00438 
00439     foreach (const KUrl &url, urls) {
00440         if(KDesktopFile::isDesktopFile(url.toLocalFile())) {
00441             addProgram(pos, url.toLocalFile());
00442         }
00443     }
00444     return true;
00445 }
00446 
00447 
00448 void QuicklaunchApplet::showAddInterface()
00449 {
00450     if (!m_addDialog) {
00451         m_addDialog = new KDialog;
00452         m_addDialog->setCaption(i18n("Add Shortcut"));
00453 
00454         QWidget *widget = new QWidget;
00455         addUi.setupUi(widget);
00456         m_addDialog->setMainWidget(widget);
00457         connect(m_addDialog, SIGNAL(okClicked()), this, SLOT(addAccepted()));
00458     }
00459     m_addDialog->show();
00460 }
00461 
00462 void QuicklaunchApplet::addAccepted()
00463 {
00464     int insertplace = m_rightClickedIcon ? m_icons.indexOf(m_rightClickedIcon) : m_icons.size();
00465     addProgram(insertplace, addUi.urlIcon->url().url());
00466     refactorUi();
00467 }
00468 
00469 K_EXPORT_PLASMA_APPLET(quicklaunch, QuicklaunchApplet)
00470 
00471 #include "quicklaunchApplet.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