• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KFile

kfileplacesview.cpp
Go to the documentation of this file.
00001 /*  This file is part of the KDE project
00002     Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
00003     Copyright (C) 2008 Rafael Fernández López <ereslibre@kde.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 version 2 as published by the Free Software Foundation.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 
00019 */
00020 
00021 #include "kfileplacesview.h"
00022 #include "kfileplacesview_p.h"
00023 
00024 #include <QtCore/QTimeLine>
00025 #include <QtCore/QTimer>
00026 #include <QtGui/QPainter>
00027 #include <QtGui/QAbstractItemDelegate>
00028 #include <QtGui/QKeyEvent>
00029 #include <QtGui/QApplication>
00030 #include <QtGui/QScrollBar>
00031 
00032 #include <kdebug.h>
00033 
00034 #include <kmenu.h>
00035 #include <kcomponentdata.h>
00036 #include <kdirnotify.h>
00037 #include <kglobalsettings.h>
00038 #include <kiconloader.h>
00039 #include <klocale.h>
00040 #include <kmessagebox.h>
00041 #include <knotification.h>
00042 #include <kio/job.h>
00043 #include <kio/jobuidelegate.h>
00044 #include <kjob.h>
00045 #include <kcapacitybar.h>
00046 #include <kdiskfreespaceinfo.h>
00047 #include <solid/storageaccess.h>
00048 #include <solid/storagedrive.h>
00049 #include <solid/storagevolume.h>
00050 #include <solid/opticaldrive.h>
00051 #include <solid/opticaldisc.h>
00052 
00053 #include "kfileplaceeditdialog.h"
00054 #include "kfileplacesmodel.h"
00055 
00056 #define LATERAL_MARGIN 4
00057 #define CAPACITYBAR_HEIGHT 6
00058 
00059 class KFilePlacesViewDelegate : public QAbstractItemDelegate
00060 {
00061 public:
00062     KFilePlacesViewDelegate(KFilePlacesView *parent);
00063     virtual ~KFilePlacesViewDelegate();
00064     virtual QSize sizeHint(const QStyleOptionViewItem &option,
00065                            const QModelIndex &index) const;
00066     virtual void paint(QPainter *painter,
00067                        const QStyleOptionViewItem &option,
00068                        const QModelIndex &index) const;
00069 
00070     int iconSize() const;
00071     void setIconSize(int newSize);
00072 
00073     void addAppearingItem(const QModelIndex &index);
00074     void setAppearingItemProgress(qreal value);
00075     void addDisappearingItem(const QModelIndex &index);
00076     void setDisappearingItemProgress(qreal value);
00077 
00078     void setShowHoverIndication(bool show);
00079 
00080     void addFadeAnimation(const QModelIndex &index, QTimeLine *timeLine);
00081     void removeFadeAnimation(const QModelIndex &index);
00082     QModelIndex indexForFadeAnimation(QTimeLine *timeLine) const;
00083     QTimeLine *fadeAnimationForIndex(const QModelIndex &index) const;
00084 
00085     qreal contentsOpacity(const QModelIndex &index) const;
00086 
00087 private:
00088     KFilePlacesView *m_view;
00089     int m_iconSize;
00090 
00091     QList<QPersistentModelIndex> m_appearingItems;
00092     int m_appearingIconSize;
00093     qreal m_appearingOpacity;
00094 
00095     QList<QPersistentModelIndex> m_disappearingItems;
00096     int m_disappearingIconSize;
00097     qreal m_disappearingOpacity;
00098 
00099     bool m_showHoverIndication;
00100 
00101     QMap<QPersistentModelIndex, QTimeLine*> m_timeLineMap;
00102     QMap<QTimeLine*, QPersistentModelIndex> m_timeLineInverseMap;
00103 };
00104 
00105 KFilePlacesViewDelegate::KFilePlacesViewDelegate(KFilePlacesView *parent) :
00106     QAbstractItemDelegate(parent),
00107     m_view(parent),
00108     m_iconSize(48),
00109     m_appearingIconSize(0),
00110     m_appearingOpacity(0.0),
00111     m_disappearingIconSize(0),
00112     m_disappearingOpacity(0.0),
00113     m_showHoverIndication(true)
00114 {
00115 }
00116 
00117 KFilePlacesViewDelegate::~KFilePlacesViewDelegate()
00118 {
00119 }
00120 
00121 QSize KFilePlacesViewDelegate::sizeHint(const QStyleOptionViewItem &option,
00122                                         const QModelIndex &index) const
00123 {
00124     int iconSize = m_iconSize;
00125     if (m_appearingItems.contains(index)) {
00126         iconSize = m_appearingIconSize;
00127     } else if (m_disappearingItems.contains(index)) {
00128         iconSize = m_disappearingIconSize;
00129     }
00130 
00131     const KFilePlacesModel *filePlacesModel = static_cast<const KFilePlacesModel*>(index.model());
00132     Solid::Device device = filePlacesModel->deviceForIndex(index);
00133 
00134     return QSize(option.rect.width(), option.fontMetrics.height() / 2 + qMax(iconSize, option.fontMetrics.height()));
00135 }
00136 
00137 void KFilePlacesViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
00138 {
00139     painter->save();
00140 
00141     if (m_appearingItems.contains(index)) {
00142         painter->setOpacity(m_appearingOpacity);
00143     } else if (m_disappearingItems.contains(index)) {
00144         painter->setOpacity(m_disappearingOpacity);
00145     }
00146 
00147     QStyleOptionViewItemV4 opt = option;
00148     if (!m_showHoverIndication) {
00149         opt.state &= ~QStyle::State_MouseOver;
00150     }
00151     QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
00152     const KFilePlacesModel *placesModel = static_cast<const KFilePlacesModel*>(index.model());
00153 
00154     bool isLTR = option.direction == Qt::LeftToRight;
00155 
00156     QIcon icon = index.model()->data(index, Qt::DecorationRole).value<QIcon>();
00157     QPixmap pm = icon.pixmap(m_iconSize, m_iconSize);
00158     QPoint point(isLTR ? option.rect.left() + LATERAL_MARGIN
00159                        : option.rect.right() - LATERAL_MARGIN - m_iconSize, option.rect.top() + (option.rect.height() - m_iconSize) / 2);
00160     painter->drawPixmap(point, pm);
00161 
00162     if (option.state & QStyle::State_Selected) {
00163         QPalette::ColorGroup cg = QPalette::Active;
00164         if (!(option.state & QStyle::State_Enabled)) {
00165             cg = QPalette::Disabled;
00166         } else if (!(option.state & QStyle::State_Active)) {
00167             cg = QPalette::Inactive;
00168         }
00169         painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
00170     }
00171 
00172     QRect rectText;
00173 
00174     QString mountPointPath = placesModel->url(index).toLocalFile();
00175     KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(mountPointPath);
00176     bool drawCapacityBar = info.size() != 0 &&
00177             placesModel->data(index, KFilePlacesModel::CapacityBarRecommendedRole).toBool();
00178 
00179     if (drawCapacityBar && contentsOpacity(index) > 0)
00180     {
00181         painter->save();
00182         painter->setOpacity(painter->opacity() * contentsOpacity(index));
00183 
00184         int height = option.fontMetrics.height() + CAPACITYBAR_HEIGHT;
00185         rectText = QRect(isLTR ? m_iconSize + LATERAL_MARGIN * 2 + option.rect.left()
00186                                : 0, option.rect.top() + (option.rect.height() / 2 - height / 2), option.rect.width() - m_iconSize - LATERAL_MARGIN * 2, option.fontMetrics.height());
00187         painter->drawText(rectText, Qt::AlignLeft | Qt::AlignTop, option.fontMetrics.elidedText(index.model()->data(index).toString(), Qt::ElideRight, rectText.width()));
00188         QRect capacityRect(isLTR ? rectText.x() : LATERAL_MARGIN, rectText.bottom() - 1, rectText.width() - LATERAL_MARGIN, CAPACITYBAR_HEIGHT);
00189         KCapacityBar capacityBar(KCapacityBar::DrawTextInline);
00190         capacityBar.setValue((info.used() * 100) / info.size());
00191         capacityBar.drawCapacityBar(painter, capacityRect);
00192 
00193         painter->restore();
00194 
00195         painter->save();
00196         painter->setOpacity(painter->opacity() * (1 - contentsOpacity(index)));
00197     }
00198 
00199     rectText = QRect(isLTR ? m_iconSize + LATERAL_MARGIN * 2 + option.rect.left()
00200                            : 0, option.rect.top(), option.rect.width() - m_iconSize - LATERAL_MARGIN * 2, option.rect.height());
00201     painter->drawText(rectText, Qt::AlignLeft | Qt::AlignVCenter, option.fontMetrics.elidedText(index.model()->data(index).toString(), Qt::ElideRight, rectText.width()));
00202 
00203     if (drawCapacityBar && contentsOpacity(index) > 0) {
00204         painter->restore();
00205     }
00206 
00207     painter->restore();
00208 }
00209 
00210 int KFilePlacesViewDelegate::iconSize() const
00211 {
00212     return m_iconSize;
00213 }
00214 
00215 void KFilePlacesViewDelegate::setIconSize(int newSize)
00216 {
00217     m_iconSize = newSize;
00218 }
00219 
00220 void KFilePlacesViewDelegate::addAppearingItem(const QModelIndex &index)
00221 {
00222     m_appearingItems << index;
00223 }
00224 
00225 void KFilePlacesViewDelegate::setAppearingItemProgress(qreal value)
00226 {
00227     if (value<=0.25) {
00228         m_appearingOpacity = 0.0;
00229         m_appearingIconSize = iconSize()*value*4;
00230 
00231         if (m_appearingIconSize>=m_iconSize) {
00232             m_appearingIconSize = m_iconSize;
00233         }
00234     } else {
00235         m_appearingIconSize = m_iconSize;
00236         m_appearingOpacity = (value-0.25)*4/3;
00237 
00238         if (value>=1.0) {
00239             m_appearingItems.clear();
00240         }
00241     }
00242 }
00243 
00244 void KFilePlacesViewDelegate::addDisappearingItem(const QModelIndex &index)
00245 {
00246     m_disappearingItems << index;
00247 }
00248 
00249 void KFilePlacesViewDelegate::setDisappearingItemProgress(qreal value)
00250 {
00251     value = 1.0 - value;
00252 
00253     if (value<=0.25) {
00254         m_disappearingOpacity = 0.0;
00255         m_disappearingIconSize = iconSize()*value*4;
00256 
00257         if (m_disappearingIconSize>=m_iconSize) {
00258             m_disappearingIconSize = m_iconSize;
00259         }
00260 
00261         if (value<=0.0) {
00262             m_disappearingItems.clear();
00263         }
00264     } else {
00265         m_disappearingIconSize = m_iconSize;
00266         m_disappearingOpacity = (value-0.25)*4/3;
00267     }
00268 }
00269 
00270 void KFilePlacesViewDelegate::setShowHoverIndication(bool show)
00271 {
00272     m_showHoverIndication = show;
00273 }
00274 
00275 void KFilePlacesViewDelegate::addFadeAnimation(const QModelIndex &index, QTimeLine *timeLine)
00276 {
00277     m_timeLineMap.insert(index, timeLine);
00278     m_timeLineInverseMap.insert(timeLine, index);
00279 }
00280 
00281 void KFilePlacesViewDelegate::removeFadeAnimation(const QModelIndex &index)
00282 {
00283     QTimeLine *timeLine = m_timeLineMap.value(index, 0);
00284     m_timeLineMap.remove(index);
00285     m_timeLineInverseMap.remove(timeLine);
00286 }
00287 
00288 QModelIndex KFilePlacesViewDelegate::indexForFadeAnimation(QTimeLine *timeLine) const
00289 {
00290     return m_timeLineInverseMap.value(timeLine, QModelIndex());
00291 }
00292 
00293 QTimeLine *KFilePlacesViewDelegate::fadeAnimationForIndex(const QModelIndex &index) const
00294 {
00295     return m_timeLineMap.value(index, 0);
00296 }
00297 
00298 qreal KFilePlacesViewDelegate::contentsOpacity(const QModelIndex &index) const
00299 {
00300     QTimeLine *timeLine = fadeAnimationForIndex(index);
00301     if (timeLine) {
00302         return timeLine->currentValue();
00303     }
00304     return 0;
00305 }
00306 
00307 class KFilePlacesView::Private
00308 {
00309 public:
00310     Private(KFilePlacesView *parent) : q(parent), watcher(new KFilePlacesEventWatcher(q)) { }
00311 
00312     enum FadeType {
00313         FadeIn = 0,
00314         FadeOut
00315     };
00316 
00317     KFilePlacesView * const q;
00318 
00319     KUrl currentUrl;
00320     bool autoResizeItems;
00321     bool showAll;
00322     bool smoothItemResizing;
00323     bool dropOnPlace;
00324     bool dragging;
00325     Solid::StorageAccess *lastClickedStorage;
00326     QPersistentModelIndex lastClickedIndex;
00327 
00328     QRect dropRect;
00329 
00330     void setCurrentIndex(const QModelIndex &index);
00331     void adaptItemSize();
00332     void updateHiddenRows();
00333     bool insertAbove(const QRect &itemRect, const QPoint &pos) const;
00334     bool insertBelow(const QRect &itemRect, const QPoint &pos) const;
00335     int insertIndicatorHeight(int itemHeight) const;
00336     void fadeCapacityBar(const QModelIndex &index, FadeType fadeType);
00337 
00338     void _k_placeClicked(const QModelIndex &index);
00339     void _k_placeEntered(const QModelIndex &index);
00340     void _k_placeLeft(const QModelIndex &index);
00341     void _k_storageSetupDone(const QModelIndex &index, bool success);
00342     void _k_adaptItemsUpdate(qreal value);
00343     void _k_itemAppearUpdate(qreal value);
00344     void _k_itemDisappearUpdate(qreal value);
00345     void _k_enableSmoothItemResizing();
00346     void _k_trashUpdated(KJob *job);
00347     void _k_capacityBarFadeValueChanged();
00348     void _k_triggerDevicePolling();
00349 
00350     QTimeLine adaptItemsTimeline;
00351     int oldSize, endSize;
00352 
00353     QTimeLine itemAppearTimeline;
00354     QTimeLine itemDisappearTimeline;
00355 
00356     KFilePlacesEventWatcher *const watcher;
00357     KFilePlacesViewDelegate *delegate;
00358     QTimer pollDevices;
00359     int pollingRequestCount;
00360 };
00361 
00362 KFilePlacesView::KFilePlacesView(QWidget *parent)
00363     : QListView(parent), d(new Private(this))
00364 {
00365     d->showAll = false;
00366     d->smoothItemResizing = false;
00367     d->dropOnPlace = false;
00368     d->autoResizeItems = true;
00369     d->dragging = false;
00370     d->lastClickedStorage = 0;
00371     d->pollingRequestCount = 0;
00372     d->delegate = new KFilePlacesViewDelegate(this);
00373 
00374     setSelectionRectVisible(false);
00375     setSelectionMode(SingleSelection);
00376 
00377     setDragEnabled(true);
00378     setAcceptDrops(true);
00379     setMouseTracking(true);
00380     setDropIndicatorShown(false);
00381     setFrameStyle(QFrame::NoFrame);
00382 
00383     setResizeMode(Adjust);
00384     setItemDelegate(d->delegate);
00385 
00386     QPalette palette = viewport()->palette();
00387     palette.setColor(viewport()->backgroundRole(), Qt::transparent);
00388     palette.setColor(viewport()->foregroundRole(), palette.color(QPalette::WindowText));
00389     viewport()->setPalette(palette);
00390 
00391     connect(this, SIGNAL(clicked(const QModelIndex&)),
00392             this, SLOT(_k_placeClicked(const QModelIndex&)));
00393     // Note: Don't connect to the activated() signal, as the behavior when it is
00394     // committed depends on the used widget style. The click behavior of
00395     // KFilePlacesView should be style independent.
00396 
00397     connect(&d->adaptItemsTimeline, SIGNAL(valueChanged(qreal)),
00398             this, SLOT(_k_adaptItemsUpdate(qreal)));
00399     d->adaptItemsTimeline.setDuration(500);
00400     d->adaptItemsTimeline.setUpdateInterval(5);
00401     d->adaptItemsTimeline.setCurveShape(QTimeLine::EaseInOutCurve);
00402 
00403     connect(&d->itemAppearTimeline, SIGNAL(valueChanged(qreal)),
00404             this, SLOT(_k_itemAppearUpdate(qreal)));
00405     d->itemAppearTimeline.setDuration(500);
00406     d->itemAppearTimeline.setUpdateInterval(5);
00407     d->itemAppearTimeline.setCurveShape(QTimeLine::EaseInOutCurve);
00408 
00409     connect(&d->itemDisappearTimeline, SIGNAL(valueChanged(qreal)),
00410             this, SLOT(_k_itemDisappearUpdate(qreal)));
00411     d->itemDisappearTimeline.setDuration(500);
00412     d->itemDisappearTimeline.setUpdateInterval(5);
00413     d->itemDisappearTimeline.setCurveShape(QTimeLine::EaseInOutCurve);
00414 
00415     viewport()->installEventFilter(d->watcher);
00416     connect(d->watcher, SIGNAL(entryEntered(const QModelIndex&)),
00417             this, SLOT(_k_placeEntered(const QModelIndex&)));
00418     connect(d->watcher, SIGNAL(entryLeft(const QModelIndex&)),
00419             this, SLOT(_k_placeLeft(const QModelIndex&)));
00420 
00421     d->pollDevices.setInterval(5000);
00422     connect(&d->pollDevices, SIGNAL(timeout()), this, SLOT(_k_triggerDevicePolling()));
00423 
00424     // FIXME: this is necessary to avoid flashes of black with some widget styles.
00425     // could be a bug in Qt (e.g. QAbstractScrollArea) or KFilePlacesView, but has not
00426     // yet been tracked down yet. until then, this works and is harmlessly enough.
00427     // in fact, some QStyle (Oxygen, Skulpture, others?) do this already internally.
00428     // See br #242358 for more information
00429     verticalScrollBar()->setAttribute(Qt::WA_OpaquePaintEvent, false);
00430 }
00431 
00432 KFilePlacesView::~KFilePlacesView()
00433 {
00434     delete d;
00435 }
00436 
00437 void KFilePlacesView::setDropOnPlaceEnabled(bool enabled)
00438 {
00439     d->dropOnPlace = enabled;
00440 }
00441 
00442 bool KFilePlacesView::isDropOnPlaceEnabled() const
00443 {
00444     return d->dropOnPlace;
00445 }
00446 
00447 void KFilePlacesView::setAutoResizeItemsEnabled(bool enabled)
00448 {
00449     d->autoResizeItems = enabled;
00450 }
00451 
00452 bool KFilePlacesView::isAutoResizeItemsEnabled() const
00453 {
00454     return d->autoResizeItems;
00455 }
00456 
00457 void KFilePlacesView::setUrl(const KUrl &url)
00458 {
00459     KUrl oldUrl = d->currentUrl;
00460     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00461 
00462     if (placesModel==0) return;
00463 
00464     QModelIndex index = placesModel->closestItem(url);
00465     QModelIndex current = selectionModel()->currentIndex();
00466 
00467     if (index.isValid()) {
00468         if (current!=index && placesModel->isHidden(current) && !d->showAll) {
00469             KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00470             delegate->addDisappearingItem(current);
00471 
00472             if (d->itemDisappearTimeline.state()!=QTimeLine::Running) {
00473                 delegate->setDisappearingItemProgress(0.0);
00474                 d->itemDisappearTimeline.start();
00475             }
00476         }
00477 
00478         if (current!=index && placesModel->isHidden(index) && !d->showAll) {
00479             KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00480             delegate->addAppearingItem(index);
00481 
00482             if (d->itemAppearTimeline.state()!=QTimeLine::Running) {
00483                 delegate->setAppearingItemProgress(0.0);
00484                 d->itemAppearTimeline.start();
00485             }
00486 
00487             setRowHidden(index.row(), false);
00488         }
00489 
00490         d->currentUrl = url;
00491         selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
00492     } else {
00493         d->currentUrl = KUrl();
00494         selectionModel()->clear();
00495     }
00496 
00497     if (!current.isValid()) {
00498         d->updateHiddenRows();
00499     }
00500 }
00501 
00502 void KFilePlacesView::setShowAll(bool showAll)
00503 {
00504     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00505 
00506     if (placesModel==0) return;
00507 
00508     d->showAll = showAll;
00509 
00510     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00511 
00512     int rowCount = placesModel->rowCount();
00513     QModelIndex current = placesModel->closestItem(d->currentUrl);
00514 
00515     if (showAll) {
00516         d->updateHiddenRows();
00517 
00518         for (int i=0; i<rowCount; ++i) {
00519             QModelIndex index = placesModel->index(i, 0);
00520             if (index!=current && placesModel->isHidden(index)) {
00521                 delegate->addAppearingItem(index);
00522             }
00523         }
00524 
00525         if (d->itemAppearTimeline.state()!=QTimeLine::Running) {
00526             delegate->setAppearingItemProgress(0.0);
00527             d->itemAppearTimeline.start();
00528         }
00529     } else {
00530         for (int i=0; i<rowCount; ++i) {
00531             QModelIndex index = placesModel->index(i, 0);
00532             if (index!=current && placesModel->isHidden(index)) {
00533                 delegate->addDisappearingItem(index);
00534             }
00535         }
00536 
00537         if (d->itemDisappearTimeline.state()!=QTimeLine::Running) {
00538             delegate->setDisappearingItemProgress(0.0);
00539             d->itemDisappearTimeline.start();
00540         }
00541     }
00542 }
00543 
00544 void KFilePlacesView::keyPressEvent(QKeyEvent *event)
00545 {
00546     QListView::keyPressEvent(event);
00547     if ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Enter)) {
00548         d->_k_placeClicked(currentIndex());
00549     }
00550 }
00551 
00552 void KFilePlacesView::contextMenuEvent(QContextMenuEvent *event)
00553 {
00554     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00555     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00556 
00557     if (placesModel==0) return;
00558 
00559     QModelIndex index = indexAt(event->pos());
00560     QString label = placesModel->text(index).replace('&',"&&");
00561 
00562     KMenu menu;
00563 
00564     QAction *edit = 0;
00565     QAction *hide = 0;
00566     QAction *emptyTrash = 0;
00567     QAction *eject = 0;
00568     QAction *teardown = 0;
00569     QAction *add = 0;
00570     QAction *mainSeparator = 0;
00571 
00572     if (index.isValid()) {
00573         if (!placesModel->isDevice(index)) {
00574             if (placesModel->url(index) == KUrl("trash:/")) {
00575                 emptyTrash = menu.addAction(KIcon("trash-empty"), i18nc("@action:inmenu", "Empty Trash"));
00576                 KConfig trashConfig("trashrc", KConfig::SimpleConfig);
00577                 emptyTrash->setEnabled(!trashConfig.group("Status").readEntry("Empty", true));
00578                 menu.addSeparator();
00579             }
00580             add = menu.addAction(KIcon("document-new"), i18n("Add Entry..."));
00581             mainSeparator = menu.addSeparator();
00582             edit = menu.addAction(KIcon("document-properties"), i18n("&Edit Entry '%1'...", label));
00583         } else {
00584             eject = placesModel->ejectActionForIndex(index);
00585             if (eject!=0) {
00586                 eject->setParent(&menu);
00587                 menu.addAction(eject);
00588             }
00589 
00590             teardown = placesModel->teardownActionForIndex(index);
00591             if (teardown!=0) {
00592                 teardown->setParent(&menu);
00593                 menu.addAction(teardown);
00594             }
00595 
00596             if (teardown!=0 || eject!=0) {
00597                 mainSeparator = menu.addSeparator();
00598             }
00599         }
00600         if (add == 0) {
00601             add = menu.addAction(KIcon("document-new"), i18n("Add Entry..."));
00602         }
00603 
00604         hide = menu.addAction(i18n("&Hide Entry '%1'", label));
00605         hide->setCheckable(true);
00606         hide->setChecked(placesModel->isHidden(index));
00607     } else {
00608         add = menu.addAction(KIcon("document-new"), i18n("Add Entry..."));
00609     }
00610 
00611     QAction *showAll = 0;
00612     if (placesModel->hiddenCount()>0) {
00613         showAll = new QAction(i18n("&Show All Entries"), &menu);
00614         showAll->setCheckable(true);
00615         showAll->setChecked(d->showAll);
00616         if (mainSeparator == 0) {
00617             mainSeparator = menu.addSeparator();
00618         }
00619         menu.insertAction(mainSeparator, showAll);
00620     }
00621 
00622     QAction* remove = 0;
00623     if (index.isValid() && !placesModel->isDevice(index)) {
00624         remove = menu.addAction( KIcon("edit-delete"), i18n("&Remove Entry '%1'", label));
00625     }
00626 
00627     menu.addActions(actions());
00628 
00629     if (menu.isEmpty()) {
00630         return;
00631     }
00632 
00633     QAction *result = menu.exec(event->globalPos());
00634 
00635     if (emptyTrash != 0 && result == emptyTrash) {
00636         const QString text = i18nc("@info", "Do you really want to empty the Trash? All items will be deleted.");
00637         const bool del = KMessageBox::warningContinueCancel(window(),
00638                                                             text,
00639                                                             QString(),
00640                                                             KGuiItem(i18nc("@action:button", "Empty Trash"),
00641                                                                      KIcon("user-trash"))
00642                                                            ) == KMessageBox::Continue;
00643         if (del) {
00644             QByteArray packedArgs;
00645             QDataStream stream(&packedArgs, QIODevice::WriteOnly);
00646             stream << int(1);
00647             KIO::Job *job = KIO::special(KUrl("trash:/"), packedArgs);
00648             KNotification::event("Trash: emptied", QString() , QPixmap() , 0, KNotification::DefaultEvent);
00649             job->ui()->setWindow(parentWidget());
00650             connect(job, SIGNAL(result(KJob*)), SLOT(_k_trashUpdated(KJob*)));
00651         }
00652     } else if (edit != 0 && result == edit) {
00653         KBookmark bookmark = placesModel->bookmarkForIndex(index);
00654         KUrl url = bookmark.url();
00655         QString label = bookmark.text();
00656         QString iconName = bookmark.icon();
00657         bool appLocal = !bookmark.metaDataItem("OnlyInApp").isEmpty();
00658 
00659         if (KFilePlaceEditDialog::getInformation(true, url, label,
00660                                                  iconName, false, appLocal, 64, this))
00661         {
00662             QString appName;
00663             if (appLocal) appName = KGlobal::mainComponent().componentName();
00664 
00665             placesModel->editPlace(index, label, url, iconName, appName);
00666         }
00667 
00668     } else if (remove != 0 && result == remove) {
00669         placesModel->removePlace(index);
00670     } else if (hide != 0 && result == hide) {
00671         placesModel->setPlaceHidden(index, hide->isChecked());
00672         QModelIndex current = placesModel->closestItem(d->currentUrl);
00673 
00674         if (index!=current && !d->showAll && hide->isChecked()) {
00675             delegate->addDisappearingItem(index);
00676 
00677             if (d->itemDisappearTimeline.state()!=QTimeLine::Running) {
00678                 delegate->setDisappearingItemProgress(0.0);
00679                 d->itemDisappearTimeline.start();
00680             }
00681         }
00682     } else if (showAll != 0 && result == showAll) {
00683         setShowAll(showAll->isChecked());
00684     } else if (teardown != 0 && result == teardown) {
00685         placesModel->requestTeardown(index);
00686     } else if (eject != 0 && result == eject) {
00687         placesModel->requestEject(index);
00688     } else if (add != 0 && result == add) {
00689         KUrl url = d->currentUrl;
00690         QString label;
00691         QString iconName = "folder";
00692         bool appLocal = true;
00693         if (KFilePlaceEditDialog::getInformation(true, url, label,
00694                                                  iconName, true, appLocal, 64, this))
00695         {
00696             QString appName;
00697             if (appLocal) appName = KGlobal::mainComponent().componentName();
00698 
00699             placesModel->addPlace(label, url, iconName, appName, index);
00700         }
00701     }
00702 
00703     index = placesModel->closestItem(d->currentUrl);
00704     selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
00705 }
00706 
00707 void KFilePlacesView::resizeEvent(QResizeEvent *event)
00708 {
00709     QListView::resizeEvent(event);
00710     d->adaptItemSize();
00711 }
00712 
00713 void KFilePlacesView::showEvent(QShowEvent *event)
00714 {
00715     QListView::showEvent(event);
00716     QTimer::singleShot(100, this, SLOT(_k_enableSmoothItemResizing()));
00717 }
00718 
00719 void KFilePlacesView::hideEvent(QHideEvent *event)
00720 {
00721     QListView::hideEvent(event);
00722     d->smoothItemResizing = false;
00723 }
00724 
00725 void KFilePlacesView::dragEnterEvent(QDragEnterEvent *event)
00726 {
00727     QListView::dragEnterEvent(event);
00728     d->dragging = true;
00729 
00730     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00731     delegate->setShowHoverIndication(false);
00732 
00733     d->dropRect = QRect();
00734 }
00735 
00736 void KFilePlacesView::dragLeaveEvent(QDragLeaveEvent *event)
00737 {
00738     QListView::dragLeaveEvent(event);
00739     d->dragging = false;
00740 
00741     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00742     delegate->setShowHoverIndication(true);
00743 
00744     setDirtyRegion(d->dropRect);
00745 }
00746 
00747 void KFilePlacesView::dragMoveEvent(QDragMoveEvent *event)
00748 {
00749     QListView::dragMoveEvent(event);
00750 
00751     // update the drop indicator
00752     const QPoint pos = event->pos();
00753     const QModelIndex index = indexAt(pos);
00754     setDirtyRegion(d->dropRect);
00755     if (index.isValid()) {
00756         const QRect rect = visualRect(index);
00757         const int gap = d->insertIndicatorHeight(rect.height());
00758         if (d->insertAbove(rect, pos)) {
00759             // indicate that the item will be inserted above the current place
00760             d->dropRect = QRect(rect.left(), rect.top() - gap / 2,
00761                                 rect.width(), gap);
00762         } else if (d->insertBelow(rect, pos)) {
00763             // indicate that the item will be inserted below the current place
00764             d->dropRect = QRect(rect.left(), rect.bottom() + 1 -  gap / 2,
00765                                 rect.width(), gap);
00766         } else {
00767             // indicate that the item be dropped above the current place
00768             d->dropRect = rect;
00769         }
00770     }
00771 
00772     setDirtyRegion(d->dropRect);
00773 }
00774 
00775 void KFilePlacesView::dropEvent(QDropEvent *event)
00776 {
00777     const QPoint pos = event->pos();
00778     const QModelIndex index = indexAt(pos);
00779     if (index.isValid()) {
00780         const QRect rect = visualRect(index);
00781         if (!d->insertAbove(rect, pos) && !d->insertBelow(rect, pos)) {
00782             KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00783             Q_ASSERT(placesModel != 0);
00784             emit urlsDropped(placesModel->url(index), event, this);
00785             event->acceptProposedAction();
00786         }
00787     }
00788 
00789     QListView::dropEvent(event);
00790     d->dragging = false;
00791 
00792     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00793     delegate->setShowHoverIndication(true);
00794 }
00795 
00796 void KFilePlacesView::paintEvent(QPaintEvent* event)
00797 {
00798     QListView::paintEvent(event);
00799     if (d->dragging && !d->dropRect.isEmpty()) {
00800         // draw drop indicator
00801         QPainter painter(viewport());
00802 
00803         const QModelIndex index = indexAt(d->dropRect.topLeft());
00804         const QRect itemRect = visualRect(index);
00805         const bool drawInsertIndicator = !d->dropOnPlace ||
00806                                          d->dropRect.height() <= d->insertIndicatorHeight(itemRect.height());
00807 
00808         if (drawInsertIndicator) {
00809             // draw indicator for inserting items
00810             QBrush blendedBrush = viewOptions().palette.brush(QPalette::Normal, QPalette::Highlight);
00811             QColor color = blendedBrush.color();
00812 
00813             const int y = (d->dropRect.top() + d->dropRect.bottom()) / 2;
00814             const int thickness = d->dropRect.height() / 2;
00815             Q_ASSERT(thickness >= 1);
00816             int alpha = 255;
00817             const int alphaDec = alpha / (thickness + 1);
00818             for (int i = 0; i < thickness; i++) {
00819                 color.setAlpha(alpha);
00820                 alpha -= alphaDec;
00821                 painter.setPen(color);
00822                 painter.drawLine(d->dropRect.left(), y - i, d->dropRect.right(), y - i);
00823                 painter.drawLine(d->dropRect.left(), y + i, d->dropRect.right(), y + i);
00824             }
00825         } else {
00826             // draw indicator for copying/moving/linking to items
00827             QStyleOptionViewItemV4 opt;
00828             opt.initFrom(this);
00829             opt.rect = itemRect;
00830             opt.state = QStyle::State_Enabled | QStyle::State_MouseOver;
00831             style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, &painter, this);
00832         }
00833     }
00834 }
00835 
00836 void KFilePlacesView::setModel(QAbstractItemModel *model)
00837 {
00838     QListView::setModel(model);
00839     d->updateHiddenRows();
00840     // Uses Qt::QueuedConnection to delay the time when the slot will be
00841     // called. In case of an item move the remove+add will be done before
00842     // we adapt the item size (otherwise we'd get it wrong as we'd execute
00843     // it after the remove only).
00844     connect(model, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
00845             this, SLOT(adaptItemSize()), Qt::QueuedConnection);
00846     connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)),
00847             d->watcher, SLOT(currentIndexChanged(const QModelIndex&)));
00848 }
00849 
00850 void KFilePlacesView::rowsInserted(const QModelIndex &parent, int start, int end)
00851 {
00852     QListView::rowsInserted(parent, start, end);
00853     setUrl(d->currentUrl);
00854 
00855     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00856     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00857 
00858     for (int i=start; i<=end; ++i) {
00859         QModelIndex index = placesModel->index(i, 0, parent);
00860         if (d->showAll || !placesModel->isHidden(index)) {
00861             delegate->addAppearingItem(index);
00862         } else {
00863             setRowHidden(i, true);
00864         }
00865     }
00866 
00867     if (d->itemAppearTimeline.state()!=QTimeLine::Running) {
00868         delegate->setAppearingItemProgress(0.0);
00869         d->itemAppearTimeline.start();
00870     }
00871 
00872     d->adaptItemSize();
00873 }
00874 
00875 QSize KFilePlacesView::sizeHint() const
00876 {
00877     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00878     if (!placesModel) {
00879         return QListView::sizeHint();
00880     }
00881     const int height = QListView::sizeHint().height();
00882     QFontMetrics fm = d->q->fontMetrics();
00883     int textWidth = 0;
00884 
00885     for (int i=0; i<placesModel->rowCount(); ++i) {
00886         QModelIndex index = placesModel->index(i, 0);
00887         if (!placesModel->isHidden(index))
00888            textWidth = qMax(textWidth,fm.width(index.data(Qt::DisplayRole).toString()));
00889     }
00890 
00891     const int iconSize = KIconLoader::global()->currentSize(KIconLoader::Dialog);
00892     return QSize(iconSize + textWidth + fm.height() / 2, height);
00893 }
00894 
00895 void KFilePlacesView::Private::setCurrentIndex(const QModelIndex &index)
00896 {
00897     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00898 
00899     if (placesModel==0) return;
00900 
00901     KUrl url = placesModel->url(index);
00902 
00903     if (url.isValid()) {
00904         currentUrl = url;
00905         updateHiddenRows();
00906         emit q->urlChanged(url);
00907         if (showAll) {
00908             q->setShowAll(false);
00909         }
00910     } else {
00911         q->setUrl(currentUrl);
00912     }
00913 }
00914 
00915 void KFilePlacesView::Private::adaptItemSize()
00916 {
00917     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
00918     if (!delegate) return;
00919 
00920     if (!autoResizeItems) {
00921         int size = q->iconSize().width(); // Assume width == height
00922         delegate->setIconSize(size);
00923         q->scheduleDelayedItemsLayout();
00924         return;
00925     }
00926 
00927     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00928 
00929     if (placesModel==0) return;
00930 
00931     int rowCount = placesModel->rowCount();
00932 
00933     if (!showAll) {
00934         rowCount-= placesModel->hiddenCount();
00935 
00936         QModelIndex current = placesModel->closestItem(currentUrl);
00937 
00938         if (placesModel->isHidden(current)) {
00939             rowCount++;
00940         }
00941     }
00942 
00943     if (rowCount==0) return; // We've nothing to display anyway
00944 
00945     const int minSize = 16;
00946     const int maxSize = 64;
00947 
00948     int textWidth = 0;
00949     QFontMetrics fm = q->fontMetrics();
00950     for (int i=0; i<placesModel->rowCount(); ++i) {
00951         QModelIndex index = placesModel->index(i, 0);
00952 
00953         if (!placesModel->isHidden(index))
00954            textWidth = qMax(textWidth,fm.width(index.data(Qt::DisplayRole).toString()));
00955     }
00956 
00957     const int margin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, q) + 1;
00958     const int maxWidth = q->viewport()->width() - textWidth - 4 * margin - 1;
00959     const int maxHeight = ((q->height() - (fm.height() / 2) * rowCount) / rowCount) - 1;
00960 
00961     int size = qMin(maxHeight, maxWidth);
00962 
00963     if (size<minSize) {
00964         size = minSize;
00965     } else if (size>maxSize) {
00966         size = maxSize;
00967     } else {
00968         // Make it a multiple of 16
00969         size &= ~0xf;
00970     }
00971 
00972     if (size==delegate->iconSize()) return;
00973 
00974     if (smoothItemResizing) {
00975         oldSize = delegate->iconSize();
00976         endSize = size;
00977         if (adaptItemsTimeline.state()!=QTimeLine::Running) {
00978             adaptItemsTimeline.start();
00979         }
00980     } else {
00981         delegate->setIconSize(size);
00982         q->scheduleDelayedItemsLayout();
00983     }
00984 }
00985 
00986 void KFilePlacesView::Private::updateHiddenRows()
00987 {
00988     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00989 
00990     if (placesModel==0) return;
00991 
00992     int rowCount = placesModel->rowCount();
00993     QModelIndex current = placesModel->closestItem(currentUrl);
00994 
00995     for (int i=0; i<rowCount; ++i) {
00996         QModelIndex index = placesModel->index(i, 0);
00997         if (index!=current && placesModel->isHidden(index) && !showAll) {
00998             q->setRowHidden(i, true);
00999         } else {
01000             q->setRowHidden(i, false);
01001         }
01002     }
01003 
01004     adaptItemSize();
01005 }
01006 
01007 bool KFilePlacesView::Private::insertAbove(const QRect &itemRect, const QPoint &pos) const
01008 {
01009     if (dropOnPlace) {
01010         return pos.y() < itemRect.top() + insertIndicatorHeight(itemRect.height()) / 2;
01011     }
01012 
01013     return pos.y() < itemRect.top() + (itemRect.height() / 2);
01014 }
01015 
01016 bool KFilePlacesView::Private::insertBelow(const QRect &itemRect, const QPoint &pos) const
01017 {
01018     if (dropOnPlace) {
01019         return pos.y() > itemRect.bottom() - insertIndicatorHeight(itemRect.height()) / 2;
01020     }
01021 
01022     return pos.y() >= itemRect.top() + (itemRect.height() / 2);
01023 }
01024 
01025 int KFilePlacesView::Private::insertIndicatorHeight(int itemHeight) const
01026 {
01027     const int min = 4;
01028     const int max = 12;
01029 
01030     int height = itemHeight / 4;
01031     if (height < min) {
01032         height = min;
01033     } else if (height > max) {
01034         height = max;
01035     }
01036     return height;
01037 }
01038 
01039 void KFilePlacesView::Private::fadeCapacityBar(const QModelIndex &index, FadeType fadeType)
01040 {
01041     QTimeLine *timeLine = delegate->fadeAnimationForIndex(index);
01042     delete timeLine;
01043     delegate->removeFadeAnimation(index);
01044     timeLine = new QTimeLine(250, q);
01045     connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(_k_capacityBarFadeValueChanged()));
01046     if (fadeType == FadeIn) {
01047         timeLine->setDirection(QTimeLine::Forward);
01048         timeLine->setCurrentTime(0);
01049     } else {
01050         timeLine->setDirection(QTimeLine::Backward);
01051         timeLine->setCurrentTime(250);
01052     }
01053     delegate->addFadeAnimation(index, timeLine);
01054     timeLine->start();
01055 }
01056 
01057 void KFilePlacesView::Private::_k_placeClicked(const QModelIndex &index)
01058 {
01059     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
01060 
01061     if (placesModel==0) return;
01062 
01063     lastClickedIndex = QPersistentModelIndex();
01064 
01065     if (placesModel->setupNeeded(index)) {
01066         QObject::connect(placesModel, SIGNAL(setupDone(const QModelIndex &, bool)),
01067                          q, SLOT(_k_storageSetupDone(const QModelIndex &, bool)));
01068 
01069         lastClickedIndex = index;
01070         placesModel->requestSetup(index);
01071         return;
01072     }
01073 
01074     setCurrentIndex(index);
01075 }
01076 
01077 void KFilePlacesView::Private::_k_placeEntered(const QModelIndex &index)
01078 {
01079     fadeCapacityBar(index, FadeIn);
01080     pollingRequestCount++;
01081     if (pollingRequestCount == 1) {
01082         pollDevices.start();
01083     }
01084 }
01085 
01086 void KFilePlacesView::Private::_k_placeLeft(const QModelIndex &index)
01087 {
01088     fadeCapacityBar(index, FadeOut);
01089     pollingRequestCount--;
01090     if (!pollingRequestCount) {
01091         pollDevices.stop();
01092     }
01093 }
01094 
01095 void KFilePlacesView::Private::_k_storageSetupDone(const QModelIndex &index, bool success)
01096 {
01097     if (index!=lastClickedIndex) {
01098         return;
01099     }
01100 
01101     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
01102 
01103     QObject::disconnect(placesModel, SIGNAL(setupDone(const QModelIndex &, bool)),
01104                         q, SLOT(_k_storageSetupDone(const QModelIndex &, bool)));
01105 
01106     if (success) {
01107         setCurrentIndex(lastClickedIndex);
01108     } else {
01109         q->setUrl(currentUrl);
01110     }
01111 
01112     lastClickedIndex = QPersistentModelIndex();
01113 }
01114 
01115 void KFilePlacesView::Private::_k_adaptItemsUpdate(qreal value)
01116 {
01117     int add = (endSize-oldSize)*value;
01118 
01119     int size = oldSize+add;
01120 
01121     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
01122     delegate->setIconSize(size);
01123     q->scheduleDelayedItemsLayout();
01124 }
01125 
01126 void KFilePlacesView::Private::_k_itemAppearUpdate(qreal value)
01127 {
01128     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
01129 
01130     delegate->setAppearingItemProgress(value);
01131     q->scheduleDelayedItemsLayout();
01132 }
01133 
01134 void KFilePlacesView::Private::_k_itemDisappearUpdate(qreal value)
01135 {
01136     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
01137 
01138     delegate->setDisappearingItemProgress(value);
01139 
01140     if (value>=1.0) {
01141         updateHiddenRows();
01142     }
01143 
01144     q->scheduleDelayedItemsLayout();
01145 }
01146 
01147 void KFilePlacesView::Private::_k_enableSmoothItemResizing()
01148 {
01149     smoothItemResizing = true;
01150 }
01151 
01152 void KFilePlacesView::Private::_k_trashUpdated(KJob *job)
01153 {
01154     if (job->error()) {
01155         static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
01156     }
01157     org::kde::KDirNotify::emitFilesAdded("trash:/");
01158 }
01159 
01160 void KFilePlacesView::Private::_k_capacityBarFadeValueChanged()
01161 {
01162     const QModelIndex index = delegate->indexForFadeAnimation(static_cast<QTimeLine*>(q->sender()));
01163     if (!index.isValid()) {
01164         return;
01165     }
01166     q->update(index);
01167 }
01168 
01169 void KFilePlacesView::Private::_k_triggerDevicePolling()
01170 {
01171     const QModelIndex hoveredIndex = watcher->hoveredIndex();
01172     if (hoveredIndex.isValid()) {
01173         const KFilePlacesModel *placesModel = static_cast<const KFilePlacesModel*>(hoveredIndex.model());
01174         if (placesModel->isDevice(hoveredIndex)) {
01175             q->update(hoveredIndex);
01176         }
01177     }
01178     const QModelIndex focusedIndex = watcher->focusedIndex();
01179     if (focusedIndex.isValid() && focusedIndex != hoveredIndex) {
01180         const KFilePlacesModel *placesModel = static_cast<const KFilePlacesModel*>(focusedIndex.model());
01181         if (placesModel->isDevice(focusedIndex)) {
01182             q->update(focusedIndex);
01183         }
01184     }
01185 }
01186 
01187 void KFilePlacesView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
01188 {
01189     QListView::dataChanged(topLeft, bottomRight);
01190     d->adaptItemSize();
01191 }
01192 
01193 #include "kfileplacesview.moc"
01194 #include "kfileplacesview_p.moc"

KFile

Skip menu "KFile"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
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