• Skip to content
  • Skip to link menu
KDE 4.6 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     if (menu.isEmpty()) {
00628         return;
00629     }
00630 
00631     QAction *result = menu.exec(event->globalPos());
00632 
00633     if (emptyTrash != 0 && result == emptyTrash) {
00634         const QString text = i18nc("@info", "Do you really want to empty the Trash? All items will be deleted.");
00635         const bool del = KMessageBox::warningContinueCancel(window(),
00636                                                             text,
00637                                                             QString(),
00638                                                             KGuiItem(i18nc("@action:button", "Empty Trash"),
00639                                                                      KIcon("user-trash"))
00640                                                            ) == KMessageBox::Continue;
00641         if (del) {
00642             QByteArray packedArgs;
00643             QDataStream stream(&packedArgs, QIODevice::WriteOnly);
00644             stream << int(1);
00645             KIO::Job *job = KIO::special(KUrl("trash:/"), packedArgs);
00646             KNotification::event("Trash: emptied", QString() , QPixmap() , 0, KNotification::DefaultEvent);
00647             job->ui()->setWindow(parentWidget());
00648             connect(job, SIGNAL(result(KJob*)), SLOT(_k_trashUpdated(KJob*)));
00649         }
00650     } else if (edit != 0 && result == edit) {
00651         KBookmark bookmark = placesModel->bookmarkForIndex(index);
00652         KUrl url = bookmark.url();
00653         QString label = bookmark.text();
00654         QString iconName = bookmark.icon();
00655         bool appLocal = !bookmark.metaDataItem("OnlyInApp").isEmpty();
00656 
00657         if (KFilePlaceEditDialog::getInformation(true, url, label,
00658                                                  iconName, false, appLocal, 64, this))
00659         {
00660             QString appName;
00661             if (appLocal) appName = KGlobal::mainComponent().componentName();
00662 
00663             placesModel->editPlace(index, label, url, iconName, appName);
00664         }
00665 
00666     } else if (remove != 0 && result == remove) {
00667         placesModel->removePlace(index);
00668     } else if (hide != 0 && result == hide) {
00669         placesModel->setPlaceHidden(index, hide->isChecked());
00670         QModelIndex current = placesModel->closestItem(d->currentUrl);
00671 
00672         if (index!=current && !d->showAll && hide->isChecked()) {
00673             delegate->addDisappearingItem(index);
00674 
00675             if (d->itemDisappearTimeline.state()!=QTimeLine::Running) {
00676                 delegate->setDisappearingItemProgress(0.0);
00677                 d->itemDisappearTimeline.start();
00678             }
00679         }
00680     } else if (showAll != 0 && result == showAll) {
00681         setShowAll(showAll->isChecked());
00682     } else if (teardown != 0 && result == teardown) {
00683         placesModel->requestTeardown(index);
00684     } else if (eject != 0 && result == eject) {
00685         placesModel->requestEject(index);
00686     } else if (add != 0 && result == add) {
00687         KUrl url = d->currentUrl;
00688         QString label;
00689         QString iconName = "folder";
00690         bool appLocal = true;
00691         if (KFilePlaceEditDialog::getInformation(true, url, label,
00692                                                  iconName, true, appLocal, 64, this))
00693         {
00694             QString appName;
00695             if (appLocal) appName = KGlobal::mainComponent().componentName();
00696 
00697             placesModel->addPlace(label, url, iconName, appName, index);
00698         }
00699     }
00700 
00701     index = placesModel->closestItem(d->currentUrl);
00702     selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
00703 }
00704 
00705 void KFilePlacesView::resizeEvent(QResizeEvent *event)
00706 {
00707     QListView::resizeEvent(event);
00708     d->adaptItemSize();
00709 }
00710 
00711 void KFilePlacesView::showEvent(QShowEvent *event)
00712 {
00713     QListView::showEvent(event);
00714     QTimer::singleShot(100, this, SLOT(_k_enableSmoothItemResizing()));
00715 }
00716 
00717 void KFilePlacesView::hideEvent(QHideEvent *event)
00718 {
00719     QListView::hideEvent(event);
00720     d->smoothItemResizing = false;
00721 }
00722 
00723 void KFilePlacesView::dragEnterEvent(QDragEnterEvent *event)
00724 {
00725     QListView::dragEnterEvent(event);
00726     d->dragging = true;
00727 
00728     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00729     delegate->setShowHoverIndication(false);
00730 
00731     d->dropRect = QRect();
00732 }
00733 
00734 void KFilePlacesView::dragLeaveEvent(QDragLeaveEvent *event)
00735 {
00736     QListView::dragLeaveEvent(event);
00737     d->dragging = false;
00738 
00739     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00740     delegate->setShowHoverIndication(true);
00741 
00742     setDirtyRegion(d->dropRect);
00743 }
00744 
00745 void KFilePlacesView::dragMoveEvent(QDragMoveEvent *event)
00746 {
00747     QListView::dragMoveEvent(event);
00748 
00749     // update the drop indicator
00750     const QPoint pos = event->pos();
00751     const QModelIndex index = indexAt(pos);
00752     setDirtyRegion(d->dropRect);
00753     if (index.isValid()) {
00754         const QRect rect = visualRect(index);
00755         const int gap = d->insertIndicatorHeight(rect.height());
00756         if (d->insertAbove(rect, pos)) {
00757             // indicate that the item will be inserted above the current place
00758             d->dropRect = QRect(rect.left(), rect.top() - gap / 2,
00759                                 rect.width(), gap);
00760         } else if (d->insertBelow(rect, pos)) {
00761             // indicate that the item will be inserted below the current place
00762             d->dropRect = QRect(rect.left(), rect.bottom() + 1 -  gap / 2,
00763                                 rect.width(), gap);
00764         } else {
00765             // indicate that the item be dropped above the current place
00766             d->dropRect = rect;
00767         }
00768     }
00769 
00770     setDirtyRegion(d->dropRect);
00771 }
00772 
00773 void KFilePlacesView::dropEvent(QDropEvent *event)
00774 {
00775     const QPoint pos = event->pos();
00776     const QModelIndex index = indexAt(pos);
00777     if (index.isValid()) {
00778         const QRect rect = visualRect(index);
00779         if (!d->insertAbove(rect, pos) && !d->insertBelow(rect, pos)) {
00780             KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00781             Q_ASSERT(placesModel != 0);
00782             emit urlsDropped(placesModel->url(index), event, this);
00783             event->acceptProposedAction();
00784         }
00785     }
00786 
00787     QListView::dropEvent(event);
00788     d->dragging = false;
00789 
00790     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00791     delegate->setShowHoverIndication(true);
00792 }
00793 
00794 void KFilePlacesView::paintEvent(QPaintEvent* event)
00795 {
00796     QListView::paintEvent(event);
00797     if (d->dragging && !d->dropRect.isEmpty()) {
00798         // draw drop indicator
00799         QPainter painter(viewport());
00800 
00801         const QModelIndex index = indexAt(d->dropRect.topLeft());
00802         const QRect itemRect = visualRect(index);
00803         const bool drawInsertIndicator = !d->dropOnPlace ||
00804                                          d->dropRect.height() <= d->insertIndicatorHeight(itemRect.height());
00805 
00806         if (drawInsertIndicator) {
00807             // draw indicator for inserting items
00808             QBrush blendedBrush = viewOptions().palette.brush(QPalette::Normal, QPalette::Highlight);
00809             QColor color = blendedBrush.color();
00810 
00811             const int y = (d->dropRect.top() + d->dropRect.bottom()) / 2;
00812             const int thickness = d->dropRect.height() / 2;
00813             Q_ASSERT(thickness >= 1);
00814             int alpha = 255;
00815             const int alphaDec = alpha / (thickness + 1);
00816             for (int i = 0; i < thickness; i++) {
00817                 color.setAlpha(alpha);
00818                 alpha -= alphaDec;
00819                 painter.setPen(color);
00820                 painter.drawLine(d->dropRect.left(), y - i, d->dropRect.right(), y - i);
00821                 painter.drawLine(d->dropRect.left(), y + i, d->dropRect.right(), y + i);
00822             }
00823         } else {
00824             // draw indicator for copying/moving/linking to items
00825             QStyleOptionViewItemV4 opt;
00826             opt.initFrom(this);
00827             opt.rect = itemRect;
00828             opt.state = QStyle::State_Enabled | QStyle::State_MouseOver;
00829             style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, &painter, this);
00830         }
00831     }
00832 }
00833 
00834 void KFilePlacesView::setModel(QAbstractItemModel *model)
00835 {
00836     QListView::setModel(model);
00837     d->updateHiddenRows();
00838     // Uses Qt::QueuedConnection to delay the time when the slot will be
00839     // called. In case of an item move the remove+add will be done before
00840     // we adapt the item size (otherwise we'd get it wrong as we'd execute
00841     // it after the remove only).
00842     connect(model, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
00843             this, SLOT(adaptItemSize()), Qt::QueuedConnection);
00844     connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)),
00845             d->watcher, SLOT(currentIndexChanged(const QModelIndex&)));
00846 }
00847 
00848 void KFilePlacesView::rowsInserted(const QModelIndex &parent, int start, int end)
00849 {
00850     QListView::rowsInserted(parent, start, end);
00851     setUrl(d->currentUrl);
00852 
00853     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00854     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00855 
00856     for (int i=start; i<=end; ++i) {
00857         QModelIndex index = placesModel->index(i, 0, parent);
00858         if (d->showAll || !placesModel->isHidden(index)) {
00859             delegate->addAppearingItem(index);
00860         } else {
00861             setRowHidden(i, true);
00862         }
00863     }
00864 
00865     if (d->itemAppearTimeline.state()!=QTimeLine::Running) {
00866         delegate->setAppearingItemProgress(0.0);
00867         d->itemAppearTimeline.start();
00868     }
00869 
00870     d->adaptItemSize();
00871 }
00872 
00873 QSize KFilePlacesView::sizeHint() const
00874 {
00875     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00876     if (!placesModel) {
00877         return QListView::sizeHint();
00878     }
00879     const int height = QListView::sizeHint().height();
00880     QFontMetrics fm = d->q->fontMetrics();
00881     int textWidth = 0;
00882 
00883     for (int i=0; i<placesModel->rowCount(); ++i) {
00884         QModelIndex index = placesModel->index(i, 0);
00885         if (!placesModel->isHidden(index))
00886            textWidth = qMax(textWidth,fm.width(index.data(Qt::DisplayRole).toString()));
00887     }
00888 
00889     const int iconSize = KIconLoader::global()->currentSize(KIconLoader::Dialog);
00890     return QSize(iconSize + textWidth + fm.height() / 2, height);
00891 }
00892 
00893 void KFilePlacesView::Private::setCurrentIndex(const QModelIndex &index)
00894 {
00895     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00896 
00897     if (placesModel==0) return;
00898 
00899     KUrl url = placesModel->url(index);
00900 
00901     if (url.isValid()) {
00902         currentUrl = url;
00903         updateHiddenRows();
00904         emit q->urlChanged(url);
00905         if (showAll) {
00906             q->setShowAll(false);
00907         }
00908     } else {
00909         q->setUrl(currentUrl);
00910     }
00911 }
00912 
00913 void KFilePlacesView::Private::adaptItemSize()
00914 {
00915     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
00916     if (!delegate) return;
00917 
00918     if (!autoResizeItems) {
00919         int size = q->iconSize().width(); // Assume width == height
00920         delegate->setIconSize(size);
00921         q->scheduleDelayedItemsLayout();
00922         return;
00923     }
00924 
00925     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00926 
00927     if (placesModel==0) return;
00928 
00929     int rowCount = placesModel->rowCount();
00930 
00931     if (!showAll) {
00932         rowCount-= placesModel->hiddenCount();
00933 
00934         QModelIndex current = placesModel->closestItem(currentUrl);
00935 
00936         if (placesModel->isHidden(current)) {
00937             rowCount++;
00938         }
00939     }
00940 
00941     if (rowCount==0) return; // We've nothing to display anyway
00942 
00943     const int minSize = 16;
00944     const int maxSize = 64;
00945 
00946     int textWidth = 0;
00947     QFontMetrics fm = q->fontMetrics();
00948     for (int i=0; i<placesModel->rowCount(); ++i) {
00949         QModelIndex index = placesModel->index(i, 0);
00950 
00951         if (!placesModel->isHidden(index))
00952            textWidth = qMax(textWidth,fm.width(index.data(Qt::DisplayRole).toString()));
00953     }
00954 
00955     const int margin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, q) + 1;
00956     const int maxWidth = q->viewport()->width() - textWidth - 4 * margin - 1;
00957     const int maxHeight = ((q->height() - (fm.height() / 2) * rowCount) / rowCount) - 1;
00958 
00959     int size = qMin(maxHeight, maxWidth);
00960 
00961     if (size<minSize) {
00962         size = minSize;
00963     } else if (size>maxSize) {
00964         size = maxSize;
00965     } else {
00966         // Make it a multiple of 16
00967         size &= ~0xf;
00968     }
00969 
00970     if (size==delegate->iconSize()) return;
00971 
00972     if (smoothItemResizing) {
00973         oldSize = delegate->iconSize();
00974         endSize = size;
00975         if (adaptItemsTimeline.state()!=QTimeLine::Running) {
00976             adaptItemsTimeline.start();
00977         }
00978     } else {
00979         delegate->setIconSize(size);
00980         q->scheduleDelayedItemsLayout();
00981     }
00982 }
00983 
00984 void KFilePlacesView::Private::updateHiddenRows()
00985 {
00986     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00987 
00988     if (placesModel==0) return;
00989 
00990     int rowCount = placesModel->rowCount();
00991     QModelIndex current = placesModel->closestItem(currentUrl);
00992 
00993     for (int i=0; i<rowCount; ++i) {
00994         QModelIndex index = placesModel->index(i, 0);
00995         if (index!=current && placesModel->isHidden(index) && !showAll) {
00996             q->setRowHidden(i, true);
00997         } else {
00998             q->setRowHidden(i, false);
00999         }
01000     }
01001 
01002     adaptItemSize();
01003 }
01004 
01005 bool KFilePlacesView::Private::insertAbove(const QRect &itemRect, const QPoint &pos) const
01006 {
01007     if (dropOnPlace) {
01008         return pos.y() < itemRect.top() + insertIndicatorHeight(itemRect.height()) / 2;
01009     }
01010 
01011     return pos.y() < itemRect.top() + (itemRect.height() / 2);
01012 }
01013 
01014 bool KFilePlacesView::Private::insertBelow(const QRect &itemRect, const QPoint &pos) const
01015 {
01016     if (dropOnPlace) {
01017         return pos.y() > itemRect.bottom() - insertIndicatorHeight(itemRect.height()) / 2;
01018     }
01019 
01020     return pos.y() >= itemRect.top() + (itemRect.height() / 2);
01021 }
01022 
01023 int KFilePlacesView::Private::insertIndicatorHeight(int itemHeight) const
01024 {
01025     const int min = 4;
01026     const int max = 12;
01027 
01028     int height = itemHeight / 4;
01029     if (height < min) {
01030         height = min;
01031     } else if (height > max) {
01032         height = max;
01033     }
01034     return height;
01035 }
01036 
01037 void KFilePlacesView::Private::fadeCapacityBar(const QModelIndex &index, FadeType fadeType)
01038 {
01039     QTimeLine *timeLine = delegate->fadeAnimationForIndex(index);
01040     delete timeLine;
01041     delegate->removeFadeAnimation(index);
01042     timeLine = new QTimeLine(250, q);
01043     connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(_k_capacityBarFadeValueChanged()));
01044     if (fadeType == FadeIn) {
01045         timeLine->setDirection(QTimeLine::Forward);
01046         timeLine->setCurrentTime(0);
01047     } else {
01048         timeLine->setDirection(QTimeLine::Backward);
01049         timeLine->setCurrentTime(250);
01050     }
01051     delegate->addFadeAnimation(index, timeLine);
01052     timeLine->start();
01053 }
01054 
01055 void KFilePlacesView::Private::_k_placeClicked(const QModelIndex &index)
01056 {
01057     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
01058 
01059     if (placesModel==0) return;
01060 
01061     lastClickedIndex = QPersistentModelIndex();
01062 
01063     if (placesModel->setupNeeded(index)) {
01064         QObject::connect(placesModel, SIGNAL(setupDone(const QModelIndex &, bool)),
01065                          q, SLOT(_k_storageSetupDone(const QModelIndex &, bool)));
01066 
01067         lastClickedIndex = index;
01068         placesModel->requestSetup(index);
01069         return;
01070     }
01071 
01072     setCurrentIndex(index);
01073 }
01074 
01075 void KFilePlacesView::Private::_k_placeEntered(const QModelIndex &index)
01076 {
01077     fadeCapacityBar(index, FadeIn);
01078     pollingRequestCount++;
01079     if (pollingRequestCount == 1) {
01080         pollDevices.start();
01081     }
01082 }
01083 
01084 void KFilePlacesView::Private::_k_placeLeft(const QModelIndex &index)
01085 {
01086     fadeCapacityBar(index, FadeOut);
01087     pollingRequestCount--;
01088     if (!pollingRequestCount) {
01089         pollDevices.stop();
01090     }
01091 }
01092 
01093 void KFilePlacesView::Private::_k_storageSetupDone(const QModelIndex &index, bool success)
01094 {
01095     if (index!=lastClickedIndex) {
01096         return;
01097     }
01098 
01099     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
01100 
01101     QObject::disconnect(placesModel, SIGNAL(setupDone(const QModelIndex &, bool)),
01102                         q, SLOT(_k_storageSetupDone(const QModelIndex &, bool)));
01103 
01104     if (success) {
01105         setCurrentIndex(lastClickedIndex);
01106     } else {
01107         q->setUrl(currentUrl);
01108     }
01109 
01110     lastClickedIndex = QPersistentModelIndex();
01111 }
01112 
01113 void KFilePlacesView::Private::_k_adaptItemsUpdate(qreal value)
01114 {
01115     int add = (endSize-oldSize)*value;
01116 
01117     int size = oldSize+add;
01118 
01119     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
01120     delegate->setIconSize(size);
01121     q->scheduleDelayedItemsLayout();
01122 }
01123 
01124 void KFilePlacesView::Private::_k_itemAppearUpdate(qreal value)
01125 {
01126     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
01127 
01128     delegate->setAppearingItemProgress(value);
01129     q->scheduleDelayedItemsLayout();
01130 }
01131 
01132 void KFilePlacesView::Private::_k_itemDisappearUpdate(qreal value)
01133 {
01134     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
01135 
01136     delegate->setDisappearingItemProgress(value);
01137 
01138     if (value>=1.0) {
01139         updateHiddenRows();
01140     }
01141 
01142     q->scheduleDelayedItemsLayout();
01143 }
01144 
01145 void KFilePlacesView::Private::_k_enableSmoothItemResizing()
01146 {
01147     smoothItemResizing = true;
01148 }
01149 
01150 void KFilePlacesView::Private::_k_trashUpdated(KJob *job)
01151 {
01152     if (job->error()) {
01153         static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
01154     }
01155     org::kde::KDirNotify::emitFilesAdded("trash:/");
01156 }
01157 
01158 void KFilePlacesView::Private::_k_capacityBarFadeValueChanged()
01159 {
01160     const QModelIndex index = delegate->indexForFadeAnimation(static_cast<QTimeLine*>(q->sender()));
01161     if (!index.isValid()) {
01162         return;
01163     }
01164     q->update(index);
01165 }
01166 
01167 void KFilePlacesView::Private::_k_triggerDevicePolling()
01168 {
01169     const QModelIndex hoveredIndex = watcher->hoveredIndex();
01170     if (hoveredIndex.isValid()) {
01171         const KFilePlacesModel *placesModel = static_cast<const KFilePlacesModel*>(hoveredIndex.model());
01172         if (placesModel->isDevice(hoveredIndex)) {
01173             q->update(hoveredIndex);
01174         }
01175     }
01176     const QModelIndex focusedIndex = watcher->focusedIndex();
01177     if (focusedIndex.isValid() && focusedIndex != hoveredIndex) {
01178         const KFilePlacesModel *placesModel = static_cast<const KFilePlacesModel*>(focusedIndex.model());
01179         if (placesModel->isDevice(focusedIndex)) {
01180             q->update(focusedIndex);
01181         }
01182     }
01183 }
01184 
01185 void KFilePlacesView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
01186 {
01187     QListView::dataChanged(topLeft, bottomRight);
01188     d->adaptItemSize();
01189 }
01190 
01191 #include "kfileplacesview.moc"
01192 #include "kfileplacesview_p.moc"

KFile

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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.3
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