• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License version 2 as published by the Free Software Foundation.
00007 
00008     This library is distributed in the hope that it will be useful,
00009     but WITHOUT ANY WARRANTY; without even the implied warranty of
00010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011     Library General Public License for more details.
00012 
00013     You should have received a copy of the GNU Library General Public License
00014     along with this library; see the file COPYING.LIB.  If not, write to
00015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016     Boston, MA 02110-1301, USA.
00017 
00018 */
00019 
00020 #include "kfileplacesview.h"
00021 
00022 #include <QtCore/QTimeLine>
00023 #include <QtCore/QTimer>
00024 #include <QtGui/QMenu>
00025 #include <QtGui/QPainter>
00026 #include <QtGui/QStyledItemDelegate>
00027 #include <QtGui/QKeyEvent>
00028 
00029 #include <kdebug.h>
00030 
00031 #include <kcomponentdata.h>
00032 #include <kdirnotify.h>
00033 #include <kglobalsettings.h>
00034 #include <kiconloader.h>
00035 #include <klocale.h>
00036 #include <kmessagebox.h>
00037 #include <knotification.h>
00038 #include <kio/job.h>
00039 #include <kio/jobuidelegate.h>
00040 #include <kjob.h>
00041 #include <solid/storageaccess.h>
00042 #include <solid/storagedrive.h>
00043 #include <solid/storagevolume.h>
00044 #include <solid/opticaldrive.h>
00045 #include <solid/opticaldisc.h>
00046 
00047 #include "kfileplaceeditdialog.h"
00048 #include "kfileplacesmodel.h"
00049 
00050 class KFilePlacesViewDelegate : public QStyledItemDelegate
00051 {
00052 public:
00053     KFilePlacesViewDelegate(KFilePlacesView *parent);
00054     virtual ~KFilePlacesViewDelegate();
00055     virtual QSize sizeHint(const QStyleOptionViewItem &option,
00056                            const QModelIndex &index) const;
00057     virtual void paint(QPainter *painter,
00058                        const QStyleOptionViewItem &option,
00059                        const QModelIndex &index) const;
00060 
00061     int iconSize() const;
00062     void setIconSize(int newSize);
00063 
00064     void addAppearingItem(const QModelIndex &index);
00065     void setAppearingItemProgress(qreal value);
00066     void addDisappearingItem(const QModelIndex &index);
00067     void setDisappearingItemProgress(qreal value);
00068 
00069     void setShowHoverIndication(bool show);
00070 
00071 private:
00072     KFilePlacesView *m_view;
00073     int m_iconSize;
00074 
00075     QList<QPersistentModelIndex> m_appearingItems;
00076     int m_appearingIconSize;
00077     qreal m_appearingOpacity;
00078 
00079     QList<QPersistentModelIndex> m_disappearingItems;
00080     int m_disappearingIconSize;
00081     qreal m_disappearingOpacity;
00082 
00083     bool m_showHoverIndication;
00084 };
00085 
00086 KFilePlacesViewDelegate::KFilePlacesViewDelegate(KFilePlacesView *parent) :
00087     QStyledItemDelegate(parent),
00088     m_view(parent),
00089     m_iconSize(48),
00090     m_appearingIconSize(0),
00091     m_appearingOpacity(0.0),
00092     m_disappearingIconSize(0),
00093     m_disappearingOpacity(0.0),
00094     m_showHoverIndication(true)
00095 {
00096 }
00097 
00098 KFilePlacesViewDelegate::~KFilePlacesViewDelegate()
00099 {
00100 }
00101 
00102 QSize KFilePlacesViewDelegate::sizeHint(const QStyleOptionViewItem &option,
00103                                         const QModelIndex &index) const
00104 {
00105     QSize size = QStyledItemDelegate::sizeHint(option, index);
00106     int iconSize = m_iconSize;
00107     if (m_appearingItems.contains(index)) {
00108         iconSize = m_appearingIconSize;
00109     } else if (m_disappearingItems.contains(index)) {
00110         iconSize = m_disappearingIconSize;
00111     }
00112 
00113     size.setHeight(iconSize + KDialog::marginHint());
00114     return size;
00115 }
00116 
00117 void KFilePlacesViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
00118 {
00119     painter->save();
00120 
00121     if (m_appearingItems.contains(index)) {
00122         painter->setOpacity(m_appearingOpacity);
00123     } else if (m_disappearingItems.contains(index)) {
00124         painter->setOpacity(m_disappearingOpacity);
00125     }
00126 
00127     QStyleOptionViewItemV4 opt = option;
00128     opt.decorationSize = QSize(m_iconSize, m_iconSize);
00129     if (!m_showHoverIndication) {
00130         opt.state &= ~QStyle::State_MouseOver;
00131     }
00132     QStyledItemDelegate::paint(painter, opt, index);
00133 
00134     painter->restore();
00135 }
00136 
00137 int KFilePlacesViewDelegate::iconSize() const
00138 {
00139     return m_iconSize;
00140 }
00141 
00142 void KFilePlacesViewDelegate::setIconSize(int newSize)
00143 {
00144     m_iconSize = newSize;
00145 }
00146 
00147 void KFilePlacesViewDelegate::addAppearingItem(const QModelIndex &index)
00148 {
00149     m_appearingItems << index;
00150 }
00151 
00152 void KFilePlacesViewDelegate::setAppearingItemProgress(qreal value)
00153 {
00154     if (value<=0.25) {
00155         m_appearingOpacity = 0.0;
00156         m_appearingIconSize = iconSize()*value*4;
00157 
00158         if (m_appearingIconSize>=m_iconSize) {
00159             m_appearingIconSize = m_iconSize;
00160         }
00161     } else {
00162         m_appearingIconSize = m_iconSize;
00163         m_appearingOpacity = (value-0.25)*4/3;
00164 
00165         if (value>=1.0) {
00166             m_appearingItems.clear();
00167         }
00168     }
00169 }
00170 
00171 void KFilePlacesViewDelegate::addDisappearingItem(const QModelIndex &index)
00172 {
00173     m_disappearingItems << index;
00174 }
00175 
00176 void KFilePlacesViewDelegate::setDisappearingItemProgress(qreal value)
00177 {
00178     value = 1.0 - value;
00179 
00180     if (value<=0.25) {
00181         m_disappearingOpacity = 0.0;
00182         m_disappearingIconSize = iconSize()*value*4;
00183 
00184         if (m_disappearingIconSize>=m_iconSize) {
00185             m_disappearingIconSize = m_iconSize;
00186         }
00187 
00188         if (value<=0.0) {
00189             m_disappearingItems.clear();
00190         }
00191     } else {
00192         m_disappearingIconSize = m_iconSize;
00193         m_disappearingOpacity = (value-0.25)*4/3;
00194     }
00195 }
00196 
00197 void KFilePlacesViewDelegate::setShowHoverIndication(bool show)
00198 {
00199     m_showHoverIndication = show;
00200 }
00201 
00202 class KFilePlacesView::Private
00203 {
00204 public:
00205     Private(KFilePlacesView *parent) : q(parent) { }
00206 
00207     KFilePlacesView * const q;
00208 
00209     KUrl currentUrl;
00210     bool autoResizeItems;
00211     bool showAll;
00212     bool smoothItemResizing;
00213     bool dropOnPlace;
00214     bool dragging;
00215     Solid::StorageAccess *lastClickedStorage;
00216     QPersistentModelIndex lastClickedIndex;
00217 
00218     QRect dropRect;
00219 
00220     void setCurrentIndex(const QModelIndex &index);
00221     void adaptItemSize();
00222     void updateHiddenRows();
00223     bool insertAbove(const QRect &itemRect, const QPoint &pos) const;
00224     bool insertBelow(const QRect &itemRect, const QPoint &pos) const;
00225     int insertIndicatorHeight(int itemHeight) const;
00226 
00227     void _k_placeClicked(const QModelIndex &index);
00228     void _k_placeActivated(const QModelIndex &index);
00229     void _k_storageSetupDone(const QModelIndex &index, bool success);
00230     void _k_adaptItemsUpdate(qreal value);
00231     void _k_itemAppearUpdate(qreal value);
00232     void _k_itemDisappearUpdate(qreal value);
00233     void _k_enableSmoothItemResizing();
00234     void _k_trashUpdated(KJob *job);
00235 
00236     QTimeLine adaptItemsTimeline;
00237     int oldSize, endSize;
00238 
00239     QTimeLine itemAppearTimeline;
00240     QTimeLine itemDisappearTimeline;
00241 };
00242 
00243 KFilePlacesView::KFilePlacesView(QWidget *parent)
00244     : QListView(parent), d(new Private(this))
00245 {
00246     d->showAll = false;
00247     d->smoothItemResizing = false;
00248     d->dropOnPlace = false;
00249     d->autoResizeItems = true;
00250     d->dragging = false;
00251     d->lastClickedStorage = 0;
00252 
00253     setSelectionRectVisible(false);
00254     setSelectionMode(SingleSelection);
00255 
00256     setDragEnabled(true);
00257     setAcceptDrops(true);
00258     setDropIndicatorShown(false);
00259     setFrameStyle(QFrame::NoFrame);
00260 
00261     setResizeMode(Adjust);
00262     setItemDelegate(new KFilePlacesViewDelegate(this));
00263 
00264     QPalette palette = viewport()->palette();
00265     palette.setColor(viewport()->backgroundRole(), Qt::transparent);
00266     viewport()->setPalette(palette);
00267 
00268     connect(this, SIGNAL(clicked(const QModelIndex&)),
00269             this, SLOT(_k_placeClicked(const QModelIndex&)));
00270     connect(this, SIGNAL(activated(const QModelIndex&)),
00271             this, SLOT(_k_placeActivated(const QModelIndex&)));
00272 
00273     connect(&d->adaptItemsTimeline, SIGNAL(valueChanged(qreal)),
00274             this, SLOT(_k_adaptItemsUpdate(qreal)));
00275     d->adaptItemsTimeline.setDuration(500);
00276     d->adaptItemsTimeline.setUpdateInterval(5);
00277     d->adaptItemsTimeline.setCurveShape(QTimeLine::EaseInOutCurve);
00278 
00279     connect(&d->itemAppearTimeline, SIGNAL(valueChanged(qreal)),
00280             this, SLOT(_k_itemAppearUpdate(qreal)));
00281     d->itemAppearTimeline.setDuration(500);
00282     d->itemAppearTimeline.setUpdateInterval(5);
00283     d->itemAppearTimeline.setCurveShape(QTimeLine::EaseInOutCurve);
00284 
00285     connect(&d->itemDisappearTimeline, SIGNAL(valueChanged(qreal)),
00286             this, SLOT(_k_itemDisappearUpdate(qreal)));
00287     d->itemDisappearTimeline.setDuration(500);
00288     d->itemDisappearTimeline.setUpdateInterval(5);
00289     d->itemDisappearTimeline.setCurveShape(QTimeLine::EaseInOutCurve);
00290 }
00291 
00292 KFilePlacesView::~KFilePlacesView()
00293 {
00294     delete d;
00295 }
00296 
00297 void KFilePlacesView::setDropOnPlaceEnabled(bool enabled)
00298 {
00299     d->dropOnPlace = enabled;
00300 }
00301 
00302 bool KFilePlacesView::isDropOnPlaceEnabled() const
00303 {
00304     return d->dropOnPlace;
00305 }
00306 
00307 void KFilePlacesView::setAutoResizeItemsEnabled(bool enabled)
00308 {
00309     d->autoResizeItems = enabled;
00310 }
00311 
00312 bool KFilePlacesView::isAutoResizeItemsEnabled() const
00313 {
00314     return d->autoResizeItems;
00315 }
00316 
00317 void KFilePlacesView::setUrl(const KUrl &url)
00318 {
00319     KUrl oldUrl = d->currentUrl;
00320     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00321 
00322     if (placesModel==0) return;
00323 
00324     QModelIndex index = placesModel->closestItem(url);
00325     QModelIndex current = selectionModel()->currentIndex();
00326 
00327     if (index.isValid()) {
00328         if (current!=index && placesModel->isHidden(current)) {
00329             KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00330             delegate->addDisappearingItem(current);
00331 
00332             if (d->itemDisappearTimeline.state()!=QTimeLine::Running) {
00333                 delegate->setDisappearingItemProgress(0.0);
00334                 d->itemDisappearTimeline.start();
00335             }
00336         }
00337 
00338         if (current!=index && placesModel->isHidden(index)) {
00339             KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00340             delegate->addAppearingItem(index);
00341 
00342             if (d->itemAppearTimeline.state()!=QTimeLine::Running) {
00343                 delegate->setAppearingItemProgress(0.0);
00344                 d->itemAppearTimeline.start();
00345             }
00346 
00347             setRowHidden(index.row(), false);
00348         }
00349 
00350         d->currentUrl = url;
00351         selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
00352     } else {
00353         d->currentUrl = KUrl();
00354         selectionModel()->clear();
00355     }
00356 
00357     if (!current.isValid()) {
00358         d->updateHiddenRows();
00359     }
00360 }
00361 
00362 void KFilePlacesView::setShowAll(bool showAll)
00363 {
00364     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00365 
00366     if (placesModel==0) return;
00367 
00368     d->showAll = showAll;
00369 
00370     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00371 
00372     int rowCount = placesModel->rowCount();
00373     QModelIndex current = placesModel->closestItem(d->currentUrl);
00374 
00375     if (showAll) {
00376         d->updateHiddenRows();
00377 
00378         for (int i=0; i<rowCount; ++i) {
00379             QModelIndex index = placesModel->index(i, 0);
00380             if (index!=current && placesModel->isHidden(index)) {
00381                 delegate->addAppearingItem(index);
00382             }
00383         }
00384 
00385         if (d->itemAppearTimeline.state()!=QTimeLine::Running) {
00386             delegate->setAppearingItemProgress(0.0);
00387             d->itemAppearTimeline.start();
00388         }
00389     } else {
00390         for (int i=0; i<rowCount; ++i) {
00391             QModelIndex index = placesModel->index(i, 0);
00392             if (index!=current && placesModel->isHidden(index)) {
00393                 delegate->addDisappearingItem(index);
00394             }
00395         }
00396 
00397         if (d->itemDisappearTimeline.state()!=QTimeLine::Running) {
00398             delegate->setDisappearingItemProgress(0.0);
00399             d->itemDisappearTimeline.start();
00400         }
00401     }
00402 }
00403 
00404 void KFilePlacesView::contextMenuEvent(QContextMenuEvent *event)
00405 {
00406     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00407     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00408 
00409     if (placesModel==0) return;
00410 
00411     QModelIndex index = indexAt(event->pos());
00412     QString label = placesModel->text(index).replace('&',"&&");
00413 
00414     QMenu menu;
00415 
00416     QAction *edit = 0;
00417     QAction *hide = 0;
00418     QAction *emptyTrash = 0;
00419     if (index.isValid()) {
00420         if (!placesModel->isDevice(index)) {
00421             if (placesModel->url(index) == KUrl("trash:/")) {
00422                 emptyTrash = menu.addAction(KIcon("trash-empty"), i18nc("@action:inmenu", "Empty Trash"));
00423                 KConfig trashConfig("trashrc", KConfig::SimpleConfig);
00424                 emptyTrash->setEnabled(!trashConfig.group("Status").readEntry("Empty", true));
00425                 menu.addSeparator();
00426             }
00427 
00428             edit = menu.addAction(KIcon("document-properties"), i18n("&Edit '%1'...", label));
00429         }
00430 
00431         hide = menu.addAction(i18n("&Hide '%1'", label));
00432         hide->setCheckable(true);
00433         hide->setChecked(placesModel->isHidden(index));
00434     }
00435 
00436     QAction *showAll = 0;
00437     if (placesModel->hiddenCount()>0) {
00438         showAll = menu.addAction(i18n("&Show All Entries"));
00439         showAll->setCheckable(true);
00440         showAll->setChecked(d->showAll);
00441     }
00442 
00443     QAction* remove = 0L;
00444     QAction* teardown = 0L;
00445     if (index.isValid()) {
00446         if (!placesModel->isDevice(index)) {
00447             menu.addSeparator();
00448             remove = menu.addAction( KIcon("edit-delete"), i18n("&Remove '%1'", label));
00449         } else {
00450             teardown = placesModel->teardownActionForIndex(index);
00451             if (teardown!=0) {
00452                 teardown->setParent(&menu);
00453                 menu.addSeparator();
00454                 menu.addAction(teardown);
00455             }
00456         }
00457     }
00458 
00459     if (menu.isEmpty()) return;
00460 
00461     QAction *result = menu.exec(event->globalPos());
00462 
00463     if (emptyTrash != 0 && result == emptyTrash) {
00464         const QString text = i18nc("@info", "Do you really want to empty the Trash? All items will be deleted.");
00465         const bool del = KMessageBox::warningContinueCancel(window(),
00466                                                             text,
00467                                                             QString(),
00468                                                             KGuiItem(i18nc("@action:button", "Empty Trash"),
00469                                                                      KIcon("user-trash"))
00470                                                            ) == KMessageBox::Continue;
00471         if (del) {
00472             QByteArray packedArgs;
00473             QDataStream stream(&packedArgs, QIODevice::WriteOnly);
00474             stream << int(1);
00475             KIO::Job *job = KIO::special(KUrl("trash:/"), packedArgs);
00476             KNotification::event("Trash: emptied", QString() , QPixmap() , 0, KNotification::DefaultEvent);
00477             job->ui()->setWindow(parentWidget());
00478             connect(job, SIGNAL(result(KJob*)), SLOT(_k_trashUpdated(KJob*)));
00479         }
00480     } else if (edit != 0 && result == edit) {
00481         KBookmark bookmark = placesModel->bookmarkForIndex(index);
00482         KUrl url = bookmark.url();
00483         QString description = bookmark.text();
00484         QString iconName = bookmark.icon();
00485         bool appLocal = !bookmark.metaDataItem("OnlyInApp").isEmpty();
00486 
00487         if (KFilePlaceEditDialog::getInformation(true, url, description,
00488                                                  iconName, appLocal, 64, this))
00489         {
00490             QString appName;
00491             if (appLocal) appName = KGlobal::mainComponent().componentName();
00492 
00493             placesModel->editPlace(index, description, url, iconName, appName);
00494         }
00495 
00496     } else if (remove != 0 && result == remove) {
00497         placesModel->removePlace(index);
00498     } else if (hide != 0 && result == hide) {
00499         placesModel->setPlaceHidden(index, hide->isChecked());
00500         QModelIndex current = placesModel->closestItem(d->currentUrl);
00501 
00502         if (index!=current && !d->showAll && hide->isChecked()) {
00503             delegate->addDisappearingItem(index);
00504 
00505             if (d->itemDisappearTimeline.state()!=QTimeLine::Running) {
00506                 delegate->setDisappearingItemProgress(0.0);
00507                 d->itemDisappearTimeline.start();
00508             }
00509         }
00510     } else if (showAll != 0 && result == showAll) {
00511         setShowAll(showAll->isChecked());
00512     } else if (teardown != 0 && result == teardown) {
00513         placesModel->requestTeardown(index);
00514     }
00515 
00516     index = placesModel->closestItem(d->currentUrl);
00517     selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
00518 }
00519 
00520 void KFilePlacesView::resizeEvent(QResizeEvent *event)
00521 {
00522     QListView::resizeEvent(event);
00523     d->adaptItemSize();
00524 }
00525 
00526 void KFilePlacesView::showEvent(QShowEvent *event)
00527 {
00528     QListView::showEvent(event);
00529     QTimer::singleShot(100, this, SLOT(_k_enableSmoothItemResizing()));
00530 }
00531 
00532 void KFilePlacesView::hideEvent(QHideEvent *event)
00533 {
00534     QListView::hideEvent(event);
00535     d->smoothItemResizing = false;
00536 }
00537 
00538 void KFilePlacesView::dragEnterEvent(QDragEnterEvent *event)
00539 {
00540     QListView::dragEnterEvent(event);
00541     d->dragging = true;
00542 
00543     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00544     delegate->setShowHoverIndication(false);
00545 
00546     d->dropRect = QRect();
00547 }
00548 
00549 void KFilePlacesView::dragLeaveEvent(QDragLeaveEvent *event)
00550 {
00551     QListView::dragLeaveEvent(event);
00552     d->dragging = false;
00553 
00554     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00555     delegate->setShowHoverIndication(true);
00556 
00557     setDirtyRegion(d->dropRect);
00558 }
00559 
00560 void KFilePlacesView::dragMoveEvent(QDragMoveEvent *event)
00561 {
00562     QListView::dragMoveEvent(event);
00563 
00564     // update the drop indicator
00565     const QPoint pos = event->pos();
00566     const QModelIndex index = indexAt(pos);
00567     setDirtyRegion(d->dropRect);
00568     if (index.isValid()) {
00569         const QRect rect = visualRect(index);
00570         const int gap = d->insertIndicatorHeight(rect.height());
00571         if (d->insertAbove(rect, pos)) {
00572             // indicate that the item will be inserted above the current place
00573             d->dropRect = QRect(rect.left(), rect.top() - gap / 2,
00574                                 rect.width(), gap);
00575         } else if (d->insertBelow(rect, pos)) {
00576             // indicate that the item will be inserted below the current place
00577             d->dropRect = QRect(rect.left(), rect.bottom() + 1 -  gap / 2,
00578                                 rect.width(), gap);
00579         } else {
00580             // indicate that the item be dropped above the current place
00581             d->dropRect = rect;
00582         }
00583     }
00584 
00585     setDirtyRegion(d->dropRect);
00586 }
00587 
00588 void KFilePlacesView::dropEvent(QDropEvent *event)
00589 {
00590     const QPoint pos = event->pos();
00591     const QModelIndex index = indexAt(pos);
00592     if (index.isValid()) {
00593         const QRect rect = visualRect(index);
00594         if (!d->insertAbove(rect, pos) && !d->insertBelow(rect, pos)) {
00595             KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00596             Q_ASSERT(placesModel != 0);
00597             emit urlsDropped(placesModel->url(index), event, this);
00598             event->acceptProposedAction();
00599         }
00600     }
00601 
00602     QListView::dropEvent(event);
00603     d->dragging = false;
00604 
00605     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00606     delegate->setShowHoverIndication(true);
00607 }
00608 
00609 void KFilePlacesView::paintEvent(QPaintEvent* event)
00610 {
00611     QListView::paintEvent(event);
00612     if (d->dragging && !d->dropRect.isEmpty()) {
00613         // draw drop indicator
00614         QPainter painter(viewport());
00615 
00616         const QModelIndex index = indexAt(d->dropRect.topLeft());
00617         const QRect itemRect = visualRect(index);
00618         const bool drawInsertIndicator = !d->dropOnPlace ||
00619                                          d->dropRect.height() <= d->insertIndicatorHeight(itemRect.height());
00620 
00621         if (drawInsertIndicator) {
00622             // draw indicator for inserting items
00623             QBrush blendedBrush = viewOptions().palette.brush(QPalette::Normal, QPalette::Highlight);
00624             QColor color = blendedBrush.color();
00625 
00626             const int y = (d->dropRect.top() + d->dropRect.bottom()) / 2;
00627             const int thickness = d->dropRect.height() / 2;
00628             Q_ASSERT(thickness >= 1);
00629             int alpha = 255;
00630             const int alphaDec = alpha / (thickness + 1);
00631             for (int i = 0; i < thickness; i++) {
00632                 color.setAlpha(alpha);
00633                 alpha -= alphaDec;
00634                 painter.setPen(color);
00635                 painter.drawLine(d->dropRect.left(), y - i, d->dropRect.right(), y - i);
00636                 painter.drawLine(d->dropRect.left(), y + i, d->dropRect.right(), y + i);
00637             }
00638         } else {
00639             // draw indicator for copying/moving/linking to items
00640             QStyleOptionViewItemV4 opt;
00641             opt.initFrom(this);
00642             opt.rect = itemRect;
00643             opt.state = QStyle::State_Enabled | QStyle::State_MouseOver;
00644             style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, &painter, this);
00645         }
00646     }
00647 }
00648 
00649 void KFilePlacesView::setModel(QAbstractItemModel *model)
00650 {
00651     QListView::setModel(model);
00652     d->updateHiddenRows();
00653     connect(model, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
00654             this, SLOT(adaptItemSize()));
00655 }
00656 
00657 void KFilePlacesView::rowsInserted(const QModelIndex &parent, int start, int end)
00658 {
00659     QListView::rowsInserted(parent, start, end);
00660     setUrl(d->currentUrl);
00661 
00662     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(itemDelegate());
00663     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00664 
00665     for (int i=start; i<=end; ++i) {
00666         QModelIndex index = placesModel->index(i, 0, parent);
00667         if (d->showAll || !placesModel->isHidden(index)) {
00668             delegate->addAppearingItem(index);
00669         } else {
00670             setRowHidden(i, true);
00671         }
00672     }
00673 
00674     if (d->itemAppearTimeline.state()!=QTimeLine::Running) {
00675         delegate->setAppearingItemProgress(0.0);
00676         d->itemAppearTimeline.start();
00677     }
00678 
00679     d->adaptItemSize();
00680 }
00681 
00682 QSize KFilePlacesView::sizeHint() const
00683 {
00684     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(model());
00685     const int height = QListView::sizeHint().height();
00686     QFontMetrics fm = d->q->fontMetrics();
00687     int textWidth = 0;
00688 
00689     for (int i=0; i<placesModel->rowCount(); ++i) {
00690         QModelIndex index = placesModel->index(i, 0);
00691         if (!placesModel->isHidden(index))
00692            textWidth = qMax(textWidth,fm.width(index.data(Qt::DisplayRole).toString()));
00693     }
00694 
00695     const int iconSize = KIconLoader::global()->currentSize(KIconLoader::Dialog);
00696     return QSize(iconSize + textWidth + 2*KDialog::marginHint(), height);
00697 }
00698 
00699 void KFilePlacesView::Private::setCurrentIndex(const QModelIndex &index)
00700 {
00701     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00702 
00703     if (placesModel==0) return;
00704 
00705     KUrl url = placesModel->url(index);
00706 
00707     if (url.isValid()) {
00708         currentUrl = url;
00709         updateHiddenRows();
00710         emit q->urlChanged(url);
00711     } else {
00712         q->setUrl(currentUrl);
00713     }
00714 }
00715 
00716 void KFilePlacesView::Private::adaptItemSize()
00717 {
00718     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
00719     if (!delegate) return;
00720 
00721     if (!autoResizeItems) {
00722         int size = q->iconSize().width(); // Assume width == height
00723         delegate->setIconSize(size);
00724         q->scheduleDelayedItemsLayout();
00725         return;
00726     }
00727 
00728     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00729 
00730     if (placesModel==0) return;
00731 
00732     int rowCount = placesModel->rowCount();
00733 
00734     if (!showAll) {
00735         rowCount-= placesModel->hiddenCount();
00736 
00737         QModelIndex current = placesModel->closestItem(currentUrl);
00738 
00739         if (placesModel->isHidden(current)) {
00740             rowCount++;
00741         }
00742     }
00743 
00744     if (rowCount==0) return; // We've nothing to display anyway
00745 
00746     const int minSize = 16;
00747     const int maxSize = 64;
00748 
00749     int textWidth = 0;
00750     QFontMetrics fm = q->fontMetrics();
00751     for (int i=0; i<placesModel->rowCount(); ++i) {
00752         QModelIndex index = placesModel->index(i, 0);
00753 
00754         if (!placesModel->isHidden(index))
00755            textWidth = qMax(textWidth,fm.width(index.data(Qt::DisplayRole).toString()));
00756     }
00757 
00758     const int margin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, q) + 1;
00759     const int maxWidth = q->viewport()->width() - textWidth - 4 * margin - 1;
00760     const int maxHeight = ((q->height() - KDialog::marginHint() * rowCount) / rowCount) - 1;
00761 
00762     int size = qMin(maxHeight, maxWidth);
00763 
00764     if (size<minSize) {
00765         size = minSize;
00766     } else if (size>maxSize) {
00767         size = maxSize;
00768     } else {
00769         // Make it a multiple of 16
00770         size &= ~0xf;
00771     }
00772 
00773     if (size==delegate->iconSize()) return;
00774 
00775     if (smoothItemResizing) {
00776         oldSize = delegate->iconSize();
00777         endSize = size;
00778         if (adaptItemsTimeline.state()!=QTimeLine::Running) {
00779             adaptItemsTimeline.start();
00780         }
00781     } else {
00782         delegate->setIconSize(size);
00783         q->scheduleDelayedItemsLayout();
00784     }
00785 }
00786 
00787 void KFilePlacesView::Private::updateHiddenRows()
00788 {
00789     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00790 
00791     if (placesModel==0) return;
00792 
00793     int rowCount = placesModel->rowCount();
00794     QModelIndex current = placesModel->closestItem(currentUrl);
00795 
00796     for (int i=0; i<rowCount; ++i) {
00797         QModelIndex index = placesModel->index(i, 0);
00798         if (index!=current && placesModel->isHidden(index) && !showAll) {
00799             q->setRowHidden(i, true);
00800         } else {
00801             q->setRowHidden(i, false);
00802         }
00803     }
00804 
00805     adaptItemSize();
00806 }
00807 
00808 bool KFilePlacesView::Private::insertAbove(const QRect &itemRect, const QPoint &pos) const
00809 {
00810     if (dropOnPlace) {
00811         return pos.y() < itemRect.top() + insertIndicatorHeight(itemRect.height()) / 2;
00812     }
00813 
00814     return pos.y() < itemRect.top() + (itemRect.height() / 2);
00815 }
00816 
00817 bool KFilePlacesView::Private::insertBelow(const QRect &itemRect, const QPoint &pos) const
00818 {
00819     if (dropOnPlace) {
00820         return pos.y() > itemRect.bottom() - insertIndicatorHeight(itemRect.height()) / 2;
00821     }
00822 
00823     return pos.y() >= itemRect.top() + (itemRect.height() / 2);
00824 }
00825 
00826 int KFilePlacesView::Private::insertIndicatorHeight(int itemHeight) const
00827 {
00828     const int min = 4;
00829     const int max = 12;
00830 
00831     int height = itemHeight / 4;
00832     if (height < min) {
00833         height = min;
00834     } else if (height > max) {
00835         height = max;
00836     }
00837     return height;
00838 }
00839 
00840 void KFilePlacesView::Private::_k_placeClicked(const QModelIndex &index)
00841 {
00842     if (!KGlobalSettings::singleClick()) {
00843         // if double click is used, emulate a single click behavior
00844         _k_placeActivated(index);
00845     }
00846 }
00847 
00848 void KFilePlacesView::Private::_k_placeActivated(const QModelIndex &index)
00849 {
00850     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00851 
00852     if (placesModel==0) return;
00853 
00854     lastClickedIndex = QPersistentModelIndex();
00855 
00856     if (placesModel->setupNeeded(index)) {
00857         QObject::connect(placesModel, SIGNAL(setupDone(const QModelIndex &, bool)),
00858                          q, SLOT(_k_storageSetupDone(const QModelIndex &, bool)));
00859 
00860         lastClickedIndex = index;
00861         placesModel->requestSetup(index);
00862         return;
00863     }
00864 
00865     setCurrentIndex(index);
00866 }
00867 
00868 void KFilePlacesView::Private::_k_storageSetupDone(const QModelIndex &index, bool success)
00869 {
00870     if (index!=lastClickedIndex) {
00871         return;
00872     }
00873 
00874     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel*>(q->model());
00875 
00876     QObject::disconnect(placesModel, SIGNAL(setupDone(const QModelIndex &, bool)),
00877                         q, SLOT(_k_storageSetupDone(const QModelIndex &, bool)));
00878 
00879     if (success) {
00880         setCurrentIndex(lastClickedIndex);
00881     } else {
00882         q->setUrl(currentUrl);
00883     }
00884 
00885     lastClickedIndex = QPersistentModelIndex();
00886 }
00887 
00888 void KFilePlacesView::Private::_k_adaptItemsUpdate(qreal value)
00889 {
00890     int add = (endSize-oldSize)*value;
00891 
00892     int size = oldSize+add;
00893 
00894     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
00895     delegate->setIconSize(size);
00896     q->scheduleDelayedItemsLayout();
00897 }
00898 
00899 void KFilePlacesView::Private::_k_itemAppearUpdate(qreal value)
00900 {
00901     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
00902 
00903     delegate->setAppearingItemProgress(value);
00904     q->scheduleDelayedItemsLayout();
00905 }
00906 
00907 void KFilePlacesView::Private::_k_itemDisappearUpdate(qreal value)
00908 {
00909     KFilePlacesViewDelegate *delegate = dynamic_cast<KFilePlacesViewDelegate*>(q->itemDelegate());
00910 
00911     delegate->setDisappearingItemProgress(value);
00912 
00913     if (value>=1.0) {
00914         updateHiddenRows();
00915     }
00916 
00917     q->scheduleDelayedItemsLayout();
00918 }
00919 
00920 void KFilePlacesView::Private::_k_enableSmoothItemResizing()
00921 {
00922     smoothItemResizing = true;
00923 }
00924 
00925 void KFilePlacesView::Private::_k_trashUpdated(KJob *job)
00926 {
00927     if (job->error()) {
00928         static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
00929     }
00930     org::kde::KDirNotify::emitFilesAdded("trash:/");
00931 }
00932 
00933 void KFilePlacesView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
00934 {
00935     QListView::dataChanged(topLeft, bottomRight);
00936 }
00937 
00938 #include "kfileplacesview.moc"

KFile

Skip menu "KFile"
  • Main Page
  • 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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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