plasma: import folderview plugin from kde-baseapps

This commit is contained in:
Ivailo Monev 2015-07-25 17:51:40 +03:00
parent eac99cb4c4
commit 988ffd4fb4
48 changed files with 12648 additions and 0 deletions

View file

@ -1,6 +1,7 @@
add_subdirectory(homerun) add_subdirectory(homerun)
add_subdirectory(kickoff) add_subdirectory(kickoff)
add_subdirectory(trash) add_subdirectory(trash)
add_subdirectory(folderview)
#task and windowlist depend on libs/taskmanager #task and windowlist depend on libs/taskmanager
add_subdirectory(tasks) add_subdirectory(tasks)

View file

@ -0,0 +1,43 @@
project(plasma-folderview)
include_directories(${LIBKONQ_INCLUDE_DIR})
if(Q_WS_X11)
find_package(X11 REQUIRED)
endif(Q_WS_X11)
set(folderview_SRCS
folderview.cpp
abstractitemview.cpp
listview.cpp
dialog.cpp
dialogshadows.cpp
label.cpp
iconview.cpp
popupview.cpp
iconwidget.cpp
dirlister.cpp
proxymodel.cpp
folderviewadapter.cpp
previewpluginsmodel.cpp
tooltipwidget.cpp
style.cpp
itemeditor.cpp
animator.cpp
actionoverlay.cpp
asyncfiletester.cpp)
kde4_add_ui_files(folderview_SRCS
folderviewFilterConfig.ui
folderviewDisplayConfig.ui
folderviewLocationConfig.ui
folderviewPreviewConfig.ui)
kde4_add_plugin(plasma_applet_folderview ${folderview_SRCS})
target_link_libraries(plasma_applet_folderview ${KDE4_PLASMA_LIBS} ${LIBKONQ_LIBRARY}
${KDE4_KIO_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_SOLID_LIBS} ${X11_LIBRARIES})
install(TARGETS plasma_applet_folderview DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES plasma-applet-folderview.desktop DESTINATION ${SERVICES_INSTALL_DIR})

View file

@ -0,0 +1,2 @@
macro_bool_to_01(KDE4WORKSPACE_FOUND HAVE_KWORKSPACE)

View file

@ -0,0 +1,3 @@
#! /usr/bin/env bash
$EXTRACTRC *.ui >> rc.cpp
$XGETTEXT *.cpp -o $podir/plasma_applet_folderview.pot

View file

@ -0,0 +1,744 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
*
* The smooth scrolling code is based on the code in KHTMLView,
* Copyright © 2006-2008 Germain Garand <germain@ebooksfrance.org>
* Copyright © 2008 Allan Sandfeld Jensen <kde@carewolf.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "abstractitemview.h"
#include "proxymodel.h"
#include "style.h"
#include <QItemSelectionModel>
#include <QPaintEngine>
#include <KDirModel>
#include <KFileItemDelegate>
#include <KGlobalSettings>
#include <Plasma/PaintUtils>
#include <limits.h>
#ifdef Q_WS_X11
# include <QX11Info>
# include <X11/Xlib.h>
#endif
static const int sSmoothScrollTime = 140;
static const int sSmoothScrollTick = 14;
AbstractItemView::AbstractItemView(QGraphicsWidget *parent)
: QGraphicsWidget(parent),
m_itemFrame(0),
m_delegate(0),
m_lastScrollValue(0),
m_viewScrolled(false),
m_dx(0),
m_ddx(0),
m_dddx(0),
m_rdx(0),
m_dy(0),
m_ddy(0),
m_dddy(0),
m_rdy(0),
m_smoothScrolling(false),
m_autoScrollSpeed(0),
m_drawShadows(true)
{
m_scrollBar = new Plasma::ScrollBar(this);
connect(m_scrollBar, SIGNAL(valueChanged(int)), SLOT(scrollBarValueChanged(int)));
connect(m_scrollBar->nativeWidget(), SIGNAL(actionTriggered(int)), SLOT(scrollBarActionTriggered(int)));
connect(m_scrollBar->nativeWidget(), SIGNAL(sliderReleased()), SLOT(scrollBarSliderReleased()));
m_itemFrame = new Plasma::FrameSvg(this);
m_itemFrame->setImagePath("widgets/viewitem");
m_itemFrame->setCacheAllRenderedFrames(true);
m_itemFrame->setElementPrefix("normal");
connect(m_itemFrame, SIGNAL(repaintNeeded()), this, SLOT(svgChanged()));
// This is a dummy widget that's never shown - it's just passed to
// KFileItemDelegate in the style options, so it will use the widget's
// style to draw the view item backgrounds.
m_styleWidget = new QWidget;
m_style = new FolderViewStyle;
m_styleWidget->setStyle(m_style);
const int size = style()->pixelMetric(QStyle::PM_LargeIconSize);
m_iconSize = QSize(size, size);
}
AbstractItemView::~AbstractItemView()
{
delete m_styleWidget;
delete m_style;
}
void AbstractItemView::setModel(QAbstractItemModel *model)
{
m_model = static_cast<ProxyModel*>(model);
m_dirModel = static_cast<KDirModel*>(m_model->sourceModel());
connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int)));
connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(rowsRemoved(QModelIndex,int,int)));
connect(m_model, SIGNAL(modelReset()), SLOT(modelReset()));
connect(m_model, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(dataChanged(QModelIndex,QModelIndex)));
}
QAbstractItemModel *AbstractItemView::model() const
{
return m_model;
}
void AbstractItemView::setSelectionModel(QItemSelectionModel *model)
{
m_selectionModel = model;
}
QItemSelectionModel *AbstractItemView::selectionModel() const
{
return m_selectionModel;
}
void AbstractItemView::setItemDelegate(KFileItemDelegate *delegate)
{
m_delegate = static_cast<KFileItemDelegate*>(delegate);
connect(m_delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
connect(m_delegate, SIGNAL(commitData(QWidget*)), SLOT(commitData(QWidget*)));
}
KFileItemDelegate *AbstractItemView::itemDelegate() const
{
return m_delegate;
}
void AbstractItemView::setIconSize(const QSize &iconSize)
{
m_iconSize = iconSize;
}
QSize AbstractItemView::iconSize() const
{
return m_iconSize;
}
void AbstractItemView::setDrawShadows(bool on)
{
if (m_drawShadows != on) {
m_drawShadows = on;
markAreaDirty(visibleArea());
update();
}
}
bool AbstractItemView::drawShadows() const
{
return m_drawShadows;
}
QScrollBar *AbstractItemView::verticalScrollBar() const
{
return m_scrollBar->nativeWidget();
}
QRect AbstractItemView::visibleArea() const
{
return mapToViewport(contentsRect()).toAlignedRect();
}
// Marks the given rect in viewport coordinates, as dirty and schedules a repaint.
void AbstractItemView::markAreaDirty(const QRect &rect)
{
if (!rect.isEmpty() && rect.intersects(visibleArea())) {
m_dirtyRegion += rect;
update(mapFromViewport(rect));
}
}
// This function scrolls the contents of the backbuffer the distance the scrollbar
// has moved since the last time this function was called.
QRect AbstractItemView::scrollBackBuffer()
{
const int value = m_scrollBar->value();
const int delta = m_lastScrollValue - value;
m_lastScrollValue = value;
if (qAbs(delta) >= m_pixmap.height()) {
return visibleArea();
}
int sy, dy, h;
QRect dirty;
if (delta < 0) {
dy = 0;
sy = -delta;
h = m_pixmap.height() - sy;
dirty = QRect(0, m_pixmap.height() - sy, m_pixmap.width(), sy);
} else {
dy = delta;
sy = 0;
h = m_pixmap.height() - dy;
dirty = QRect(0, 0, m_pixmap.width(), dy);
}
#if defined(Q_WS_X11)
const QPaintEngine::Type type = m_pixmap.paintEngine()->type();
if (type == QPaintEngine::X11) {
Display *dpy = QX11Info::display();
GC gc = XCreateGC(dpy, m_pixmap.handle(), 0, 0);
XCopyArea(dpy, m_pixmap.handle(), m_pixmap.handle(), gc, 0, sy, m_pixmap.width(), h, 0, dy);
XFreeGC(dpy, gc);
} else if (type == QPaintEngine::Raster) {
// Hack to prevent the image from detaching
const QImage image = m_pixmap.toImage();
const uchar *src = image.scanLine(sy);
uchar *dst = const_cast<uchar*>(image.scanLine(dy));
memmove((void*)dst, (const void*)src, h * image.bytesPerLine());
} else
#endif
{
dirty = m_pixmap.rect();
}
return mapToViewport(dirty.translated(contentsRect().topLeft().toPoint())).toAlignedRect();
}
void AbstractItemView::prepareBackBuffer()
{
const QRect cr = contentsRect().toRect();
// Make sure the backbuffer pixmap has the same size as the content rect
if (m_pixmap.size() != cr.size()) {
QPixmap pixmap(cr.size());
pixmap.fill(Qt::transparent);
if (!m_pixmap.isNull()) {
// Static content optimization
#ifdef Q_WS_X11
if (m_pixmap.paintEngine()->type() == QPaintEngine::X11) {
GC gc = XCreateGC(QX11Info::display(), pixmap.handle(), 0, NULL);
XCopyArea(QX11Info::display(), m_pixmap.handle(), pixmap.handle(), gc, 0, 0,
m_pixmap.width(), m_pixmap.height(), 0, 0);
XFreeGC(QX11Info::display(), gc);
} else
#endif
{
QPainter p(&pixmap);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.drawPixmap(0, 0, m_pixmap);
}
QRegion region(pixmap.rect());
region -= m_pixmap.rect();
region.translate(0, m_scrollBar->value());
m_dirtyRegion |= region;
} else {
m_dirtyRegion = QRegion(visibleArea());
}
m_pixmap = pixmap;
}
if (m_viewScrolled) {
m_dirtyRegion += scrollBackBuffer();
m_viewScrolled = false;
}
}
// This function draws the backbuffer pixmap on the widget, and fades out the top
// and bottom if as needed.
void AbstractItemView::syncBackBuffer(QPainter *painter, const QRect &clipRect)
{
const QRect cr = contentsRect().toRect();
const int fadeHeight = 16;
const QRect topFadeRect(cr.x(), cr.y(), cr.width(), fadeHeight);
const QRect bottomFadeRect(cr.bottomLeft() - QPoint(0, fadeHeight), QSize(cr.width(), fadeHeight));
int scrollValue = m_scrollBar->value();
int maxValue = m_scrollBar->maximum();
// Draw the backbuffer on the widget
// =================================
if ((scrollValue > 0 && topFadeRect.intersects(clipRect)) ||
(scrollValue < maxValue && bottomFadeRect.intersects(clipRect)))
{
QPixmap pixmap = m_pixmap;
QPainter p(&pixmap);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
// Fade out the top section of the pixmap if the scrollbar slider isn't at the top
if (scrollValue > 0 && topFadeRect.intersects(clipRect))
{
if (m_topFadeTile.isNull())
{
m_topFadeTile = QPixmap(256, fadeHeight);
m_topFadeTile.fill(Qt::transparent);
QLinearGradient g(0, 0, 0, fadeHeight);
g.setColorAt(0, Qt::transparent);
g.setColorAt(1, Qt::black);
QPainter p(&m_topFadeTile);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(0, 0, 256, fadeHeight, g);
p.end();
}
p.drawTiledPixmap(0, 0, m_pixmap.width(), fadeHeight, m_topFadeTile);
}
// Fade out the bottom part of the pixmap if the scrollbar slider isn't at the bottom
if (scrollValue < maxValue && bottomFadeRect.intersects(clipRect))
{
if (m_topFadeTile.isNull())
{
m_bottomFadeTile = QPixmap(256, fadeHeight);
m_bottomFadeTile.fill(Qt::transparent);
QLinearGradient g(0, 0, 0, fadeHeight);
g.setColorAt(0, Qt::black);
g.setColorAt(1, Qt::transparent);
QPainter p(&m_bottomFadeTile);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(0, 0, 256, fadeHeight, g);
p.end();
}
p.drawTiledPixmap(0, m_pixmap.height() - fadeHeight, m_pixmap.width(), fadeHeight, m_bottomFadeTile);
}
p.end();
painter->drawPixmap(cr.topLeft(), pixmap);
}
else
{
painter->drawPixmap(cr.topLeft(), m_pixmap);
}
}
QSize AbstractItemView::doTextLayout(QTextLayout &layout, const QSize &constraints, Qt::Alignment alignment,
QTextOption::WrapMode wrapMode) const
{
QTextOption to;
to.setAlignment(alignment);
to.setTextDirection(layoutDirection());
to.setWrapMode(wrapMode);
layout.setTextOption(to);
QFontMetricsF fm = QFontMetricsF(layout.font());
QTextLine line;
qreal leading = fm.leading();
qreal widthUsed = 0;
qreal height = 0;
layout.beginLayout();
while ((line = layout.createLine()).isValid()) {
// Make the last line that will fit infinitely long.
// drawTextLayout() will handle this by fading the line out
// if it won't fit inside the constraints.
if (height + 2 * fm.lineSpacing() > constraints.height()) {
line.setLineWidth(INT_MAX);
if (line.naturalTextWidth() < constraints.width()) {
line.setLineWidth(constraints.width());
widthUsed = qMax(widthUsed, line.naturalTextWidth());
} else {
widthUsed = constraints.width();
}
} else {
line.setLineWidth(constraints.width());
widthUsed = qMax(widthUsed, line.naturalTextWidth());
}
line.setPosition(QPointF(0, height));
height += line.height() + leading;
}
layout.endLayout();
return QSize(widthUsed, height);
}
void AbstractItemView::drawTextLayout(QPainter *painter, const QTextLayout &layout, const QRect &rect) const
{
// Create the alpha gradient for the fade out effect
QLinearGradient alphaGradient(0, 0, 1, 0);
alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
if (layout.textOption().textDirection() == Qt::LeftToRight) {
alphaGradient.setColorAt(0, QColor(0, 0, 0, 255));
alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
} else {
alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
alphaGradient.setColorAt(1, QColor(0, 0, 0, 255));
}
QFontMetrics fm(layout.font());
QList<QRect> fadeRects;
QList<QRect> haloRects;
int fadeWidth = 30;
// Compute halo and fade rects
for (int i = 0; i < layout.lineCount(); i++) {
const QTextLine line = layout.lineAt(i);
const QRectF lr = line.naturalTextRect();
// Add a fade out rect to the list if the line is too long
if (lr.width() > rect.width()) {
int x = rect.width() - fadeWidth;
int y = lr.y();
QRect r = QStyle::visualRect(layout.textOption().textDirection(), QRect(QPoint(), rect.size()),
QRect(x, y, fadeWidth, int(lr.height())));
fadeRects.append(r);
}
haloRects.append((lr & rect.translated(-rect.topLeft())).toAlignedRect());
}
// Create a pixmap for the text
QPixmap pixmap(rect.size());
pixmap.fill(Qt::transparent);
QPainter p(&pixmap);
p.setPen(painter->pen());
int y = 0;
if (layout.textOption().alignment() & Qt::AlignVCenter) {
const int h = fm.height() * layout.lineCount();
if (h < pixmap.height()) {
y = (pixmap.height() - h) / 2;
}
}
p.translate(0, y);
// Draw each line in the layout
for (int i = 0; i < layout.lineCount(); i++)
{
const QTextLine line = layout.lineAt(i);
const QRectF tr = line.naturalTextRect();
if (tr.width() > rect.width()) {
if (layoutDirection() == Qt::LeftToRight) {
line.draw(&p, QPointF(-tr.x(), 0));
} else {
line.draw(&p, QPointF(rect.width() - tr.right(), 0));
}
} else {
line.draw(&p, QPointF());
}
}
// Reduce the alpha in each fade out rect using the alpha gradient
if (!fadeRects.isEmpty()) {
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
foreach (const QRect &rect, fadeRects) {
p.fillRect(rect, alphaGradient);
}
}
p.end();
if (drawShadows()) {
const QColor color = painter->pen().color();
if (qGray(color.rgb()) < 192) {
// Draw halos
painter->translate(0, y);
foreach (const QRect &haloRect, haloRects) {
Plasma::PaintUtils::drawHalo(painter, haloRect.translated(rect.topLeft()));
}
painter->translate(0, -y);
} else {
// Draw shadow
QImage shadow = pixmap.toImage();
Plasma::PaintUtils::shadowBlur(shadow, 2, Qt::black);
// Make the shadow twice as dark
quint32 * const pixels = reinterpret_cast<quint32*>(shadow.bits());
for (int i = 0; i < shadow.width() * shadow.height(); i++) {
pixels[i] = qMin(255, qAlpha(pixels[i]) * 2) << 24;
}
painter->drawImage(rect.topLeft() + QPoint(1, 1), shadow);
}
}
// Draw the text pixmap
painter->drawPixmap(rect.topLeft(), pixmap);
}
void AbstractItemView::rowsInserted(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent)
Q_UNUSED(first)
Q_UNUSED(last)
}
void AbstractItemView::rowsRemoved(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent)
Q_UNUSED(first)
Q_UNUSED(last)
}
void AbstractItemView::modelReset()
{
}
void AbstractItemView::layoutChanged()
{
}
void AbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
Q_UNUSED(topLeft)
Q_UNUSED(bottomRight)
}
void AbstractItemView::commitData(QWidget *editor)
{
Q_UNUSED(editor)
}
void AbstractItemView::closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
{
Q_UNUSED(editor)
Q_UNUSED(hint)
}
void AbstractItemView::svgChanged()
{
}
void AbstractItemView::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint)
{
Q_UNUSED(hint)
const QRectF r = mapFromViewport(visualRect(index));
if (r.top() < 0) {
smoothScroll(0, r.top());
} else if (r.bottom() > geometry().height()) {
smoothScroll(0, r.bottom() - geometry().height());
}
}
void AbstractItemView::autoScroll(ScrollDirection direction, int pixelsPerSecond)
{
m_scrollDirection = direction;
m_autoScrollSetSpeed = direction == ScrollUp ? -pixelsPerSecond : pixelsPerSecond;
if (!m_autoScrollTimer.isActive()) {
m_autoScrollSpeed = 1;
m_autoScrollTime.restart();
m_autoScrollTimer.start(1000 / 30, this);
}
}
void AbstractItemView::stopAutoScrolling()
{
m_autoScrollSetSpeed = 0;
m_autoScrollTimer.stop();
}
void AbstractItemView::scrollBarValueChanged(int value)
{
Q_UNUSED(value)
m_viewScrolled = true;
update();
}
void AbstractItemView::scrollBarActionTriggered(int action)
{
switch (action)
{
case QAbstractSlider::SliderSingleStepAdd:
case QAbstractSlider::SliderSingleStepSub:
case QAbstractSlider::SliderPageStepAdd:
case QAbstractSlider::SliderPageStepSub:
stopAutoScrolling();
smoothScroll(0, m_scrollBar->nativeWidget()->sliderPosition() - m_scrollBar->value());
break;
case QAbstractSlider::SliderToMinimum:
case QAbstractSlider::SliderToMaximum:
stopAutoScrolling();
// Use a delayed call since the value won't propagate until after this function returns
QMetaObject::invokeMethod(this, "finishedScrolling", Qt::QueuedConnection);
break;
}
}
void AbstractItemView::scrollBarSliderReleased()
{
finishedScrolling();
}
void AbstractItemView::finishedScrolling()
{
}
void AbstractItemView::timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_smoothScrollTimer.timerId()) {
scrollTick();
} else if (event->timerId() == m_autoScrollTimer.timerId()) {
int step = qRound(m_autoScrollTime.elapsed() * (m_autoScrollSpeed / 1000.));
m_autoScrollTime.restart();
if (m_scrollDirection == ScrollUp && m_scrollBar->value() > m_scrollBar->minimum()) {
m_scrollBar->setValue(qMax(m_scrollBar->minimum(), m_scrollBar->value() + step));
} else if (m_scrollDirection == ScrollDown && m_scrollBar->value() < m_scrollBar->maximum()) {
m_scrollBar->setValue(qMin(m_scrollBar->maximum(), m_scrollBar->value() + step));
} else {
m_autoScrollSetSpeed = 0;
m_autoScrollSpeed = 0;
}
if (m_autoScrollSetSpeed > m_autoScrollSpeed) {
int delta;
if (m_autoScrollSpeed >= 0) {
delta = qBound(2, m_autoScrollSpeed * 2, 30);
} else {
delta = qBound(2, qAbs(m_autoScrollSpeed) / 2, 30);
}
m_autoScrollSpeed = qMin(m_autoScrollSpeed + delta, m_autoScrollSetSpeed);
} else if (m_autoScrollSetSpeed < m_autoScrollSpeed) {
int delta;
if (m_autoScrollSpeed >= 0) {
delta = qBound(2, m_autoScrollSpeed / 2, 30);
} else {
delta = qBound(2, qAbs(m_autoScrollSpeed * 2), 30);
}
m_autoScrollSpeed = qMax(m_autoScrollSetSpeed, m_autoScrollSpeed - delta);
}
if (m_autoScrollSpeed == 0 && m_autoScrollSetSpeed == 0) {
m_autoScrollTimer.stop();
}
}
}
void AbstractItemView::startScrolling()
{
m_smoothScrolling = true;
m_smoothScrollTimer.start(sSmoothScrollTick, this);
}
void AbstractItemView::stopScrolling()
{
m_smoothScrollTimer.stop();
m_dx = m_dy = 0;
m_ddx = m_ddy = 0;
m_rdx = m_rdy = 0;
m_dddx = m_dddy = 0;
m_smoothScrolling = false;
finishedScrolling();
}
void AbstractItemView::smoothScroll(int dx, int dy)
{
// full scroll is remaining scroll plus new scroll
m_dx = m_dx + dx;
m_dy = m_dy + dy;
if (m_dx == 0 && m_dy == 0) return;
int steps = sSmoothScrollTime/sSmoothScrollTick;
// average step size (stored in 1/16 px/step)
m_ddx = (m_dx*16)/(steps+1);
m_ddy = (m_dy*16)/(steps+1);
if (qAbs(m_ddx) < 64 && qAbs(m_ddy) < 64) {
// Don't move slower than average 4px/step in minimum one direction
if (m_ddx > 0) m_ddx = qMax(m_ddx, 64);
if (m_ddy > 0) m_ddy = qMax(m_ddy, 64);
if (m_ddx < 0) m_ddx = qMin(m_ddx, -64);
if (m_ddy < 0) m_ddy = qMin(m_ddy, -64);
// This means fewer than normal steps
steps = qMax(m_ddx ? (m_dx*16)/m_ddx : 0, m_ddy ? (m_dy*16)/m_ddy : 0);
if (steps < 1) steps = 1;
m_ddx = (m_dx*16)/(steps+1);
m_ddy = (m_dy*16)/(steps+1);
}
// step size starts at double average speed and ends at 0
m_ddx *= 2;
m_ddy *= 2;
// deacceleration speed
m_dddx = (m_ddx+1)/steps;
m_dddy = (m_ddy+1)/steps;
if (!m_smoothScrolling) {
startScrolling();
scrollTick();
}
m_smoothScrollStopwatch.start();
}
void AbstractItemView::scrollTick() {
if (m_dx == 0 && m_dy == 0) {
stopScrolling();
return;
}
// step size + remaining partial step
int tddx = m_ddx + m_rdx;
int tddy = m_ddy + m_rdy;
// don't go under 1px/step
if (tddx > 0 && tddx < 16) tddx = 16;
if (tddy > 0 && tddy < 16) tddy = 16;
if (tddx < 0 && tddx > -16) tddx = -16;
if (tddy < 0 && tddy > -16) tddy = -16;
// full pixel steps to scroll in this step
int ddx = tddx / 16;
int ddy = tddy / 16;
// remaining partial step (this is especially needed for 1.x sized steps)
m_rdx = tddx % 16;
m_rdy = tddy % 16;
// limit step to requested scrolling distance
if (qAbs(ddx) > qAbs(m_dx)) ddx = m_dx;
if (qAbs(ddy) > qAbs(m_dy)) ddy = m_dy;
// Don't stop if deaccelerated too fast
if (!ddx) ddx = m_dx;
if (!ddy) ddy = m_dy;
// update remaining scroll
m_dx -= ddx;
m_dy -= ddy;
m_scrollBar->setValue(m_scrollBar->value() + ddy);
// only consider decelerating if we aren't too far behind schedule
if (m_smoothScrollStopwatch.elapsed() < 2 * sSmoothScrollTick) {
// update scrolling speed
int dddx = m_dddx;
int dddy = m_dddy;
// don't change direction
if (abs(dddx) > abs(m_ddx)) dddx = m_ddx;
if (abs(dddy) > abs(m_ddy)) dddy = m_ddy;
m_ddx -= dddx;
m_ddy -= dddy;
}
m_smoothScrollStopwatch.start();
}
#include "moc_abstractitemview.cpp"

View file

@ -0,0 +1,187 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef ABSTRACTITEMVIEW_H
#define ABSTRACTITEMVIEW_H
#include <QGraphicsWidget>
#include <QAbstractItemDelegate>
#include <QAbstractItemView>
#include <QPointer>
#include <QCache>
#include <QTextLayout>
#include <QTime>
#include <QBasicTimer>
#include <plasma/widgets/scrollbar.h>
#include <plasma/framesvg.h>
class KDirModel;
class KFileItemDelegate;
class QItemSelectionModel;
class ProxyModel;
class QScrollBar;
// The abstract base class for IconView and ListView
class AbstractItemView : public QGraphicsWidget
{
Q_OBJECT
Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
Q_PROPERTY(bool drawShadows READ drawShadows WRITE setDrawShadows)
public:
enum ScrollDirection { ScrollUp, ScrollDown };
AbstractItemView(QGraphicsWidget *parent = 0);
~AbstractItemView();
virtual void setModel(QAbstractItemModel *model);
QAbstractItemModel *model() const;
void setSelectionModel(QItemSelectionModel *model);
QItemSelectionModel *selectionModel() const;
void setItemDelegate(KFileItemDelegate *delegate);
KFileItemDelegate *itemDelegate() const;
virtual void setIconSize(const QSize &iconSize);
QSize iconSize() const;
void setDrawShadows(bool on);
bool drawShadows() const;
QScrollBar *verticalScrollBar() const;
QRect visibleArea() const;
virtual QModelIndex indexAt(const QPointF &point) const = 0;
virtual QRect visualRect(const QModelIndex &index) const = 0;
QPointF mapToViewport(const QPointF &point) const;
QRectF mapToViewport(const QRectF &rect) const;
QPointF mapFromViewport(const QPointF &point) const;
QRectF mapFromViewport(const QRectF &rect) const;
void markAreaDirty(const QRect &rect);
void markAreaDirty(const QRectF &rect) { markAreaDirty(rect.toAlignedRect()); }
void scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint = QAbstractItemView::EnsureVisible);
void autoScroll(ScrollDirection direction, int pixelsPerSecond);
void stopAutoScrolling();
signals:
void activated(const QModelIndex &index);
void entered(const QModelIndex &index);
void left(const QModelIndex &index);
void contextMenuRequest(QWidget *widget, const QPoint &screenPos);
protected:
QRect scrollBackBuffer();
void prepareBackBuffer();
void syncBackBuffer(QPainter *painter, const QRect &clipRect);
QSize doTextLayout(QTextLayout &layout, const QSize &constraints, Qt::Alignment alignment,
QTextOption::WrapMode wrapMode) const;
void drawTextLayout(QPainter *painter, const QTextLayout &layout, const QRect &rect) const;
void timerEvent(QTimerEvent *event);
void smoothScroll(int dx, int dy);
void startScrolling();
void stopScrolling();
void scrollTick();
protected slots:
virtual void rowsInserted(const QModelIndex &parent, int first, int last);
virtual void rowsRemoved(const QModelIndex &parent, int first, int last);
virtual void modelReset();
virtual void layoutChanged();
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
virtual void commitData(QWidget *editor);
virtual void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
virtual void finishedScrolling();
virtual void svgChanged();
private slots:
void scrollBarValueChanged(int value);
void scrollBarActionTriggered(int action);
void scrollBarSliderReleased();
protected:
Plasma::FrameSvg *m_itemFrame;
KFileItemDelegate *m_delegate;
QPointer<KDirModel> m_dirModel;
QPointer<ProxyModel> m_model;
QPointer<QItemSelectionModel> m_selectionModel;
QSize m_iconSize;
QRegion m_dirtyRegion;
QPixmap m_pixmap;
QPixmap m_topFadeTile;
QPixmap m_bottomFadeTile;
Plasma::ScrollBar *m_scrollBar;
QStyle *m_style;
QWidget *m_styleWidget;
int m_lastScrollValue;
bool m_viewScrolled;
// These variables are for the smooth scrolling code
int m_dx;
int m_ddx;
int m_dddx;
int m_rdx;
int m_dy;
int m_ddy;
int m_dddy;
int m_rdy;
bool m_smoothScrolling;
QBasicTimer m_smoothScrollTimer;
QBasicTimer m_autoScrollTimer;
QTime m_smoothScrollStopwatch;
QTime m_autoScrollTime;
ScrollDirection m_scrollDirection;
int m_autoScrollSpeed;
int m_autoScrollSetSpeed;
bool m_drawShadows;
};
inline QPointF AbstractItemView::mapToViewport(const QPointF &point) const
{
return point + QPointF(0, m_scrollBar->value());
}
inline QRectF AbstractItemView::mapToViewport(const QRectF &rect) const
{
return rect.translated(0, m_scrollBar->value());
}
inline QPointF AbstractItemView::mapFromViewport(const QPointF &point) const
{
return point - QPointF(0, m_scrollBar->value());
}
inline QRectF AbstractItemView::mapFromViewport(const QRectF &rect) const
{
return rect.translated(0, -m_scrollBar->value());
}
#endif // ABSTRACTITEMVIEW_H

View file

@ -0,0 +1,321 @@
/*
* Copyright © 2009, 2010 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2009 Bruno Bigras <bigras.bruno@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "actionoverlay.h"
#include "asyncfiletester.h"
#include "iconview.h"
#include <Plasma/PaintUtils>
#include <Plasma/Animator>
#include <Plasma/Svg>
#include <QPainter>
#include <QGraphicsGridLayout>
ActionIcon::ActionIcon(QGraphicsItem* parent)
: QGraphicsWidget(parent),
m_pressed(false),
m_sunken(false)
{
setAcceptHoverEvents(true);
setCacheMode(DeviceCoordinateCache);
m_icon = new Plasma::Svg(this);
m_icon->setImagePath("widgets/action-overlays");
m_icon->setContainsMultipleImages(true);
setMinimumSize(m_icon->elementSize("add-normal"));
setMaximumSize(minimumSize());
show();
}
void ActionIcon::setElement(const QString &element)
{
m_element = element;
}
void ActionIcon::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
QString element = m_element;
if (m_sunken) {
element += "-pressed";
} else if (isUnderMouse()) {
element += "-hover";
} else {
element += "-normal";
}
m_icon->paint(painter, rect(), element);
}
void ActionIcon::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
Q_UNUSED(event)
m_pressed = true;
m_sunken = true;
update();
}
void ActionIcon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event)
m_pressed = false;
m_sunken = false;
if (isUnderMouse()) {
emit clicked();
}
update();
}
void ActionIcon::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event)
if (m_sunken != isUnderMouse()) {
m_sunken = isUnderMouse();
update();
}
}
void ActionIcon::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event)
emit iconHoverEnter();
update();
}
void ActionIcon::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event)
emit iconHoverLeave();
update();
}
// --------------------------------------------------------
ActionOverlay::ActionOverlay(AbstractItemView* parent)
: QGraphicsWidget(parent)
{
m_toggleButton = new ActionIcon(this);
m_openButton = new ActionIcon(this);
m_openButton->setElement("open");
m_showFolderButton = true;
m_showSelectionButton = true;
m_layout = new QGraphicsGridLayout(this);
m_layout->setContentsMargins(4, 4, 4, 4);
m_layout->setSpacing(1);
m_layout->addItem(m_toggleButton, 0, 0);
m_layout->addItem(m_openButton, 1, 0);
connect(parentWidget(), SIGNAL(entered(QModelIndex)), this, SLOT(entered(QModelIndex)));
connect(parentWidget(), SIGNAL(left(QModelIndex)), this, SLOT(left(QModelIndex)));
connect(parentWidget(), SIGNAL(modelChanged()), this, SLOT(modelChanged()));
connect(m_toggleButton, SIGNAL(clicked()), this, SLOT(toggleSelection()));
connect(m_openButton, SIGNAL(clicked()), this, SLOT(openPopup()));
m_hideActionOverlayIconTimer = new QTimer(this);
connect(m_hideActionOverlayIconTimer, SIGNAL(timeout()), this, SLOT(timeout()));
connect(m_toggleButton, SIGNAL(iconHoverEnter()), m_hideActionOverlayIconTimer, SLOT(stop()));
connect(m_toggleButton, SIGNAL(iconHoverLeave()), m_hideActionOverlayIconTimer, SLOT(start()));
connect(m_openButton, SIGNAL(iconHoverEnter()), m_hideActionOverlayIconTimer, SLOT(stop()));
connect(m_openButton, SIGNAL(iconHoverLeave()), m_hideActionOverlayIconTimer, SLOT(start()));
connect(parent->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(close()));
m_hideActionOverlayIconTimer->setInterval(500);
m_hideActionOverlayIconTimer->setSingleShot(true);
fadeIn = Plasma::Animator::create(Plasma::Animator::FadeAnimation, this);
fadeIn->setProperty("startOpacity", 0);
fadeIn->setProperty("targetOpacity", 1);
fadeIn->setTargetWidget(this);
fadeOut = Plasma::Animator::create(Plasma::Animator::FadeAnimation, this);
fadeOut->setProperty("startOpacity", 1);
fadeOut->setProperty("targetOpacity", 0);
fadeOut->setTargetWidget(this);
connect(fadeOut, SIGNAL(finished()), SLOT(close()));
hide();
}
void ActionOverlay::toggleSelection()
{
AbstractItemView *view = static_cast<AbstractItemView*>(parentWidget());
QItemSelectionModel *m_selectionModel = view->selectionModel();
if (m_hoverIndex.isValid()) {
const QModelIndex oldCurrent = m_selectionModel->currentIndex();
m_selectionModel->select(m_hoverIndex, QItemSelectionModel::Toggle);
m_selectionModel->setCurrentIndex(m_hoverIndex, QItemSelectionModel::NoUpdate);
m_toggleButton->setElement(m_selectionModel->isSelected(m_hoverIndex) ? "remove" : "add");
view->markAreaDirty(view->visualRect(m_hoverIndex));
if (oldCurrent.isValid() && oldCurrent != m_hoverIndex) {
view->markAreaDirty(view->visualRect(oldCurrent));
}
}
}
void ActionOverlay::openPopup()
{
if (IconView *view = qobject_cast<IconView*>(parentWidget())) {
view->openPopup(m_hoverIndex);
}
}
QPersistentModelIndex ActionOverlay::hoverIndex()
{
return m_hoverIndex;
}
void ActionOverlay::entered(const QModelIndex &index)
{
m_hideActionOverlayIconTimer->stop();
if (index.isValid()) {
AbstractItemView *view = static_cast<AbstractItemView*>(parentWidget());
QItemSelectionModel *m_selectionModel = view->selectionModel();
m_toggleButton->setElement(m_selectionModel->isSelected(index) ? "remove" : "add");
setPos(view->mapFromViewport(view->visualRect(index)).topLeft());
show();
if (m_hoverIndex != index) {
m_toggleButton->update();
fadeOut->stop();
fadeIn->start();
}
m_hoverIndex = index;
IconView *iview = qobject_cast<IconView*>(view);
if (iview && iview->clickToViewFolders()) {
AsyncFileTester::checkIfFolder(index, this, "checkIfFolderResult");
}
}
}
void ActionOverlay::checkIfFolderResult(const QModelIndex &index, bool isFolder)
{
if (index == m_hoverIndex) {
m_openButton->setVisible(isFolder);
}
}
void ActionOverlay::left(const QModelIndex &index)
{
Q_UNUSED(index);
if (!m_hideActionOverlayIconTimer->isActive()) {
m_hideActionOverlayIconTimer->start();
}
}
void ActionOverlay::timeout()
{
// allow the animation to restart after hiding the ActionOverlayIcon even if m_hoverIndex didn't change
m_hoverIndex = QPersistentModelIndex();
if (isVisible() && (fadeOut->state() != QAbstractAnimation::Running)) {
fadeIn->stop();
fadeOut->start();
}
}
void ActionOverlay::forceHide(HideHint hint)
{
m_hideActionOverlayIconTimer->stop();
if (hint == FadeOut) {
timeout();
} else {
hide();
}
}
void ActionOverlay::rowsRemoved(const QModelIndex & parent, int start, int end)
{
Q_UNUSED(parent);
Q_UNUSED(start);
Q_UNUSED(end);
if (!m_hoverIndex.isValid()) {
hide();
}
}
void ActionOverlay::modelChanged()
{
AbstractItemView *view = static_cast<AbstractItemView*>(parentWidget());
QAbstractItemModel *mod = view->model();
connect(mod, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(rowsRemoved(QModelIndex,int,int)));
}
void ActionOverlay::setShowFolderButton(bool show)
{
if (m_showFolderButton != show) {
m_showFolderButton = show;
toggleShowActionButton(show, m_openButton, 1);
}
}
void ActionOverlay::setShowSelectionButton(bool show)
{
if (m_showSelectionButton!= show) {
m_showSelectionButton = show;
toggleShowActionButton(show, m_toggleButton, 0);
}
}
bool ActionOverlay::showFolderButton() const
{
return m_showFolderButton;
}
bool ActionOverlay::showSelectionButton() const
{
return m_showSelectionButton;
}
QSizeF ActionOverlay::iconSize() const
{
return m_openButton->geometry().size();
}
void ActionOverlay::toggleShowActionButton(bool show, ActionIcon* button, unsigned int pos)
{
if (show && m_layout->itemAt(pos, 0) != button) {
m_layout->addItem(button, pos, 0);
button->show();
} else if (m_layout->itemAt(pos, 0) == button) {
button->hide();
m_layout->removeItem(button);
}
}

View file

@ -0,0 +1,108 @@
/*
* Copyright © 2009, 2010 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2009 Bruno Bigras <bigras.bruno@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef ACTIONOVERLAY_H
#define ACTIONOVERLAY_H
#include "abstractitemview.h"
#include <Plasma/Animation>
#include <QTimer>
#include <QGraphicsWidget>
#include <QPersistentModelIndex>
#include <QGraphicsGridLayout>
namespace Plasma {
class Svg;
}
class ActionIcon : public QGraphicsWidget
{
Q_OBJECT
public:
ActionIcon(QGraphicsItem* parent = 0);
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
void setElement(const QString &element);
signals:
void clicked();
void iconHoverEnter();
void iconHoverLeave();
private:
Plasma::Svg *m_icon;
QString m_element;
bool m_pressed;
bool m_sunken;
};
// -----------------------------------------------------------------------
class ActionOverlay : public QGraphicsWidget
{
Q_OBJECT
public:
enum HideHint { HideNow, FadeOut };
ActionOverlay(AbstractItemView *parent = 0);
QPersistentModelIndex hoverIndex();
void forceHide(HideHint hint);
void setShowFolderButton(bool show);
void setShowSelectionButton(bool show);
bool showFolderButton() const;
bool showSelectionButton() const;
QSizeF iconSize() const;
private slots:
void toggleSelection();
void openPopup();
void entered(const QModelIndex &index);
void left(const QModelIndex &index);
void timeout();
void modelChanged();
void rowsRemoved(const QModelIndex& indexes, int start, int end);
void checkIfFolderResult(const QModelIndex &index, bool isFolder);
void toggleShowActionButton(bool show, ActionIcon *button, unsigned int pos);
private:
ActionIcon *m_toggleButton;
ActionIcon *m_openButton;
QPersistentModelIndex m_hoverIndex;
QTimer *m_hideActionOverlayIconTimer;
Plasma::Animation *fadeIn;
Plasma::Animation *fadeOut;
bool m_showFolderButton;
bool m_showSelectionButton;
QGraphicsGridLayout * m_layout;
};
#endif // ACTIONOVERLAY_H

View file

@ -0,0 +1,139 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "animator.h"
#include "abstractitemview.h"
HoverAnimation::HoverAnimation(AbstractItemView *view, const QModelIndex &index)
: QAbstractAnimation(view), m_index(index), m_curve(QEasingCurve::InQuad)
{
}
void HoverAnimation::setEasingCurve(QEasingCurve::Type type)
{
m_curve.setType(type);
}
qreal HoverAnimation::progress() const
{
return m_curve.valueForProgress(m_progress);
}
void HoverAnimation::updateCurrentTime(int currentTime)
{
m_progress = qreal(currentTime) / duration();
AbstractItemView *view = static_cast<AbstractItemView*>(parent());
view->markAreaDirty(view->visualRect(m_index));
}
// --------------------------------------------------------
Animator::Animator(AbstractItemView *view)
: QObject(view)
{
m_effectsOn = (KGlobalSettings::graphicEffectsLevel() >= KGlobalSettings::SimpleAnimationEffects); //do not animate if the graphics effects are set to Low CPU
connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), SLOT(graphicsEffectsToggled(int)));
connect(view, SIGNAL(entered(QModelIndex)), SLOT(entered(QModelIndex)));
connect(view, SIGNAL(left(QModelIndex)), SLOT(left(QModelIndex)));
}
Animator::~Animator()
{
}
HoverAnimation *Animator::findHoverAnimation(const QModelIndex &index) const
{
foreach (HoverAnimation *animation, m_list) {
if (animation->index() == index) {
return animation;
}
}
return 0;
}
void Animator::animate(Type type, const QModelIndex &index)
{
AbstractItemView *view = static_cast<AbstractItemView*>(parent());
HoverAnimation *animation = findHoverAnimation(index);
if (!animation) {
animation = new HoverAnimation(view, index);
connect(animation, SIGNAL(destroyed(QObject*)), SLOT(animationDestroyed(QObject*)));
m_list.append(animation);
}
if (type == HoverEnter) {
animation->setDirection(QAbstractAnimation::Forward);
} else {
animation->setDirection(QAbstractAnimation::Backward);
}
if (animation->state() != QAbstractAnimation::Running) {
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
}
qreal Animator::hoverProgress(const QModelIndex &index) const
{
if (HoverAnimation *animation = findHoverAnimation(index)) {
return animation->progress();
}
return (index == m_hoveredIndex) ? 1.0 : 0.0;
}
void Animator::animationDestroyed(QObject *obj)
{
m_list.removeOne(static_cast<HoverAnimation*>(obj));
}
void Animator::entered(const QModelIndex &index)
{
m_hoveredIndex = index;
if (m_effectsOn) {
animate(HoverEnter, index);
}
}
void Animator::left(const QModelIndex &index)
{
m_hoveredIndex = QModelIndex();
if (m_effectsOn) {
animate(HoverLeave, index);
}
}
void Animator::graphicsEffectsToggled(int category)
{
if ( (category == KGlobalSettings::SETTINGS_STYLE) && (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ) {
m_effectsOn = true;
} else {
m_effectsOn = false;
}
}
#include "moc_animator.cpp"

View file

@ -0,0 +1,82 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef ANIMATOR_H
#define ANIMATOR_H
#include <QAbstractAnimation>
#include <QEasingCurve>
#include <QModelIndex>
#include <kglobalsettings.h>
class AbstractItemView;
class HoverAnimation : public QAbstractAnimation
{
public:
HoverAnimation(AbstractItemView *view, const QModelIndex &index);
QModelIndex index() const { return m_index; }
qreal progress() const;
void setEasingCurve(QEasingCurve::Type type);
int duration() const { return 250; }
protected:
void updateCurrentTime(int currentTime);
private:
QModelIndex m_index;
QEasingCurve m_curve;
qreal m_progress;
};
// -----------------------------------------------------------------------
class Animator : public QObject
{
Q_OBJECT
public:
enum Type { HoverEnter, HoverLeave };
Animator(AbstractItemView *view);
~Animator();
HoverAnimation *findHoverAnimation(const QModelIndex &index) const;
void animate(Type type, const QModelIndex &index);
qreal hoverProgress(const QModelIndex &index) const;
private slots:
void entered(const QModelIndex &index);
void left(const QModelIndex &index);
void animationDestroyed(QObject *object);
void graphicsEffectsToggled(int category);
private:
QList<HoverAnimation*> m_list;
QPersistentModelIndex m_hoveredIndex;
bool m_effectsOn;
};
#endif

View file

@ -0,0 +1,95 @@
/*
* Copyright © 2010 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "asyncfiletester.h"
#include "proxymodel.h"
#include <KDesktopFile>
#include <KFileItem>
#include <KProtocolInfo>
#include <KUrl>
#include <KIO/StatJob>
#include <KIO/Scheduler>
AsyncFileTester::AsyncFileTester(const QModelIndex &index, QObject *object, const char *member)
: index(index), object(object), member(member)
{
}
void AsyncFileTester::checkIfFolder(const QModelIndex &index, QObject *object, const char *method)
{
if (!index.isValid()) {
callResultMethod(object, method, index, false);
return;
}
KFileItem item = static_cast<const ProxyModel*>(index.model())->itemForIndex(index);
KUrl url = item.targetUrl();
if (item.isDir()) {
callResultMethod(object, method, index, true);
return;
}
if (item.isDesktopFile()) {
// Check if the desktop file is a link to a local folder
KDesktopFile file(url.path());
if (file.readType() == "Link") {
url = file.readUrl();
if (url.isLocalFile()) {
KFileItem destItem(KFileItem::Unknown, KFileItem::Unknown, url);
callResultMethod(object, method, index, destItem.isDir());
return;
}
if (KProtocolInfo::protocolClass(url.protocol()) == QString(":local")) {
AsyncFileTester *tester = new AsyncFileTester(index, object, method);
tester->delayedFolderCheck(url);
return;
}
}
}
callResultMethod(object, method, index, false);
}
void AsyncFileTester::delayedFolderCheck(const KUrl &url)
{
KIO::StatJob *job = KIO::stat(url, KIO::HideProgressInfo);
job->setSide(KIO::StatJob::SourceSide); // We will only read the file
connect(job, SIGNAL(result(KJob*)), SLOT(statResult(KJob*)));
}
void AsyncFileTester::callResultMethod(QObject *object, const char *member, const QModelIndex &index, bool result)
{
QMetaObject::invokeMethod(object, member, Q_ARG(QModelIndex, index),
Q_ARG(bool, result));
}
void AsyncFileTester::statResult(KJob *job)
{
if (object && !job->error()) {
KIO::StatJob *statJob = static_cast<KIO::StatJob*>(job);
callResultMethod(object.data(), member, index, statJob->statResult().isDir());
}
deleteLater();
}
#include "moc_asyncfiletester.cpp"

View file

@ -0,0 +1,62 @@
/*
* Copyright © 2010 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef ASYNCFILETESTER_H
#define ASYNCFILETESTER_H
#include <QObject>
#include <QModelIndex>
#include <QWeakPointer>
class KJob;
class KUrl;
class AsyncFileTester : public QObject
{
Q_OBJECT
public:
/* Checks if the file the index refers to is a folder and calls the given member in
* the object with the result.
*
* The index must belong to a ProxyModel, and the member function must be a slot
* with the following signature:
*
* checkIfFolderResult(const QModelIndex &index, bool result)
*/
static void checkIfFolder(const QModelIndex &index, QObject *object, const char *method);
private:
AsyncFileTester(const QModelIndex &index, QObject *object, const char *member);
void delayedFolderCheck(const KUrl &url);
static void callResultMethod(QObject *object, const char *member, const QModelIndex &index, bool result);
private slots:
void statResult(KJob *job);
private:
QModelIndex index;
QWeakPointer<QObject> object;
const char *member;
};
#endif

View file

@ -0,0 +1,183 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "dialog.h"
#include "dialogshadows_p.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QGraphicsView>
#include <QGraphicsWidget>
#include <QGraphicsScene>
#include <KWindowSystem>
#include <Plasma/Applet>
#include <Plasma/FrameSvg>
#include <Plasma/WindowEffects>
#ifdef Q_WS_X11
# include <QX11Info>
# include <X11/Xlib.h>
#endif
Dialog::Dialog(QWidget *parent)
: QWidget(parent, Qt::Popup), m_widget(0)
{
setAttribute(Qt::WA_TranslucentBackground);
#ifdef Q_WS_X11
setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu);
if (KWindowSystem::compositingActive()) {
setAttribute(Qt::WA_NoSystemBackground, false);
Plasma::WindowEffects::overrideShadow(winId(), true);
} else {
setAttribute(Qt::WA_NoSystemBackground);
}
#endif
KWindowSystem::setState(effectiveWinId(), NET::SkipTaskbar | NET::SkipPager);
QPalette pal = palette();
pal.setColor(backgroundRole(), Qt::transparent);
setPalette(pal);
m_background = new Plasma::FrameSvg(this);
m_background->setImagePath("dialogs/background");
m_scene = new QGraphicsScene(this);
m_view = new QGraphicsView(m_scene, this);
m_view->setFrameShape(QFrame::NoFrame);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->viewport()->setAutoFillBackground(false);
}
Dialog::~Dialog()
{
}
void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
{
m_widget = widget;
m_scene->addItem(widget);
}
void Dialog::show(Plasma::Applet *applet)
{
Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders;
m_background->setEnabledBorders(borders);
int left = m_background->marginSize(Plasma::LeftMargin);
int top = m_background->marginSize(Plasma::TopMargin);
int right = m_background->marginSize(Plasma::RightMargin);
int bottom = m_background->marginSize(Plasma::BottomMargin);
switch (applet->location())
{
case Plasma::BottomEdge:
borders &= ~Plasma::FrameSvg::BottomBorder;
bottom = qMin(bottom, 2);
break;
case Plasma::TopEdge:
borders &= ~Plasma::FrameSvg::TopBorder;
top = qMin(top, 2);
break;
case Plasma::LeftEdge:
borders &= ~Plasma::FrameSvg::LeftBorder;
left = qMin(left, 2);
break;
case Plasma::RightEdge:
borders &= ~Plasma::FrameSvg::RightBorder;
right = qMin(right, 2);
break;
default:
break;
}
const QSize margin(left + right, top + bottom);
QSize size = m_widget->preferredSize().toSize() + margin;
QPoint pos = applet->popupPosition(size);
const QRect availableGeometry = QApplication::desktop()->availableGeometry(pos);
if (pos.y() < 0) {
size.rheight() += pos.y();
pos.ry() = 0;
} else if (applet->location() == Plasma::TopEdge &&
pos.y() + size.height() > availableGeometry.bottom()) {
size.rheight() -= pos.y() + size.height() - availableGeometry.bottom();
}
if (pos.x() < 0) {
size.rwidth() += pos.x();
pos.rx() = 0;
} else if (applet->location() == Plasma::LeftEdge &&
pos.x() + size.width() > availableGeometry.right()) {
size.rwidth() -= pos.x() + size.width() - availableGeometry.right();
}
m_background->setEnabledBorders(borders);
setContentsMargins(left, top, right, bottom);
m_widget->resize(size - margin);
resize(size);
move(pos);
QWidget::show();
DialogShadows::self()->addWindow(this, borders);
}
void Dialog::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event)
m_background->resizeFrame(rect().size());
m_view->setGeometry(contentsRect());
if (KWindowSystem::compositingActive()) {
Plasma::WindowEffects::enableBlurBehind(winId(), true, m_background->mask());
} else {
setMask(m_background->mask());
}
}
void Dialog::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
m_background->paintFrame(&p);
}
void Dialog::mousePressEvent(QMouseEvent *event)
{
if (!rect().contains(event->pos())) {
hide();
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef DIALOG_H
#define DIALOG_H
#include <QWidget>
namespace Plasma {
class Applet;
class FrameSvg;
}
class QGraphicsView;
class QGraphicsWidget;
class QGraphicsScene;
class Dialog : public QWidget
{
public:
Dialog(QWidget *parent = 0);
~Dialog();
void setGraphicsWidget(QGraphicsWidget *widget);
void show(Plasma::Applet *applet);
protected:
void mousePressEvent(QMouseEvent *event);
void resizeEvent(QResizeEvent *event);
void paintEvent(QPaintEvent *event);
private:
Plasma::FrameSvg *m_background;
QGraphicsScene *m_scene;
QGraphicsView *m_view;
QGraphicsWidget *m_widget;
};
#endif

View file

@ -0,0 +1,385 @@
/*
* Copyright 2011 by Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "dialogshadows_p.h"
#include <QWidget>
#include <QPainter>
#ifdef Q_WS_X11
#include <QX11Info>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <fixx11h.h>
#endif
#include <kdebug.h>
#include <kglobal.h>
class DialogShadows::Private
{
public:
Private(DialogShadows *shadows)
: q(shadows),
m_managePixmaps(false)
{
}
~Private()
{
clearPixmaps();
}
void clearPixmaps();
void setupPixmaps();
void initPixmap(const QString &element);
QPixmap initEmptyPixmap(const QSize &size);
void updateShadow(const QWidget *window, Plasma::FrameSvg::EnabledBorders);
void clearShadow(const QWidget *window);
void updateShadows();
void windowDestroyed(QObject *deletedObject);
void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders);
DialogShadows *q;
QList<QPixmap> m_shadowPixmaps;
QPixmap m_emptyCornerPix;
QPixmap m_emptyCornerLeftPix;
QPixmap m_emptyCornerTopPix;
QPixmap m_emptyCornerRightPix;
QPixmap m_emptyCornerBottomPix;
QPixmap m_emptyVerticalPix;
QPixmap m_emptyHorizontalPix;
QHash<Plasma::FrameSvg::EnabledBorders, QVector<unsigned long> > data;
QHash<const QWidget *, Plasma::FrameSvg::EnabledBorders> m_windows;
bool m_managePixmaps;
};
class DialogShadowsSingleton
{
public:
DialogShadowsSingleton()
{
}
DialogShadows self;
};
K_GLOBAL_STATIC(DialogShadowsSingleton, privateDialogShadowsSelf)
DialogShadows::DialogShadows(QObject *parent, const QString &prefix)
: Plasma::Svg(parent),
d(new Private(this))
{
setImagePath(prefix);
connect(this, SIGNAL(repaintNeeded()), this, SLOT(updateShadows()));
}
DialogShadows *DialogShadows::self()
{
return &privateDialogShadowsSelf->self;
}
void DialogShadows::addWindow(const QWidget *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
{
if (!window || !window->isWindow()) {
return;
}
d->m_windows[window] = enabledBorders;
d->updateShadow(window, enabledBorders);
connect(window, SIGNAL(destroyed(QObject*)),
this, SLOT(windowDestroyed(QObject*)), Qt::UniqueConnection);
}
void DialogShadows::removeWindow(const QWidget *window)
{
if (!d->m_windows.contains(window)) {
return;
}
d->m_windows.remove(window);
disconnect(window, 0, this, 0);
d->clearShadow(window);
if (d->m_windows.isEmpty()) {
d->clearPixmaps();
}
}
void DialogShadows::Private::windowDestroyed(QObject *deletedObject)
{
m_windows.remove(static_cast<QWidget *>(deletedObject));
if (m_windows.isEmpty()) {
clearPixmaps();
}
}
void DialogShadows::Private::updateShadows()
{
setupPixmaps();
QHash<const QWidget *, Plasma::FrameSvg::EnabledBorders>::const_iterator i;
for (i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) {
updateShadow(i.key(), i.value());
}
}
void DialogShadows::Private::initPixmap(const QString &element)
{
#ifdef Q_WS_X11
QPixmap pix = q->pixmap(element);
if (!pix.isNull() && pix.handle() == 0) {
Pixmap xPix = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), pix.width(), pix.height(), 32);
QPixmap tempPix = QPixmap::fromX11Pixmap(xPix, QPixmap::ExplicitlyShared);
tempPix.fill(Qt::transparent);
QPainter p(&tempPix);
p.drawPixmap(QPoint(0, 0), pix);
m_shadowPixmaps << tempPix;
m_managePixmaps = true;
} else {
m_shadowPixmaps << pix;
}
#endif
}
QPixmap DialogShadows::Private::initEmptyPixmap(const QSize &size)
{
#ifdef Q_WS_X11
Pixmap emptyXPix = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), size.width(), size.height(), 32);
QPixmap tempEmptyPix = QPixmap::fromX11Pixmap(emptyXPix, QPixmap::ExplicitlyShared);
#else
QPixmap tempEmptyPix(size.width(), size.height());
#endif
tempEmptyPix.fill(Qt::transparent);
return tempEmptyPix;
}
void DialogShadows::Private::setupPixmaps()
{
clearPixmaps();
initPixmap("shadow-top");
initPixmap("shadow-topright");
initPixmap("shadow-right");
initPixmap("shadow-bottomright");
initPixmap("shadow-bottom");
initPixmap("shadow-bottomleft");
initPixmap("shadow-left");
initPixmap("shadow-topleft");
m_emptyCornerPix = initEmptyPixmap(QSize(1,1));
m_emptyCornerLeftPix = initEmptyPixmap(QSize(q->elementSize("shadow-topleft").width(), 1));
m_emptyCornerTopPix = initEmptyPixmap(QSize(1, q->elementSize("shadow-topleft").height()));
m_emptyCornerRightPix = initEmptyPixmap(QSize(q->elementSize("shadow-bottomright").width(), 1));
m_emptyCornerBottomPix = initEmptyPixmap(QSize(1, q->elementSize("shadow-bottomright").height()));
m_emptyVerticalPix = initEmptyPixmap(QSize(1, q->elementSize("shadow-left").height()));
m_emptyHorizontalPix = initEmptyPixmap(QSize(q->elementSize("shadow-top").width(), 1));
}
void DialogShadows::Private::setupData(Plasma::FrameSvg::EnabledBorders enabledBorders)
{
#ifdef Q_WS_X11
//shadow-top
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
data[enabledBorders] << m_shadowPixmaps[0].handle();
} else {
data[enabledBorders] << m_emptyHorizontalPix.handle();
}
//shadow-topright
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << m_shadowPixmaps[1].handle();
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
data[enabledBorders] << m_emptyCornerTopPix.handle();
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << m_emptyCornerRightPix.handle();
} else {
data[enabledBorders] << m_emptyCornerPix.handle();
}
//shadow-right
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << m_shadowPixmaps[2].handle();
} else {
data[enabledBorders] << m_emptyVerticalPix.handle();
}
//shadow-bottomright
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << m_shadowPixmaps[3].handle();
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
data[enabledBorders] << m_emptyCornerBottomPix.handle();
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << m_emptyCornerRightPix.handle();
} else {
data[enabledBorders] << m_emptyCornerPix.handle();
}
//shadow-bottom
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
data[enabledBorders] << m_shadowPixmaps[4].handle();
} else {
data[enabledBorders] << m_emptyHorizontalPix.handle();
}
//shadow-bottomleft
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << m_shadowPixmaps[5].handle();
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
data[enabledBorders] << m_emptyCornerBottomPix.handle();
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << m_emptyCornerLeftPix.handle();
} else {
data[enabledBorders] << m_emptyCornerPix.handle();
}
//shadow-left
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << m_shadowPixmaps[6].handle();
} else {
data[enabledBorders] << m_emptyVerticalPix.handle();
}
//shadow-topleft
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << m_shadowPixmaps[7].handle();
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
data[enabledBorders] << m_emptyCornerTopPix.handle();
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << m_emptyCornerLeftPix.handle();
} else {
data[enabledBorders] << m_emptyCornerPix.handle();
}
#endif
int left, top, right, bottom = 0;
QSize marginHint;
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
marginHint = q->elementSize("shadow-hint-top-margin");
if (marginHint.isValid()) {
top = marginHint.height();
} else {
top = m_shadowPixmaps[0].height(); // top
}
} else {
top = 1;
}
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
marginHint = q->elementSize("shadow-hint-right-margin");
if (marginHint.isValid()) {
right = marginHint.width();
} else {
right = m_shadowPixmaps[2].width(); // right
}
} else {
right = 1;
}
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
marginHint = q->elementSize("shadow-hint-bottom-margin");
if (marginHint.isValid()) {
bottom = marginHint.height();
} else {
bottom = m_shadowPixmaps[4].height(); // bottom
}
} else {
bottom = 1;
}
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
marginHint = q->elementSize("shadow-hint-left-margin");
if (marginHint.isValid()) {
left = marginHint.width();
} else {
left = m_shadowPixmaps[6].width(); // left
}
} else {
left = 1;
}
data[enabledBorders] << top << right << bottom << left;
}
void DialogShadows::Private::clearPixmaps()
{
#ifdef Q_WS_X11
if (m_managePixmaps) {
foreach (const QPixmap &pixmap, m_shadowPixmaps) {
XFreePixmap(QX11Info::display(), pixmap.handle());
}
XFreePixmap(QX11Info::display(), m_emptyCornerPix.handle());
XFreePixmap(QX11Info::display(), m_emptyCornerBottomPix.handle());
XFreePixmap(QX11Info::display(), m_emptyCornerLeftPix.handle());
XFreePixmap(QX11Info::display(), m_emptyCornerRightPix.handle());
XFreePixmap(QX11Info::display(), m_emptyCornerTopPix.handle());
XFreePixmap(QX11Info::display(), m_emptyVerticalPix.handle());
XFreePixmap(QX11Info::display(), m_emptyHorizontalPix.handle());
m_managePixmaps = false;
}
#endif
m_shadowPixmaps.clear();
data.clear();
}
void DialogShadows::Private::updateShadow(const QWidget *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
{
#ifdef Q_WS_X11
if (m_shadowPixmaps.isEmpty()) {
setupPixmaps();
}
if (!data.contains(enabledBorders)) {
setupData(enabledBorders);
}
Display *dpy = QX11Info::display();
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
//kDebug() << "going to set the shadow of" << winId() << "to" << data;
XChangeProperty(dpy, window->winId(), atom, XA_CARDINAL, 32, PropModeReplace,
reinterpret_cast<const unsigned char *>(data[enabledBorders].constData()), data[enabledBorders].size());
#endif
}
void DialogShadows::Private::clearShadow(const QWidget *window)
{
#ifdef Q_WS_X11
Display *dpy = QX11Info::display();
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
XDeleteProperty(dpy, window->winId(), atom);
#endif
}
bool DialogShadows::enabled() const
{
return hasElement("shadow-left");
}
#include "moc_dialogshadows_p.cpp"

View file

@ -0,0 +1,51 @@
/*
* Copyright 2011 by Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PLASMA_DIALOGSHADOWS_H
#define PLASMA_DIALOGSHADOWS_H
#include <QSet>
#include "plasma/framesvg.h"
#include "plasma/svg.h"
class DialogShadows : public Plasma::Svg
{
Q_OBJECT
public:
explicit DialogShadows(QObject *parent = 0, const QString &prefix = "dialogs/background");
static DialogShadows *self();
void addWindow(const QWidget *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
void removeWindow(const QWidget *window);
bool enabled() const;
private:
class Private;
Private * const d;
Q_PRIVATE_SLOT(d, void updateShadows())
Q_PRIVATE_SLOT(d, void windowDestroyed(QObject *deletedObject))
};
#endif

View file

@ -0,0 +1,42 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "dirlister.h"
#include <KIO/Job>
DirLister::DirLister(QObject *parent)
: KDirLister(parent)
{
}
DirLister:: ~DirLister()
{
}
void DirLister::handleError(KIO::Job *job)
{
if (!autoErrorHandlingEnabled()) {
emit showErrorMessage(job->errorString());
return;
}
KDirLister::handleError(job);
}

View file

@ -0,0 +1,42 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef DIRLISTER_H
#define DIRLISTER_H
#include <KDirLister>
// Reimplemented to provide custom error handling
class DirLister : public KDirLister
{
Q_OBJECT
public:
DirLister(QObject *parent = 0);
~DirLister();
signals:
void showErrorMessage(const QString &string);
protected:
void handleError(KIO::Job *job);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,285 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2008 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef FOLDERVIEW_H
#define FOLDERVIEW_H
#include <QCache>
#include <QSortFilterProxyModel>
#include <QStyleOption>
#include <QPointer>
#include <QBasicTimer>
#include <KActionCollection>
#include <KMimeType>
#include <Solid/Networking>
#include <plasma/containment.h>
#include "iconview.h"
#include "dirlister.h"
#include "proxymodel.h"
#include "ui_folderviewFilterConfig.h"
#include "ui_folderviewDisplayConfig.h"
#include "ui_folderviewLocationConfig.h"
#include "ui_folderviewPreviewConfig.h"
class KDirModel;
class KFileItemDelegate;
class KFilePlacesModel;
class KFilePreviewGenerator;
class KNewFileMenu;
class KFileItemActions;
class KJob;
class QItemSelectionModel;
class FolderView;
class ProxyModel;
class IconView;
class IconWidget;
class ListView;
class Label;
class Dialog;
/**
* Helper class that downloads a wallpaper image asynchronously to a suitable
* temporary directory in the user's home folder, and applies it to the given
* folderview containment when the download finishes.
*
* The class deletes itself automatically when the operation is completed.
*/
class RemoteWallpaperSetter : public QObject
{
Q_OBJECT
public:
RemoteWallpaperSetter(const KUrl &url, FolderView *containment);
private slots:
void result(KJob *job);
};
// ----------------------------------------------------------------------------
class FolderView : public Plasma::Containment
{
Q_OBJECT
public:
enum LabelType { None = 0, PlaceName, FullPath, Custom };
enum { Unsorted = -1 };
public:
FolderView(QObject *parent, const QVariantList &args);
~FolderView();
void init();
void saveState(KConfigGroup &config) const;
void paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRect &contentsRect);
void setPath(const QString&);
void setWallpaper(const KUrl &url);
void configChanged();
public slots:
// Move to Plasma::Containment in 4.9
void addUrls(const KUrl::List& urls);
protected:
void createConfigurationInterface(KConfigDialog *parent);
QList<QAction*> contextualActions();
void constraintsEvent(Plasma::Constraints);
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
protected slots:
// These slots are for KonqPopupMenu
void copy();
void cut();
void paste();
void pasteTo();
void refreshIcons();
void moveToTrash(Qt::MouseButtons, Qt::KeyboardModifiers);
void deleteSelectedIcons();
void renameSelectedIcon();
void emptyTrashBin();
void undoTextChanged(const QString &text);
void toggleIconsLocked(bool locked);
void toggleAlignToGrid(bool align);
void toggleClickToViewFolders(bool enable);
void toggleSortDescending(bool enable);
void toggleDirectoriesFirst(bool enable);
void layoutChanged(QAction *action);
void alignmentChanged(QAction *action);
void sortingChanged(QAction *action);
void aboutToShowCreateNew();
void updateIconWidget();
void iconWidgetClicked();
void activated(const QModelIndex &index);
void indexesMoved(const QModelIndexList &indexes);
void contextMenuRequest(QWidget *widget, const QPoint &screenPos);
void configAccepted();
void filterChanged(int index);
void selectAllMimetypes();
void deselectAllMimeTypes();
void fontSettingsChanged();
void iconSettingsChanged(int group);
void clickSettingsChanged(int category);
void plasmaThemeChanged();
//void clipboardDataChanged();
void updateScreenRegion();
void showPreviewConfigDialog();
private slots:
void networkAvailable();
void setTitleEditEnabled(int);
private:
void updatePasteAction();
void addActions(AbstractItemView *view);
void addActionGroupToCombo(QActionGroup *group, QComboBox *combo);
template <typename T>
void setCurrentItem(QComboBox *combo, T current);
QColor textColor() const;
void setupIconView();
void setUrl(const KUrl &url);
QSize iconSize() const;
void createActions();
void updateFlowActionsState();
void updateSortActionsState();
void updateListViewState();
void updateIconViewState();
void saveIconPositions() const;
KUrl::List selectedUrls(bool forTrash) const;
void showContextMenu(QWidget *widget, const QPoint &pos, const QModelIndexList &indexes);
void timerEvent(QTimerEvent *event);
void recreateLayout();
void setAppletTitle();
void toggleAllMimetypes(Qt::CheckState);
private:
KFileItemDelegate *m_delegate;
QPointer<KFilePreviewGenerator> m_previewGenerator;
QItemSelectionModel *m_selectionModel;
ProxyModel *m_model;
KDirModel *m_dirModel;
KFilePlacesModel *m_placesModel;
KFileItemActions *m_itemActions;
KAction *m_openWithAction;
IconView *m_iconView;
ListView *m_listView;
Label *m_label;
IconWidget *m_iconWidget;
Dialog *m_dialog;
QIcon m_icon;
KUrl m_url;
QColor m_textColor;
QString m_titleText;
ProxyModel::FilterMode m_filterType;
QString m_filterFiles;
QStringList m_filterFilesMimeList;
QPointer<KNewFileMenu> m_newMenu;
KActionCollection m_actionCollection;
QActionGroup *m_layoutGroup;
QActionGroup *m_alignmentGroup;
QActionGroup *m_sortingGroup;
int m_sortColumn;
Qt::SortOrder m_sortOrder;
Ui::folderviewFilterConfig uiFilter;
Ui::folderviewDisplayConfig uiDisplay;
Ui::folderviewLocationConfig uiLocation;
Ui::folderviewPreviewConfig uiPreviewConfig;
bool m_sortDirsFirst;
bool m_showPreviews;
bool m_drawShadows;
bool m_iconsLocked;
bool m_alignToGrid;
bool m_clickToView;
bool m_showSelectionMarker;
LabelType m_labelType;
QString m_customLabel;
QStringList m_previewPlugins;
int m_customIconSize;
int m_numTextLines;
IconView::Layout m_layout;
IconView::Alignment m_alignment;
QBasicTimer m_delayedSaveTimer;
DirLister *m_dirLister;
};
// ---------------------------------------------------------------------------
class MimeModel : public QStringListModel
{
public:
MimeModel(QObject *parent = 0);
virtual QVariant data(const QModelIndex &index, int role) const;
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
private:
KMimeType::List m_mimetypes;
QMap<KMimeType*, Qt::CheckState> m_state;
};
// ---------------------------------------------------------------------------
class ProxyMimeModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
ProxyMimeModel(QObject *parent = 0);
virtual void setSourceModel(QAbstractItemModel *sourceModel);
public slots:
void setFilter(const QString &filter);
protected:
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
private:
QString m_filter;
};
#endif

View file

@ -0,0 +1,490 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>folderviewDisplayConfig</class>
<widget class="QWidget" name="folderviewDisplayConfig">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>570</width>
<height>703</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="iconsTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Sorting</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="sortLabel">
<property name="text">
<string>Sort By:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>sortCombo</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="KComboBox" name="sortCombo">
<property name="whatsThis">
<string>Use this control to choose the criteria by which the icons will be sorted in the view.</string>
</property>
</widget>
</item>
<item row="1" column="3">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>38</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLabel" name="sortDescendingLabel">
<property name="text">
<string>Descending:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="foldersFirstLabel">
<property name="text">
<string>Folders first:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="foldersFirst">
<property name="whatsThis">
<string>Check this option if you want folders to have sorting precedence. When this option is turned off, folders will be treated like regular files with respect to sorting.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Arrangement</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="layoutLabel">
<property name="text">
<string>Arrange In:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QComboBox" name="layoutCombo">
<property name="whatsThis">
<string>Use this control to choose whether the icons will be arranged horizontally (in rows) or vertically (in columns).</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="alignmentLabel">
<property name="text">
<string>Align:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QComboBox" name="alignmentCombo">
<property name="whatsThis">
<string>Use this control to choose whether the icons will be aligned to the left or to the right side of the screen.</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="lockInPlaceLabel">
<property name="text">
<string>Lock in place:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QCheckBox" name="lockInPlace">
<property name="whatsThis">
<string>Check this option if you do not want the icons to be moveable in the view.
This option is useful if you want to avoid accidentally moving the icons while interacting with them.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="alignToGridLabel">
<property name="text">
<string>Align to grid:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QCheckBox" name="alignToGrid">
<property name="whatsThis">
<string>Check this option if you want the icons to be arranged in a grid.
When this option is checked, icons will automatically snap to the nearest grid cell when you move them around in the view.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="sizeSliderLabel">
<property name="text">
<string>Size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>sizeSlider</cstring>
</property>
</widget>
</item>
<item row="9" column="2" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Small</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="sizeSlider">
<property name="whatsThis">
<string>Use this slider to increase or decrease the size of the icons in the view.</string>
</property>
<property name="maximum">
<number>6</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Large</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Behavior</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="previewsAdvancedLabel">
<property name="text">
<string>Previews:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="2" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="showPreviews">
<property name="whatsThis">
<string>Check this option if you want to see previews of the file contents in the icons.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previewsAdvanced">
<property name="whatsThis">
<string>Click this button to choose for which types of files previews will be shown.</string>
</property>
<property name="text">
<string>More Preview Options...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="12" column="1">
<widget class="QLabel" name="clickToViewLabel">
<property name="text">
<string>Click to view folder:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="QCheckBox" name="clickToView">
<property name="whatsThis">
<string>Check this option if you want folder previews to appear only when clicked. When this option is turned off, folder previews will appear automatically when the mouse hovers over a folder.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="iconTextTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Icon Text</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="numLinesEditLabel">
<property name="text">
<string>Lines:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>numLinesEdit</cstring>
</property>
</widget>
</item>
<item row="14" column="2">
<widget class="KIntSpinBox" name="numLinesEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>Use this control to choose how many lines of text will be shown below the icons.</string>
</property>
<property name="specialValueText">
<string>1 line</string>
</property>
<property name="suffix">
<string> lines</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10</number>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="colorButtonLabel">
<property name="text">
<string>Color:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>colorButton</cstring>
</property>
</widget>
</item>
<item row="15" column="2">
<widget class="KColorButton" name="colorButton">
<property name="whatsThis">
<string>Click this button to choose the color which is used for the text labels in the view.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QLabel" name="drawShadowsLabel">
<property name="text">
<string>Shadows:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>numLinesEdit</cstring>
</property>
</widget>
</item>
<item row="16" column="2">
<widget class="QCheckBox" name="drawShadows">
<property name="whatsThis">
<string>&lt;html&gt;&lt;body&gt;&lt;p&gt;Check this option if you want the text labels to cast a shadow on the background.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Shadows help make the text easier to read by making it stand out more from the background.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Note that with dark text colors, this option will cause the text to glow with a bright halo, instead of casting a shadow.&lt;/i&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="17" column="4">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>44</width>
<height>216</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="sortDescending">
<property name="whatsThis">
<string>Check this option if you want the icons to be sorted in a descending order.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KColorButton</class>
<extends>QPushButton</extends>
<header>kcolorbutton.h</header>
</customwidget>
<customwidget>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>kcombobox.h</header>
</customwidget>
<customwidget>
<class>KIntSpinBox</class>
<extends>QSpinBox</extends>
<header>knuminput.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>sortCombo</tabstop>
<tabstop>sortDescending</tabstop>
<tabstop>foldersFirst</tabstop>
<tabstop>layoutCombo</tabstop>
<tabstop>alignmentCombo</tabstop>
<tabstop>lockInPlace</tabstop>
<tabstop>alignToGrid</tabstop>
<tabstop>sizeSlider</tabstop>
<tabstop>showPreviews</tabstop>
<tabstop>previewsAdvanced</tabstop>
<tabstop>clickToView</tabstop>
<tabstop>numLinesEdit</tabstop>
<tabstop>colorButton</tabstop>
<tabstop>drawShadows</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>folderviewFilterConfig</class>
<widget class="QWidget" name="folderviewFilterConfig">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>509</width>
<height>375</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="filterCombo">
<property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;If you have selected &quot;Show Files Matching&quot; or &quot;Hide Files Matching&quot;, only the files matching BOTH the conditions will be shown or hidden respectively.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For example, if you have &quot;*&quot; as your pattern, but have nothing selected in the MIME types, no files will be shown.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="fileFilters">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>10</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="1">
<layout class="QGridLayout" name="mimeTypeLayout">
<item row="5" column="0">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<item>
<widget class="QListView" name="filterFilesList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="flow">
<enum>QListView::TopToBottom</enum>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="selectAll">
<property name="text">
<string>Select All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deselectAll">
<property name="text">
<string>Deselect All</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="toolTip">
<string>Note that if you have selected &quot;Show Files Matching&quot; or &quot;Hide Files Matching&quot;,
only the files matching BOTH the conditions will be shown or hidden respectively.
For example, if you have &quot;*&quot; as your pattern, but have nothing selected in the MIME types, no files will be shown.</string>
</property>
<property name="text">
<string>&lt;a href=&quot;null&quot;&gt;Cannot See Any Files?&lt;/a&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="KLineEdit" name="searchMimetype">
<property name="clickMessage">
<string>Search file type</string>
</property>
<property name="showClearButton" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="fileTypesLabel">
<property name="text">
<string>File types:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="fileNameLabel">
<property name="text">
<string>File name pattern:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="KLineEdit" name="filterFilesPattern">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Space-separated list of extensions, e.g. *.txt *.od*</string>
</property>
<property name="whatsThis">
<string>Space-separated list of extensions, e.g. *.txt *.od* to display only office- and text-files</string>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="urlDropsEnabled">
<bool>false</bool>
</property>
<property name="clickMessage">
<string>Pattern filter</string>
</property>
<property name="showClearButton" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
</customwidgets>
<includes>
<include location="global">KUrlRequester</include>
</includes>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>folderviewLocationConfig</class>
<widget class="QWidget" name="folderviewLocationConfig">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>577</width>
<height>408</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="locationLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>138</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="showDesktopFolder">
<property name="text">
<string>Show the Desktop folder</string>
</property>
<attribute name="buttonGroup">
<string notr="true">locatgionButtonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="showPlace">
<property name="text">
<string>Show a place:</string>
</property>
<attribute name="buttonGroup">
<string notr="true">locatgionButtonGroup</string>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>25</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="KComboBox" name="placesCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="showCustomFolder">
<property name="text">
<string>Specify a folder:</string>
</property>
<property name="autoExclusive">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">locatgionButtonGroup</string>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>25</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="KUrlRequester" name="lineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="clickMessage">
<string>Type a path or a URL here</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="titleLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:400;&quot;&gt;Title:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="buddy">
<cstring>titleCombo</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="KComboBox" name="titleCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>false</bool>
</property>
<property name="autoCompletion">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="KLineEdit" name="titleEdit">
<property name="clickMessage">
<string>Enter custom title here</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>90</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>kcombobox.h</header>
</customwidget>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
<customwidget>
<class>KUrlRequester</class>
<extends>QFrame</extends>
<header>kurlrequester.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>showDesktopFolder</tabstop>
<tabstop>showPlace</tabstop>
<tabstop>placesCombo</tabstop>
<tabstop>showCustomFolder</tabstop>
<tabstop>lineEdit</tabstop>
<tabstop>titleCombo</tabstop>
<tabstop>titleEdit</tabstop>
</tabstops>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="locatgionButtonGroup"/>
</buttongroups>
</ui>

View file

@ -0,0 +1,31 @@
<ui version="4.0" >
<class>folderviewPreviewConfig</class>
<widget class="QWidget" name="folderviewPreviewConfig" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>Check the file types you want icon previews for:</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listView" >
<property name="alternatingRowColors" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,58 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "folderviewadapter.h"
FolderViewAdapter::FolderViewAdapter(AbstractItemView *view)
: KAbstractViewAdapter(view), m_view(view)
{
}
QAbstractItemModel *FolderViewAdapter::model() const
{
return m_view->model();
}
QSize FolderViewAdapter::iconSize() const
{
return m_view->iconSize();
}
QPalette FolderViewAdapter::palette() const
{
return m_view->palette();
}
QRect FolderViewAdapter::visibleArea() const
{
return m_view->visibleArea();
}
QRect FolderViewAdapter::visualRect(const QModelIndex &index) const
{
return m_view->visualRect(index);
}
void FolderViewAdapter::connect(Signal signal, QObject *receiver, const char *slot)
{
if (signal == ScrollBarValueChanged) {
QObject::connect(m_view->verticalScrollBar(), SIGNAL(valueChanged(int)), receiver, slot);
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef FOLDERVIEWADAPTER_H
#define FOLDERVIEWADAPTER_H
#include "kabstractviewadapter_p.h"
#include "abstractitemview.h"
class FolderViewAdapter : public KAbstractViewAdapter
{
public:
FolderViewAdapter(AbstractItemView *view);
QAbstractItemModel *model() const;
QSize iconSize() const;
QPalette palette() const;
QRect visibleArea() const;
QRect visualRect(const QModelIndex &index) const;
void connect(Signal signal, QObject *receiver, const char *slot);
private:
AbstractItemView *m_view;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,295 @@
/*
* Copyright © 2008, 2009, 2010 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2008 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef ICONVIEW_H
#define ICONVIEW_H
#include "abstractitemview.h"
#include "popupview.h"
#include "itemeditor.h"
#include "actionoverlay.h"
#include <QAbstractItemDelegate>
#include <QPointer>
#include <QCache>
#include <QTime>
#include <QBasicTimer>
class KUrl;
class KFileItemList;
class KonqOperations;
class QActionGroup;
class QStyleOptionViewItemV4;
class ToolTipWidget;
class Animator;
namespace Plasma
{
class ScrollBar;
}
struct ViewItem
{
ViewItem() : rect(QRect()), layouted(false), needSizeAdjust(true) {}
QRect rect;
bool layouted:1;
bool needSizeAdjust:1;
};
class IconView : public AbstractItemView
{
Q_OBJECT
public:
enum Flow { HorLeftToRight, VerLeftToRight, HorRightToLeft, VerRightToLeft };
enum Layout { Rows, Columns };
enum Alignment { Left, Right };
Q_PROPERTY(QSize gridSize READ gridSize WRITE setGridSize)
Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap)
Q_PROPERTY(bool alignToGrid READ alignToGrid WRITE setAlignToGrid)
Q_PROPERTY(bool clickToViewFolders READ clickToViewFolders WRITE setClickToViewFolders)
Q_PROPERTY(bool showSelectionMarker READ showSelectionMarker WRITE setShowSelectionMarker)
Q_PROPERTY(bool iconsMoveable READ iconsMoveable WRITE setIconsMoveable)
Q_PROPERTY(bool customLayout READ customLayout WRITE setCustomLayout)
Q_PROPERTY(Layout layout READ layout WRITE setLayout)
Q_PROPERTY(Alignment alignment READ alignment WRITE setAlignment)
public:
IconView(QGraphicsWidget *parent);
~IconView();
void setModel(QAbstractItemModel *model);
void setGridSize(const QSize &gridSize);
QSize gridSize() const;
void setIconSize(const QSize &gridSize);
void setWordWrap(bool on);
bool wordWrap() const;
void setTextLineCount(int rows);
int textLineCount() const;
void setLayout(Layout layout);
Layout layout() const;
void setAlignment(Alignment alignment);
Alignment alignment() const;
void setAlignToGrid(bool on);
bool alignToGrid() const;
void setIconsMoveable(bool on);
bool iconsMoveable() const;
void setCustomLayout(bool value);
bool customLayout() const;
/**
* The icon position data is encoded in a QStringList as follows:
*
* 1 string for version number
* 1 string for icon count
* 3 strings for every icon:
* 1 string for icon name
* 1 string for icon x position (relative to contentsRect().left())
* 1 string for icon y position (relative to contentsRect().top())
*/
void setIconPositionsData(const QStringList &data);
QStringList iconPositionsData() const;
void setPopupPreviewSettings(const bool &showPreview, const QStringList &plugins);
bool popupShowPreview() const;
QStringList popupPreviewPlugins() const;
void updateGridSize();
bool listingInProgress() const;
bool renameInProgress() const;
bool dragInProgress() const;
bool popupVisible() const;
int scrollBarExtent() const;
QSize sizeForRowsColumns(int rows, int columns) const;
QRect visualRect(const QModelIndex &index) const;
QRegion visualRegion(const QModelIndex &index) const;
QModelIndex indexAt(const QPointF &point) const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
void setClickToViewFolders(bool click);
bool clickToViewFolders() const;
void openPopup(const QModelIndex &index);
void setShowSelectionMarker(bool show);
bool showSelectionMarker() const;
bool overlayEnabled() const;
signals:
void indexesMoved(const QModelIndexList &indexes);
void popupViewClosed();
void busy(bool);
void modelChanged();
protected:
bool indexIntersectsRect(const QModelIndex &index, const QRect &rect) const;
void startDrag(const QPointF &pos, QWidget *widget);
void focusInEvent(QFocusEvent *event);
void focusOutEvent(QFocusEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void wheelEvent(QGraphicsSceneWheelEvent *event);
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
void timerEvent(QTimerEvent *event);
void changeEvent(QEvent *event);
void resizeEvent(QGraphicsSceneResizeEvent *event);
void rowsInserted(const QModelIndex &parent, int first, int last);
void rowsRemoved(const QModelIndex &parent, int first, int last);
void modelReset();
void layoutChanged();
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void commitData(QWidget *editor);
void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
void finishedScrolling();
QSize itemSize(const QStyleOptionViewItemV4 &option, const QModelIndex &index) const;
void paintItem(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index) const;
public slots:
void renameSelectedIcon();
void selectFirstIcon();
void selectLastIcon();
private slots:
void listingStarted(const KUrl &url);
void listingClear();
void listingCompleted();
void listingCanceled();
void listingError(const QString &message);
void itemsDeleted(const KFileItemList &items);
void popupCloseRequested();
void dropActionTriggered(QAction *action);
void dropCompleted();
void repositionWidgetsManually();
void closeEditor(QGraphicsWidget *editor, QAbstractItemDelegate::EndEditHint hint);
void checkIfFolderResult(const QModelIndex &index, bool isFolder);
void svgChanged();
void viewScrolled();
private:
void paintMessage(QPainter *painter, const QRect &rect, const QString &message,
const QIcon &icon = QIcon()) const;
int columnsForWidth(qreal width) const;
int rowsForHeight(qreal height) const;
QPoint nextGridPosition(const QPoint &prevPos, const QSize &gridSize, const QRect &contentRect) const;
QPoint findNextEmptyPosition(const QPoint &prevPos, const QSize &gridSize, const QRect &contentRect) const;
void layoutItems();
void alignIconsToGrid();
QRect itemsBoundingRect() const;
QRect adjustedContentsRect(const QSize &gridSize, int *rowCount, int *colCount) const;
bool doLayoutSanityCheck();
void updateScrollBar();
void updateScrollBarGeometry();
void updateEditorGeometry();
void updateToolTip();
void updateRubberband();
void updateActionButtons();
void createDropActions(const KUrl::List &urls, QActionGroup *actions);
QStyleOptionViewItemV4 viewOptions() const;
void selectIcon(QModelIndex index);
void selectFirstOrLastIcon(bool firstIcon); //Useful to select first or last icon when view is unsorted
void selectIconsInArea(const QRect &area, const QPoint &finalPos); //Selects all icons in the specified rectangular area
void selectIconRange(const QModelIndex &begin, const QModelIndex &end);
void repaintSelectedIcons();
QRect selectedItemsBoundingRect() const;
private:
QVector<ViewItem> m_items;
QHash<QString, QPoint> m_savedPositions;
mutable QCache<quint64, QRegion> m_regionCache;
qreal m_margins[4];
int m_columns;
int m_rows;
int m_validRows;
int m_numTextLines;
bool m_layoutBroken;
bool m_needPostLayoutPass;
bool m_positionsLoaded;
bool m_doubleClick;
bool m_dragInProgress;
bool m_hoverDrag;
bool m_iconsLocked;
bool m_alignToGrid;
bool m_wordWrap;
bool m_popupShowPreview;
bool m_folderIsEmpty;
bool m_clickToViewFolders;
bool m_showSelectionMarker;
bool m_drawIconShrinked;
QPersistentModelIndex m_hoveredIndex;
QPersistentModelIndex m_pressedIndex;
QPersistentModelIndex m_editorIndex;
QRect m_rubberBand;
QPointF m_buttonDownPos;
QPointF m_mouseMovedPos;
QTime m_pressTime;
Layout m_layout;
Alignment m_alignment;
QString m_errorMessage;
QPoint m_lastDeletedPos;
QPoint m_currentLayoutPos;
QSize m_gridSize;
QBasicTimer m_delayedLayoutTimer;
QBasicTimer m_delayedRelayoutTimer;
QBasicTimer m_delayedCacheClearTimer;
QBasicTimer m_toolTipShowTimer;
QBasicTimer m_searchQueryTimer;
ToolTipWidget *m_toolTipWidget;
QPointer<PopupView> m_popupView;
QPointer<QWidget> m_popupCausedWidget;
KonqOperations *m_dropOperation;
QActionGroup *m_dropActions;
QPersistentModelIndex m_popupIndex;
QPointer<ItemEditor> m_editor;
Animator *m_animator;
ActionOverlay *m_actionOverlay;
QStringList m_popupPreviewPlugins;
QString m_searchQuery;
};
#endif

View file

@ -0,0 +1,79 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "iconwidget.h"
#include <KDirModel>
#include <KDirLister>
#include <konq_operations.h>
#include <Plasma/Corona>
#include <QGraphicsSceneDragDropEvent>
IconWidget::IconWidget(QGraphicsItem *parent)
: Plasma::IconWidget(parent), m_model(0)
{
setAcceptDrops(true);
}
IconWidget::~IconWidget()
{
}
void IconWidget::setModel(KDirModel *model)
{
m_model = model;
}
void IconWidget::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
if (KUrl::List::canDecode(event->mimeData())){
Plasma::IconWidget::sceneEventFilter(this, event);
event->accept();
}
}
void IconWidget::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
Plasma::IconWidget::sceneEventFilter(this, event);
}
void IconWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
const QString appletMimeType = static_cast<Plasma::Corona*>(scene())->appletMimeType();
event->setAccepted(!event->mimeData()->hasFormat(appletMimeType));
}
void IconWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
{
// If the dropped item is an applet, let the parent widget handle it
const QString appletMimeType = static_cast<Plasma::Corona*>(scene())->appletMimeType();
if (event->mimeData()->hasFormat(appletMimeType)) {
event->ignore();
return;
}
QDropEvent ev(event->screenPos(), event->dropAction(), event->mimeData(),
event->buttons(), event->modifiers());
KonqOperations::doDrop(m_model->dirLister()->rootItem(), m_model->dirLister()->url(),
&ev, event->widget());
}

View file

@ -0,0 +1,48 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef ICONWIDGET_H
#define ICONWIDGET_H
#include <Plasma/IconWidget>
class KDirModel;
// Reimplemented to add drag and drop support
class IconWidget : public Plasma::IconWidget
{
public:
IconWidget(QGraphicsItem *parent = 0);
~IconWidget();
void setModel(KDirModel *model);
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
private:
KDirModel *m_model;
};
#endif

View file

@ -0,0 +1,128 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "itemeditor.h"
#include <KTextEdit>
#include <QAbstractItemModel>
#include <QAbstractItemDelegate>
#include <KMimeType>
ItemEditor::ItemEditor(QGraphicsWidget *parent, const QStyleOptionViewItemV4 &option,
const QModelIndex &index)
: QGraphicsProxyWidget(parent),
m_index(index),
m_uncommitted(true)
{
// Create the editor
m_editor = new KTextEdit();
m_editor->setAttribute(Qt::WA_NoSystemBackground);
m_editor->setAcceptRichText(false);
m_editor->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_editor->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_editor->setAlignment(option.displayAlignment);
m_editor->installEventFilter(this);
// Set the editor data
const QVariant value = index.data(Qt::EditRole);
const QString text = value.toString();
m_editor->insertPlainText(text);
m_editor->selectAll();
const QString extension = KMimeType::extractKnownExtension(text);
if (!extension.isEmpty()) {
// The filename contains an extension. Assure that only the filename
// gets selected.
const int selectionLength = text.length() - extension.length() - 1;
QTextCursor cursor = m_editor->textCursor();
cursor.movePosition(QTextCursor::StartOfBlock);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, selectionLength);
m_editor->setTextCursor(cursor);
}
setWidget(m_editor);
}
ItemEditor::~ItemEditor()
{
}
void ItemEditor::commitData()
{
if (m_uncommitted) {
const_cast<QAbstractItemModel*>(m_index.model())->setData(m_index, m_editor->toPlainText(), Qt::EditRole);
m_uncommitted = false;
}
}
bool ItemEditor::eventFilter(QObject *watched, QEvent *event)
{
KTextEdit *editor = qobject_cast<KTextEdit*>(watched);
if (!editor) {
return false;
}
switch (event->type())
{
case QEvent::KeyPress:
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
switch (keyEvent->key())
{
case Qt::Key_Tab:
case Qt::Key_Backtab:
commitData();
emit closeEditor(this, QAbstractItemDelegate::NoHint);
return true;
case Qt::Key_Enter:
case Qt::Key_Return:
if (!editor->toPlainText().isEmpty()) {
commitData();
emit closeEditor(this, QAbstractItemDelegate::SubmitModelCache);
}
return true;
case Qt::Key_Escape:
emit closeEditor(this, QAbstractItemDelegate::RevertModelCache);
return true;
default:
return false;
} // switch (keyEvent->key())
} // case QEvent::KeyPress
case QEvent::FocusOut:
{
if (m_uncommitted) {
commitData();
emit closeEditor(this, QAbstractItemDelegate::NoHint);
}
return true;
}
default:
return false;
} // switch (event->type())
}
#include "moc_itemeditor.cpp"

View file

@ -0,0 +1,56 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef EDITOR_H
#define EDITOR_H
#include <QGraphicsProxyWidget>
#include <QAbstractItemDelegate>
#include <QModelIndex>
#include <KTextEdit>
class QStyleOptionViewItemV4;
class ItemEditor : public QGraphicsProxyWidget
{
Q_OBJECT
public:
ItemEditor(QGraphicsWidget *parent, const QStyleOptionViewItemV4 &option,
const QModelIndex &index);
~ItemEditor();
KTextEdit *nativeWidget() const { return m_editor; }
signals:
void closeEditor(QGraphicsWidget *editor, QAbstractItemDelegate::EndEditHint hint = QAbstractItemDelegate::NoHint);
protected:
void commitData();
bool eventFilter(QObject *watched, QEvent *event);
private:
KTextEdit *m_editor;
QModelIndex m_index;
bool m_uncommitted;
};
#endif

View file

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public License *
* along with this library; see the file COPYING.LIB. If not, write to *
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301, USA. *
*******************************************************************************/
#ifndef KABSTRACTVIEWADAPTER_H
#define KABSTRACTVIEWADAPTER_H
#include <QObject>
class QAbstractItemModel;
class QModelIndex;
class QPalette;
class QRect;
class QSize;
/*
* Interface used by KFilePreviewGenerator to generate previews
* for files. The interface allows KFilePreviewGenerator to be
* independent from the view implementation.
*/
class KAbstractViewAdapter : public QObject
{
public:
enum Signal { ScrollBarValueChanged };
KAbstractViewAdapter(QObject *parent) : QObject(parent) {}
virtual ~KAbstractViewAdapter() {}
virtual QAbstractItemModel *model() const = 0;
virtual QSize iconSize() const = 0;
virtual QPalette palette() const = 0;
virtual QRect visibleArea() const = 0;
virtual QRect visualRect(const QModelIndex &index) const = 0;
virtual void connect(Signal signal, QObject *receiver, const char *slot) = 0;
};
#endif

View file

@ -0,0 +1,82 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2008 Andrew Lake <jamboarder@yahoo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "label.h"
#include <QString>
#include <QPainter>
#include "plasma/paintutils.h"
Label::Label(QGraphicsWidget *parent)
: QGraphicsWidget(parent)
{
QFontMetrics fm(font());
setMinimumHeight(fm.height() + 4);
setMaximumHeight(fm.height() + 4);
setCacheMode(DeviceCoordinateCache);
}
Label::~Label()
{
}
void Label::setText(const QString &text)
{
m_text = text;
update();
}
QString Label::text() const
{
return m_text;
}
void Label::setDrawShadow(bool on)
{
m_drawShadow = on;
update();
}
bool Label::drawShadow() const
{
return m_drawShadow;
}
void Label::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
QColor color = palette().color(QPalette::Text);
color.setAlphaF(.75);
QFontMetrics fm(font());
const QString text = fm.elidedText(m_text, Qt::ElideMiddle, contentsRect().width());
painter->save();
painter->setFont(font());
painter->setPen(color);
painter->drawText(contentsRect(), Qt::AlignCenter, text);
painter->restore();
}
#include "moc_label.cpp"

View file

@ -0,0 +1,53 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef LABEL_H
#define LABEL_H
#include <QGraphicsWidget>
class QString;
class QPainter;
class Label : public QGraphicsWidget
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(bool drawShadow READ drawShadow WRITE setDrawShadow)
public:
Label(QGraphicsWidget *parent);
~Label();
void setText(const QString &text);
QString text() const;
void setDrawShadow(bool on);
bool drawShadow() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
private:
QString m_text;
QPixmap m_divider;
bool m_drawShadow;
};
#endif

View file

@ -0,0 +1,648 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2008 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "listview.h"
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QItemSelectionModel>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <KDirModel>
#include <KStringHandler>
#include "animator.h"
#include "proxymodel.h"
#include "plasma/containment.h"
#include "plasma/corona.h"
#include "plasma/paintutils.h"
#include "plasma/theme.h"
ListView::ListView(QGraphicsWidget *parent)
: AbstractItemView(parent),
m_rowHeight(-1),
m_numTextLines(2),
m_dragInProgress(false),
m_wordWrap(true)
{
setAcceptHoverEvents(true);
setAcceptDrops(true);
setCacheMode(NoCache);
m_animator = new Animator(this);
}
ListView::~ListView()
{
}
void ListView::setModel(QAbstractItemModel *model)
{
AbstractItemView::setModel(model);
updateSizeHint();
}
void ListView::setIconSize(const QSize &size)
{
if (size != m_iconSize) {
m_iconSize = size;
m_rowHeight = -1;
updateSizeHint();
}
}
void ListView::setWordWrap(bool on)
{
if (m_wordWrap != on) {
m_wordWrap = on;
m_rowHeight = -1;
updateSizeHint();
}
}
bool ListView::wordWrap() const
{
return m_wordWrap;
}
void ListView::setTextLineCount(int count)
{
if (count != m_numTextLines) {
m_numTextLines = count;
m_rowHeight = -1;
updateSizeHint();
}
}
int ListView::textLineCount() const
{
return m_numTextLines;
}
void ListView::rowsInserted(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent)
Q_UNUSED(first)
Q_UNUSED(last)
markAreaDirty(visibleArea());
updateScrollBar();
updateSizeHint();
}
void ListView::rowsRemoved(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent)
Q_UNUSED(first)
Q_UNUSED(last)
markAreaDirty(visibleArea());
updateScrollBar();
updateSizeHint();
}
void ListView::modelReset()
{
markAreaDirty(visibleArea());
updateScrollBar();
updateSizeHint();
}
void ListView::layoutChanged()
{
markAreaDirty(visibleArea());
updateScrollBar();
updateSizeHint();
}
void ListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
markAreaDirty(visualRect(topLeft) | visualRect(bottomRight));
}
void ListView::svgChanged()
{
m_rowHeight = -1;
updateSizeHint();
}
void ListView::updateScrollBar()
{
if (!m_model) {
return;
}
if (m_rowHeight == -1 && m_model->rowCount() > 0) {
// Use the height of the first item for all items
const QSize size = itemSize(viewOptions(), m_model->index(0, 0));
m_rowHeight = size.height();
}
int max = int(m_rowHeight * m_model->rowCount() - contentsRect().height());
// Keep the scrollbar handle at the bottom if it was at the bottom and the viewport
// has grown vertically
bool updateValue = (m_scrollBar->minimum() != m_scrollBar->maximum()) &&
(max > m_scrollBar->maximum()) && (m_scrollBar->value() == m_scrollBar->maximum());
m_scrollBar->setRange(0, max);
m_scrollBar->setPageStep(contentsRect().height());
m_scrollBar->setSingleStep(m_rowHeight);
if (updateValue) {
m_scrollBar->setValue(max);
}
if (max > 0) {
m_scrollBar->show();
} else {
m_scrollBar->hide();
}
}
QSize ListView::itemSize(const QStyleOptionViewItemV4 &option, const QModelIndex &index) const
{
qreal left, top, right, bottom;
m_itemFrame->getMargins(left, top, right, bottom);
QFont font = option.font;
KFileItem item = qvariant_cast<KFileItem>(index.data(KDirModel::FileItemRole));
if (item.isLink()) {
font.setItalic(true);
}
QFontMetrics fm(font);
QSize size;
size.rwidth() += contentsRect().width();
size.rheight() = qMax(option.decorationSize.height(), m_numTextLines * fm.height());
size.rheight() += top + bottom;
return size;
}
void ListView::updateSizeHint()
{
if (m_rowHeight == -1 && m_model->rowCount() > 0) {
// Use the height of the first item for all items
const QSize size = itemSize(viewOptions(), m_model->index(0, 0));
m_rowHeight = size.height();
}
QFontMetrics fm(font());
setPreferredSize(m_iconSize.width() + fm.lineSpacing() * 18, m_rowHeight * m_model->rowCount());
}
QRect ListView::visualRect(const QModelIndex &index) const
{
if (!index.isValid() || index.row() >= m_model->rowCount()) {
return QRect();
}
QRectF cr = contentsRect();
return QRect(cr.left(), cr.top() + index.row() * m_rowHeight, cr.width(), m_rowHeight);
}
void ListView::paintItem(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index) const
{
// Draw the item background
// ========================
const bool selected = (option.state & QStyle::State_Selected);
const qreal hoverProgress = m_animator->hoverProgress(index);
QPixmap from(option.rect.size());
QPixmap to(option.rect.size());
from.fill(Qt::transparent);
to.fill(Qt::transparent);
if (selected) {
QPainter p(&from);
m_itemFrame->setElementPrefix("selected");
m_itemFrame->resizeFrame(option.rect.size());
m_itemFrame->paintFrame(&p, QPoint());
}
if (hoverProgress > 0.0) {
QPainter p(&to);
m_itemFrame->setElementPrefix(selected ? "selected+hover" : "hover");
m_itemFrame->resizeFrame(option.rect.size());
m_itemFrame->paintFrame(&p, QPoint());
p.end();
QPixmap result = Plasma::PaintUtils::transition(from, to, hoverProgress);
painter->drawPixmap(option.rect.topLeft(), result);
} else if (selected) {
painter->drawPixmap(option.rect.topLeft(), from);
}
qreal left, top, right, bottom;
m_itemFrame->getMargins(left, top, right, bottom);
const QRect r = option.rect.adjusted(left, top, -right, -bottom);
const QRect ir = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter,
option.decorationSize, r);
const QRect tr = QStyle::alignedRect(option.direction, Qt::AlignRight | Qt::AlignVCenter,
QSize(r.width() - ir.width() - 4, r.height()), r);
// Draw the text label
// ===================
QFont font = option.font;
KFileItem item = qvariant_cast<KFileItem>(index.data(KDirModel::FileItemRole));
if (item.isLink()) {
font.setItalic(true);
}
const QString text = index.data(Qt::DisplayRole).toString();
QTextLayout layout;
layout.setText(KStringHandler::preProcessWrap(text));
layout.setFont(font);
const QSize size = doTextLayout(layout, tr.size(), Qt::AlignLeft | Qt::AlignVCenter,
QTextOption::WrapAtWordBoundaryOrAnywhere);
painter->setPen(option.palette.color(QPalette::Text));
drawTextLayout(painter, layout, tr);
// Draw the icon
// =============
const QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
icon.paint(painter, ir);
// Draw the focus rect
// ===================
if (option.state & QStyle::State_HasFocus) {
QRect fr = QStyle::alignedRect(layoutDirection(), Qt::AlignCenter, size, tr);
fr.adjust(-2, -2, 2, 2);
QColor color = Qt::white;
color.setAlphaF(.33);
QColor transparent = color;
transparent.setAlphaF(0);
QLinearGradient g1(0, fr.top(), 0, fr.bottom());
g1.setColorAt(0, color);
g1.setColorAt(1, transparent);
QLinearGradient g2(fr.left(), 0, fr.right(), 0);
g2.setColorAt(0, transparent);
g2.setColorAt(.5, color);
g2.setColorAt(1, transparent);
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(QPen(g1, 0));
painter->setBrush(Qt::NoBrush);
painter->drawRoundedRect(QRectF(fr).adjusted(.5, .5, -.5, -.5), 2, 2);
painter->setPen(QPen(g2, 0));
painter->drawLine(QLineF(fr.left() + 2, fr.bottom() + .5,
fr.right() - 2, fr.bottom() + .5));
painter->restore();
}
}
void ListView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget)
const QRect cr = contentsRect().toRect();
if (!cr.isValid()) {
return;
}
QRect clipRect = cr & option->exposedRect.toAlignedRect();
if (clipRect.isEmpty()) {
return;
}
int offset = m_scrollBar->value();
prepareBackBuffer();
painter->setClipRect(clipRect);
// Update the dirty region in the backbuffer
// =========================================
if (!m_dirtyRegion.isEmpty()) {
QStyleOptionViewItemV4 opt = viewOptions();
int width = m_scrollBar->isVisible() ? cr.width() - m_scrollBar->geometry().width() : cr.width();
if (m_rowHeight == -1 && m_model->rowCount() > 0) {
// Use the height of the first item for all items
const QSize size = itemSize(opt, m_model->index(0, 0));
m_rowHeight = size.height();
}
QPainter p(&m_pixmap);
p.translate(-cr.topLeft() - QPoint(0, offset));
p.setClipRegion(m_dirtyRegion);
// Clear the dirty region
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(mapToViewport(cr).toAlignedRect(), Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
for (int i = 0; i < m_model->rowCount(); i++) {
opt.rect = QRect(cr.left(), cr.top() + i * m_rowHeight, width, m_rowHeight);
if (!m_dirtyRegion.intersects(opt.rect)) {
continue;
}
const QModelIndex index = m_model->index(i, 0);
opt.state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver | QStyle::State_Selected);
if (m_selectionModel->isSelected(index)) {
if (m_dragInProgress) {
continue;
}
opt.state |= QStyle::State_Selected | QStyle::State_MouseOver;
}
if (hasFocus() && index == m_selectionModel->currentIndex()) {
opt.state |= QStyle::State_HasFocus;
}
paintItem(&p, opt, index);
}
m_dirtyRegion = QRegion();
}
syncBackBuffer(painter, clipRect);
}
QModelIndex ListView::indexAt(const QPointF &pos) const
{
int row = pos.y() / m_rowHeight;
return row < m_model->rowCount() ? m_model->index(row, 0) : QModelIndex();
}
void ListView::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
const QPoint pos = mapToViewport(event->pos()).toPoint();
const QModelIndex index = indexAt(pos);
if (m_selectionModel->currentIndex().isValid()) {
markAreaDirty(visualRect(m_selectionModel->currentIndex()));
}
if (index.isValid()) {
emit entered(index);
m_selectionModel->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
markAreaDirty(visualRect(index));
}
}
void ListView::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
const QPoint pos = mapToViewport(event->pos()).toPoint();
const QModelIndex index = indexAt(pos);
if (index != m_selectionModel->currentIndex()) {
if (m_selectionModel->currentIndex().isValid()) {
emit left(m_selectionModel->currentIndex());
}
if (index.isValid()) {
emit entered(index);
}
markAreaDirty(visualRect(index));
markAreaDirty(visualRect(m_selectionModel->currentIndex()));
m_selectionModel->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
}
}
void ListView::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event)
if (!m_pressedIndex.isValid() && m_selectionModel->currentIndex().isValid()) {
emit left(m_selectionModel->currentIndex());
markAreaDirty(visualRect(m_selectionModel->currentIndex()));
m_selectionModel->clear();
}
}
void ListView::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
const QPointF pos = mapToViewport(event->pos());
//setFocus(Qt::MouseFocusReason);
if (event->button() == Qt::RightButton) {
const QModelIndex index = indexAt(pos);
if (index.isValid()) {
if (!m_selectionModel->isSelected(index)) {
m_selectionModel->select(index, QItemSelectionModel::ClearAndSelect);
m_selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
markAreaDirty(visibleArea());
}
event->ignore(); // Causes contextMenuEvent() to get called
} else if (m_selectionModel->hasSelection()) {
m_selectionModel->clearSelection();
markAreaDirty(visibleArea());
}
m_pressedIndex = index;
return;
}
if (event->button() == Qt::LeftButton) {
const QModelIndex index = indexAt(pos);
// If an icon was pressed
if (index.isValid())
{
if (event->modifiers() & Qt::ControlModifier) {
m_selectionModel->select(index, QItemSelectionModel::Toggle);
m_selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
markAreaDirty(visualRect(index));
} else if (!m_selectionModel->isSelected(index)) {
m_selectionModel->select(index, QItemSelectionModel::ClearAndSelect);
m_selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
markAreaDirty(visibleArea());
}
m_pressedIndex = index;
return;
}
}
}
void ListView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
const QPointF pos = mapToViewport(event->pos());
const QModelIndex index = indexAt(pos);
if (index.isValid() && index == m_pressedIndex && !(event->modifiers() & Qt::ControlModifier)) {
emit activated(index);
m_selectionModel->clearSelection();
markAreaDirty(visibleArea());
}
}
m_pressedIndex = QModelIndex();
}
void ListView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (!(event->buttons() & Qt::LeftButton)) {
return;
}
// If an item is pressed
if (m_pressedIndex.isValid())
{
const QPointF buttonDownPos = event->buttonDownPos(Qt::LeftButton);
const QPointF point = event->pos() - buttonDownPos;
if (point.toPoint().manhattanLength() >= QApplication::startDragDistance())
{
startDrag(mapToViewport(buttonDownPos), event->widget());
}
return;
}
}
void ListView::wheelEvent(QGraphicsSceneWheelEvent *event)
{
if ((event->modifiers() & Qt::CTRL) || (event->orientation() == Qt::Horizontal)) {
// Let the event propagate to the parent widget
event->ignore();
return;
}
const int pixels = 96 * event->delta() / 120;
smoothScroll(0, -pixels);
}
void ListView::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
const QPointF pos = mapToViewport(event->pos());
const QModelIndex index = indexAt(pos);
if (index.isValid()) {
emit contextMenuRequest(event->widget(), event->screenPos());
} else {
// Let the event propagate to the parent widget
event->ignore();
}
}
void ListView::dropEvent(QGraphicsSceneDragDropEvent *)
{
m_pressedIndex = QModelIndex();
}
void ListView::resizeEvent(QGraphicsSceneResizeEvent *)
{
const QRectF cr = contentsRect();
const QRectF r = QRectF(cr.right() - m_scrollBar->geometry().width(), cr.top(),
m_scrollBar->geometry().width(), cr.height());
if (m_scrollBar->geometry() != r) {
m_scrollBar->setGeometry(r);
}
updateScrollBar();
markAreaDirty(visibleArea());
}
// pos is the position where the mouse was clicked in the applet.
// widget is the widget that sent the mouse event that triggered the drag.
void ListView::startDrag(const QPointF &pos, QWidget *widget)
{
QModelIndexList indexes = m_selectionModel->selectedIndexes();
QRect boundingRect;
foreach (const QModelIndex &index, indexes) {
boundingRect |= visualRect(index);
}
QPixmap pixmap(boundingRect.size());
pixmap.fill(Qt::transparent);
QStyleOptionViewItemV4 option = viewOptions();
// ### We can't draw the items as selected or hovered since Qt doesn't
// use an ARGB window for the drag pixmap.
//option.state |= QStyle::State_Selected | QStyle::State_MouseOver;
option.state &= ~(QStyle::State_Selected | QStyle::State_MouseOver);
QPainter p(&pixmap);
foreach (const QModelIndex &index, indexes)
{
option.rect = visualRect(index).translated(-boundingRect.topLeft());
paintItem(&p, option, index);
}
p.end();
// Mark the area containing the about-to-be-dragged items as dirty, so they
// will be erased from the view on the next repaint. We have to do this
// before calling QDrag::exec(), since it's a blocking call.
markAreaDirty(boundingRect);
m_dragInProgress = true;
QDrag *drag = new QDrag(widget);
drag->setMimeData(m_model->mimeData(indexes));
drag->setPixmap(pixmap);
drag->setHotSpot((pos - boundingRect.topLeft()).toPoint());
drag->exec(m_model->supportedDragActions());
m_dragInProgress = false;
// Repaint the dragged icons in case the drag did not remove the file
markAreaDirty(boundingRect);
}
QStyleOptionViewItemV4 ListView::viewOptions() const
{
QStyleOptionViewItemV4 option;
initStyleOption(&option);
option.font = font();
option.decorationAlignment = Qt::AlignCenter;
option.decorationPosition = QStyleOptionViewItem::Left;
option.decorationSize = iconSize();
option.displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
option.textElideMode = Qt::ElideMiddle;
option.locale = QLocale::system();
option.widget = m_styleWidget;
option.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
if (m_wordWrap) {
option.features = QStyleOptionViewItemV2::WrapText;
}
return option;
}
#include "moc_listview.cpp"

View file

@ -0,0 +1,98 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2008 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef LISTVIEW_H
#define LISTVIEW_H
#include "abstractitemview.h"
#include <QCache>
class QStyleOptionViewItemV4;
class Animator;
namespace Plasma {
class FrameSvg;
}
class ListView : public AbstractItemView
{
Q_OBJECT
public:
ListView(QGraphicsWidget *parent = 0);
~ListView();
void setModel(QAbstractItemModel *model);
void setIconSize(const QSize &iconSize);
void setWordWrap(bool on);
bool wordWrap() const;
void setTextLineCount(int rows);
int textLineCount() const;
QModelIndex indexAt(const QPointF &point) const;
QRect visualRect(const QModelIndex &index) const;
protected:
void startDrag(const QPointF &pos, QWidget *widget);
void updateScrollBar();
void updateSizeHint();
QStyleOptionViewItemV4 viewOptions() const;
QSize itemSize(const QStyleOptionViewItemV4 &option, const QModelIndex &index) const;
void paintItem(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index) const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void wheelEvent(QGraphicsSceneWheelEvent *event);
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
void resizeEvent(QGraphicsSceneResizeEvent *event);
void rowsInserted(const QModelIndex &parent, int first, int last);
void rowsRemoved(const QModelIndex &parent, int first, int last);
void modelReset();
void layoutChanged();
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
private slots:
void svgChanged();
private:
Animator *m_animator;
int m_rowHeight;
int m_numTextLines;
QPersistentModelIndex m_pressedIndex;
bool m_dragInProgress;
bool m_wordWrap;
bool m_drawShadows;
};
#endif // LISTVIEW_H

View file

@ -0,0 +1,164 @@
[Desktop Entry]
Name=Folder
Name[af]=Gids
Name[ar]=مجلد
Name[as]=
Name[ast]=Carpeta
Name[be]=Тэчка
Name[be@latin]=Kataloh
Name[bg]=Папка
Name[bn]=
Name[bn_IN]=
Name[br]=Renkell
Name[bs]=Fascikla
Name[ca]=Carpeta
Name[ca@valencia]=Carpeta
Name[cs]=Složka
Name[csb]=Katalog
Name[cy]=Plygell
Name[da]=Mappe
Name[de]=Ordner
Name[el]=Φάκελος
Name[en_GB]=Folder
Name[eo]=Dosierujo
Name[es]=Carpeta
Name[et]=Kataloog
Name[eu]=Karpeta
Name[fa]=پوشه
Name[fi]=Kansio
Name[fr]=Dossier
Name[fy]=Map
Name[ga]=Fillteán
Name[gl]=Cartafol
Name[gu]=
Name[he]=תיקייה
Name[hi]=
Name[hne]=
Name[hr]=Mapa
Name[hsb]=Zapisk
Name[hu]=Mappa
Name[ia]=Dossier
Name[id]=Folder
Name[is]=Mappa
Name[it]=Cartella
Name[ja]=
Name[ka]=
Name[kk]=Қапшық
Name[km]=
Name[kn]=
Name[ko]=
Name[ku]=Peldank
Name[lt]=Aplankas
Name[lv]=Mape
Name[mai]=
Name[mk]=Папка
Name[ml]=
Name[mr]=
Name[ms]=Folder
Name[nb]=Mappe
Name[nds]=Orner
Name[ne]=
Name[nl]=Map
Name[nn]=Mappe
Name[oc]=Repertòri
Name[or]=
Name[pa]=
Name[pl]=Katalog
Name[pt]=Pasta
Name[pt_BR]=Pasta
Name[ro]=Dosar
Name[ru]=Папка
Name[se]=Máhppa
Name[si]=
Name[sk]=Priečinok
Name[sl]=Mapa
Name[sr]=Фасцикла
Name[sr@ijekavian]=Фасцикла
Name[sr@ijekavianlatin]=Fascikla
Name[sr@latin]=Fascikla
Name[sv]=Katalog
Name[ta]=
Name[te]=
Name[tg]=Феҳрист
Name[th]=
Name[tr]=Dizin
Name[ug]=قىسقۇچ
Name[uk]=Тека
Name[uz]=Jild
Name[uz@cyrillic]=Жилд
Name[vi]=Thư mc
Name[wa]=Ridant
Name[x-test]=xxFolderxx
Name[zh_CN]=
Name[zh_TW]=
Comment=Display the contents of folders
Comment[ar]=اعرض محتوى المجلدات
Comment[bg]=Показва съдържанието на папки
Comment[bs]=Prikaži sadržaj direktorija
Comment[ca]=Mostra el contingut de les carpetes
Comment[ca@valencia]=Mostra el contingut de les carpetes
Comment[cs]=Zobrazit obsah složek
Comment[da]=Vis indholdet af mapper
Comment[de]=Ordnerinhalte anzeigen
Comment[el]=Εμφάνιση περιεχομένων των φακέλων
Comment[en_GB]=Display the contents of folders
Comment[es]=Mostrar el contenido de las carpetas
Comment[et]=Kataloogide sisu näitamine
Comment[eu]=Bistaratu karpeten edukia
Comment[fi]=Näyttää kansion sisällön
Comment[fr]=Afficher les contenus de dossiers
Comment[ga]=Taispeáin inneachar d'fhillteáin
Comment[gl]=Mostra o contido dos cartafoles
Comment[he]=הצגת התוכן של תיקייה
Comment[hu]=Megjeleníti a mappák tartalmát
Comment[ia]=Monstra le contentos de dossieres
Comment[id]=Tampilkan isi folder
Comment[is]=Sýna innihald mappa
Comment[it]=Mostra il contenuto delle cartelle
Comment[kk]=Қапшықтардағыны көрсету
Comment[km]=
Comment[ko]=
Comment[lt]=Rodyti aplankų turinį
Comment[lv]=Rādīt mapju saturu
Comment[mr]=
Comment[nb]=Vis pampers innhold
Comment[nds]=Den Inholt vun Ornern wiesen
Comment[nl]=Toon de inhoud van mappen
Comment[pa]=
Comment[pl]=Wyświetl zawartość katalogów
Comment[pt]=Mostrar o conteúdo das pastas
Comment[pt_BR]=Mostra o conteúdo das pastas
Comment[ro]=Afișează conținutul dosarelor
Comment[ru]=Вывод содержимого папки
Comment[sk]=Zobraziť obsah priečinkov
Comment[sl]=Pokaži vsebino map
Comment[sr]=Приказује садржај фасцикли
Comment[sr@ijekavian]=Приказује садржај фасцикли
Comment[sr@ijekavianlatin]=Prikazuje sadržaj fascikli
Comment[sr@latin]=Prikazuje sadržaj fascikli
Comment[sv]=Visa innehåll i kataloger
Comment[tg]=Намоиши мазмуни феҳристҳо
Comment[tr]=Dizinlerin içeriğini göster
Comment[ug]=قىسقۇچلارنىڭ مەزمۇنلىرىنى كۆرسىتىدۇ
Comment[uk]=Показ вмісту тек
Comment[wa]=Håynêye çou k' i gn a dins des ridants
Comment[x-test]=xxDisplay the contents of foldersxx
Comment[zh_CN]=
Comment[zh_TW]=
Type=Service
Icon=folder
X-KDE-ServiceTypes=Plasma/Applet,Plasma/Containment
X-Plasma-ContainmentCategories=desktop
X-Plasma-DropMimeTypes=inode/directory
X-KDE-Library=plasma_applet_folderview
X-KDE-PluginInfo-Author=Fredrik Höglund
X-KDE-PluginInfo-Email=fredrik@kde.org
X-KDE-PluginInfo-Name=folderview
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=
X-KDE-PluginInfo-Category=File System
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=LGPL
X-KDE-PluginInfo-EnabledByDefault=true

View file

@ -0,0 +1,705 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "popupview.h"
#include "dialogshadows_p.h"
#include <QApplication>
#include <QClipboard>
#include <QDesktopWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsWidget>
#include <QItemSelectionModel>
#include <QStyle>
#include <KAction>
#include <KBookmarkManager>
#include <KDesktopFile>
#include <KDirModel>
#include <kfileitemactions.h>
#include <KFileItemDelegate>
#include <kfileitemlistproperties.h>
#include <kfilepreviewgenerator.h>
#include <knewfilemenu.h>
#include <KWindowSystem>
#include <KMenu>
#include <kio/fileundomanager.h>
#include <kio/paste.h>
#include <konqmimedata.h>
#include <konq_operations.h>
#include <konq_popupmenu.h>
#include "dirlister.h"
#include "folderviewadapter.h"
#include "iconview.h"
#include "proxymodel.h"
#include <Plasma/Applet>
#include <Plasma/BusyWidget>
#include <Plasma/FrameSvg>
#include <Plasma/Theme>
#include <Plasma/WindowEffects>
QTime PopupView::s_lastOpenClose;
PopupView::PopupView(const QModelIndex &index, const QPoint &pos,
const bool &showPreview, const QStringList &previewPlugins,
const IconView *parentView)
: QWidget(0, Qt::X11BypassWindowManagerHint),
m_view(0),
m_parentView(parentView),
m_busyWidget(0),
m_iconView(0),
m_parentViewModel(0),
m_dirModel(0),
m_model(0),
m_actionCollection(this),
m_newMenu(0),
m_itemActions(0),
m_showingMenu(false),
m_showPreview(showPreview),
m_delayedClose(false),
m_previewPlugins(previewPlugins)
{
setAttribute(Qt::WA_TranslucentBackground);
#ifdef Q_WS_X11
if (KWindowSystem::compositingActive()) {
setAttribute(Qt::WA_NoSystemBackground, false);
}
#endif
KWindowSystem::setState(effectiveWinId(), NET::SkipTaskbar | NET::SkipPager);
setAcceptDrops(true);
QPalette pal = palette();
pal.setColor(backgroundRole(), Qt::transparent);
pal.setColor(QPalette::Text, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
setPalette(pal);
m_parentViewModel = static_cast<const ProxyModel*>(index.model());
KFileItem item = m_parentViewModel->itemForIndex(index);
if (item.isDesktopFile()) {
KDesktopFile file(item.localPath());
m_url = file.readUrl();
} else {
m_url = item.targetUrl();
}
m_background = new Plasma::FrameSvg(this);
m_background->setImagePath("dialogs/background");
int left = m_background->marginSize(Plasma::LeftMargin);
int top = m_background->marginSize(Plasma::TopMargin);
int right = m_background->marginSize(Plasma::RightMargin);
int bottom = m_background->marginSize(Plasma::BottomMargin);
setContentsMargins(left, top, right, bottom);
resize(parentView->sizeForRowsColumns(2, 3) + QSize(left + right, top + bottom));
const QRect available = QApplication::desktop()->availableGeometry(pos);
QPoint pt = pos;
if (pt.x() + width() > available.right()) {
pt.rx() -= width();
}
if (pt.x() < available.left()) {
pt.rx() = available.left();
}
if (pt.y() + height() > available.bottom()) {
pt.ry() -= height();
}
if (pt.y() < available.top()) {
pt.ry() = available.top();
}
Plasma::WindowEffects::overrideShadow(winId(), true);
move(pt);
show();
QTimer::singleShot(10, this, SLOT(init()));
s_lastOpenClose.restart();
}
PopupView::~PopupView()
{
delete m_newMenu;
s_lastOpenClose.restart();
}
void PopupView::delayedHide()
{
if (!m_iconView || !m_iconView->dragInProgress()) {
m_hideTimer.start(400, this);
}
}
bool PopupView::dragInProgress()
{
return m_iconView && m_iconView->dragInProgress();
}
void PopupView::init()
{
if (m_model) {
return;
}
m_scene = new QGraphicsScene(this);
m_view = new QGraphicsView(m_scene, this);
m_view->setFrameShape(QFrame::NoFrame);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->viewport()->setAutoFillBackground(false);
m_view->setGeometry(contentsRect());
m_view->show();
DirLister *lister = new DirLister(this);
lister->setDelayedMimeTypes(true);
lister->setAutoErrorHandlingEnabled(false, 0);
lister->openUrl(m_url);
m_dirModel = new KDirModel(this);
m_dirModel->setDropsAllowed(KDirModel::DropOnDirectory | KDirModel::DropOnLocalExecutable);
m_dirModel->setDirLister(lister);
m_model = new ProxyModel(this);
m_model->setSourceModel(m_dirModel);
m_model->setSortLocaleAware(m_parentViewModel->isSortLocaleAware());
m_model->setParseDesktopFiles(m_parentViewModel->parseDesktopFiles());
m_model->setFilterMode(m_parentViewModel->ProxyModel::NoFilter);
m_model->setDynamicSortFilter(true);
if (!m_parentViewModel->dynamicSortFilter()) {
m_model->setSortDirectoriesFirst(true);
m_model->sort(int(KDirModel::Name), Qt::AscendingOrder);
} else {
m_model->setSortDirectoriesFirst(m_parentViewModel->sortDirectoriesFirst());
m_model->sort(m_parentViewModel->sortColumn(), m_parentViewModel->sortOrder());
}
m_delegate = new KFileItemDelegate(this);
m_selectionModel = new QItemSelectionModel(m_model, this);
m_iconView = new IconView(0);
m_iconView->setModel(m_model);
m_iconView->setItemDelegate(m_delegate);
m_iconView->setSelectionModel(m_selectionModel);
m_iconView->setFont(m_parentView->font());
m_iconView->setPalette(palette());
m_iconView->setDrawShadows(m_parentView->drawShadows());
m_iconView->setIconSize(m_parentView->iconSize());
m_iconView->setGridSize(m_parentView->gridSize());
m_iconView->setTextLineCount(m_parentView->textLineCount());
m_iconView->setWordWrap(m_parentView->wordWrap());
m_iconView->setIconsMoveable(false);
m_iconView->setClickToViewFolders(false);
m_iconView->setShowSelectionMarker(m_parentView->showSelectionMarker());
connect(m_iconView, SIGNAL(activated(QModelIndex)), SLOT(activated(QModelIndex)));
connect(m_iconView, SIGNAL(contextMenuRequest(QWidget*,QPoint)), SLOT(contextMenuRequest(QWidget*,QPoint)));
connect(m_iconView, SIGNAL(busy(bool)), SLOT(setBusy(bool)));
connect(m_iconView, SIGNAL(popupViewClosed()), SLOT(maybeClose()));
FolderViewAdapter *adapter = new FolderViewAdapter(m_iconView);
m_previewGenerator = new KFilePreviewGenerator(adapter, m_model);
m_previewGenerator->setPreviewShown(m_showPreview);
m_previewGenerator->setEnabledPlugins(m_previewPlugins);
m_iconView->setGeometry(contentsRect());
m_iconView->show();
m_scene->addItem(m_iconView);
setBusy(true);
}
void PopupView::createActions()
{
// Remove the Shift+Delete shortcut from the cut action, since it's used for deleting files
KAction *cut = KStandardAction::cut(this, SLOT(cut()), this);
KShortcut cutShortCut = cut->shortcut();
cutShortCut.remove(Qt::SHIFT + Qt::Key_Delete);
cut->setShortcut(cutShortCut);
KAction *copy = KStandardAction::copy(this, SLOT(copy()), this);
KIO::FileUndoManager *manager = KIO::FileUndoManager::self();
KAction *undo = KStandardAction::undo(manager, SLOT(undo()), this);
connect(manager, SIGNAL(undoAvailable(bool)), undo, SLOT(setEnabled(bool)));
connect(manager, SIGNAL(undoTextChanged(QString)), SLOT(undoTextChanged(QString)));
undo->setEnabled(manager->undoAvailable());
KAction *paste = KStandardAction::paste(this, SLOT(paste()), this);
KAction *pasteTo = KStandardAction::paste(this, SLOT(pasteTo()), this);
pasteTo->setEnabled(false); // Only enabled during popupMenu()
QString actionText = KIO::pasteActionText();
if (!actionText.isEmpty()) {
paste->setText(actionText);
} else {
paste->setEnabled(false);
}
KAction *rename = new KAction(KIcon("edit-rename"), i18n("&Rename"), this);
rename->setShortcut(Qt::Key_F2);
connect(rename, SIGNAL(triggered()), SLOT(renameSelectedIcon()));
KAction *trash = new KAction(KIcon("user-trash"), i18n("&Move to Trash"), this);
trash->setShortcut(Qt::Key_Delete);
connect(trash, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)),
SLOT(moveToTrash(Qt::MouseButtons,Qt::KeyboardModifiers)));
KAction *emptyTrash = new KAction(KIcon("trash-empty"), i18n("&Empty Trash Bin"), this);
KConfig trashConfig("trashrc", KConfig::SimpleConfig);
emptyTrash->setEnabled(!trashConfig.group("Status").readEntry("Empty", true));
connect(emptyTrash, SIGNAL(triggered()), SLOT(emptyTrashBin()));
KAction *del = new KAction(i18n("&Delete"), this);
del->setIcon(KIcon("edit-delete"));
del->setShortcut(Qt::SHIFT + Qt::Key_Delete);
connect(del, SIGNAL(triggered()), SLOT(deleteSelectedIcons()));
// Create the new menu
m_newMenu = new KNewFileMenu(&m_actionCollection, "new_menu", this);
connect(m_newMenu->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowCreateNew()));
m_actionCollection.addAction("undo", undo);
m_actionCollection.addAction("cut", cut);
m_actionCollection.addAction("copy", copy);
m_actionCollection.addAction("paste", paste);
m_actionCollection.addAction("pasteto", pasteTo);
m_actionCollection.addAction("rename", rename);
m_actionCollection.addAction("trash", trash);
m_actionCollection.addAction("del", del);
m_actionCollection.addAction("empty_trash", emptyTrash);
}
void PopupView::contextMenuRequest(QWidget *widget, const QPoint& screenPos)
{
showContextMenu(widget, screenPos, m_selectionModel->selectedIndexes());
}
void PopupView::showContextMenu(QWidget *widget, const QPoint &screenPos, const QList<QModelIndex> &indexes)
{
Q_UNUSED(widget)
// contextMenuRequest is only called from the icon view, which is created in init()
// which mean m_model should always be initialized
Q_ASSERT(m_model);
if (indexes.isEmpty()) {
return;
}
if (m_actionCollection.isEmpty()) {
createActions();
}
KFileItemList items;
bool hasRemoteFiles = false;
bool isTrashLink = false;
foreach (const QModelIndex &index, m_selectionModel->selectedIndexes()) {
KFileItem item = m_model->itemForIndex(index);
if (!item.isNull()) {
hasRemoteFiles |= item.localPath().isEmpty();
items.append(item);
}
}
// Check if we're showing the menu for the trash link
if (items.count() == 1 && items.at(0).isDesktopFile()) {
KDesktopFile file(items.at(0).localPath());
if (file.readType() == "Link" && file.readUrl() == "trash:/") {
isTrashLink = true;
}
}
QAction *pasteTo = m_actionCollection.action("pasteto");
if (pasteTo) {
if (QAction *paste = m_actionCollection.action("paste")) {
pasteTo->setEnabled(paste->isEnabled());
pasteTo->setText(paste->text());
}
}
QList<QAction*> editActions;
editActions.append(m_actionCollection.action("rename"));
KConfigGroup configGroup(KGlobal::config(), "KDE");
bool showDeleteCommand = configGroup.readEntry("ShowDeleteCommand", false);
// Don't add the "Move to Trash" action if we're showing the menu for the trash link
if (!isTrashLink) {
if (!hasRemoteFiles) {
editActions.append(m_actionCollection.action("trash"));
} else {
showDeleteCommand = true;
}
}
if (showDeleteCommand) {
editActions.append(m_actionCollection.action("del"));
}
KParts::BrowserExtension::ActionGroupMap actionGroups;
actionGroups.insert("editactions", editActions);
KParts::BrowserExtension::PopupFlags flags = KParts::BrowserExtension::ShowProperties;
flags |= KParts::BrowserExtension::ShowUrlOperations;
// m_newMenu can be NULL here but KonqPopupMenu does handle this.
KonqPopupMenu *contextMenu = new KonqPopupMenu(items, m_url, m_actionCollection, m_newMenu,
KonqPopupMenu::ShowNewWindow, flags,
QApplication::desktop(),
KBookmarkManager::userBookmarksManager(),
actionGroups);
connect(contextMenu->fileItemActions(), SIGNAL(openWithDialogAboutToBeShown()), this, SLOT(openWithDialogAboutToShow()));
m_showingMenu = true;
contextMenu->exec(screenPos);
delete contextMenu;
m_showingMenu = false;
if (pasteTo) {
pasteTo->setEnabled(false);
}
if (m_delayedClose) {
m_delayedClose = false;
closeThisAndParentPopup();
}
}
KUrl::List PopupView::selectedUrls() const
{
Q_ASSERT(m_model);
KUrl::List urls;
foreach (const QModelIndex &index, m_selectionModel->selectedIndexes())
{
KFileItem item = m_model->itemForIndex(index);
// Prefer the local URL if there is one, since we can't trash remote URL's
const QString path = item.localPath();
if (!path.isEmpty()) {
urls.append(path);
} else {
urls.append(item.url());
}
}
return urls;
}
void PopupView::cut()
{
QMimeData *mimeData = m_model->mimeData(m_selectionModel->selectedIndexes());
KonqMimeData::addIsCutSelection(mimeData, true);
QApplication::clipboard()->setMimeData(mimeData);
}
void PopupView::copy()
{
QMimeData *mimeData = m_model->mimeData(m_selectionModel->selectedIndexes());
QApplication::clipboard()->setMimeData(mimeData);
}
void PopupView::paste()
{
KonqOperations::doPaste(QApplication::desktop(), m_url);
}
void PopupView::pasteTo()
{
KUrl::List urls = selectedUrls();
Q_ASSERT(urls.count() == 1);
KonqOperations::doPaste(QApplication::desktop(), urls.first());
}
void PopupView::moveToTrash(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
{
Q_UNUSED(buttons)
if (!m_iconView->renameInProgress()) {
KonqOperations::Operation op = (modifiers & Qt::ShiftModifier) ?
KonqOperations::DEL : KonqOperations::TRASH;
KonqOperations::del(QApplication::desktop(), op, selectedUrls());
}
}
void PopupView::deleteSelectedIcons()
{
if (!m_iconView->renameInProgress()) {
KonqOperations::del(QApplication::desktop(), KonqOperations::DEL, selectedUrls());
}
}
void PopupView::renameSelectedIcon()
{
activateWindow();
m_iconView->renameSelectedIcon();
}
void PopupView::activated(const QModelIndex &index)
{
const KFileItem item = m_model->itemForIndex(index);
item.run();
closeThisAndParentPopup();
}
void PopupView::openWithDialogAboutToShow()
{
m_delayedClose = true;
hideThisAndParentPopup();
}
void PopupView::setBusy(bool busy)
{
m_busy = busy;
if (busy && !m_busyWidget) {
QTimer::singleShot(100, this, SLOT(createBusyWidgetIfNeeded()));
} else {
delete m_busyWidget;
m_busyWidget = 0;
}
}
void PopupView::createBusyWidgetIfNeeded()
{
if (m_busy && !m_busyWidget) {
const int size = qMin(width(), height()) * .3;
m_busyWidget = new Plasma::BusyWidget;
m_busyWidget->setGeometry(QStyle::alignedRect(layoutDirection(), Qt::AlignCenter, QSize(size, size), contentsRect()));
m_scene->addItem(m_busyWidget);
}
}
void PopupView::emptyTrashBin()
{
KonqOperations::emptyTrash(QApplication::desktop());
}
void PopupView::undoTextChanged(const QString &text)
{
if (QAction *action = m_actionCollection.action("undo")) {
action->setText(text);
}
}
void PopupView::aboutToShowCreateNew()
{
if (m_newMenu) {
m_newMenu->checkUpToDate();
m_newMenu->setPopupFiles(m_url);
}
}
void PopupView::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event)
m_background->resizeFrame(rect().size());
if (m_view) {
m_view->setGeometry(contentsRect());
}
if (KWindowSystem::compositingActive()) {
Plasma::WindowEffects::enableBlurBehind(winId(), true, m_background->mask());
} else {
setMask(m_background->mask());
}
}
void PopupView::showEvent(QShowEvent *event)
{
Q_UNUSED(event)
DialogShadows::self()->addWindow(this);
}
void PopupView::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
m_background->paintFrame(&p);
}
void PopupView::contextMenuEvent(QContextMenuEvent *event)
{
if (!m_model) {
init();
}
if (m_actionCollection.isEmpty()) {
createActions();
}
KFileItem rootItem = m_model->itemForIndex(QModelIndex());
//The root item is invalid (non-existent)
if (rootItem.isNull()) {
return;
}
QMenu menu;
menu.addAction(m_actionCollection.action("new_menu"));
menu.addSeparator();
menu.addAction(m_actionCollection.action("undo"));
menu.addAction(m_actionCollection.action("paste"));
menu.addSeparator();
// Add an action for opening the folder in the preferred application.
if (!m_itemActions) {
// Create a new KFileItem to prevent the target URL in the root item
// from being used. In this case we want the configured URL instead.
KFileItem item(rootItem.mode(), rootItem.permissions(), m_url);
KFileItemListProperties itemList(KFileItemList() << item);
m_itemActions = new KFileItemActions(this);
m_itemActions->setItemListProperties(itemList);
}
menu.addAction(m_itemActions->preferredOpenWithAction(QString()));
if (m_url.protocol() == "trash") {
menu.addAction(m_actionCollection.action("empty_trash"));
}
m_showingMenu = true;
menu.exec(event->globalPos());
m_showingMenu = false;
}
// This function calls a given method in the parent PopupView, and returns true
// if successful or false otherwise.
bool PopupView::callOnParent(const char *method)
{
// Since the scene is a child of the popup view, we can get to the parent view easily
PopupView *parentView = qobject_cast<PopupView*>(m_parentView->scene()->parent());
if (parentView) {
// We use a delayed call to give enter and leave events time be delivered
QMetaObject::invokeMethod(parentView, method, Qt::QueuedConnection);
return true;
}
return false;
}
void PopupView::maybeClose()
{
if (!underMouse() && !m_showingMenu &&
(!m_iconView || (!m_iconView->isUnderMouse() && !m_iconView->dragInProgress())) &&
!callOnParent("maybeClose") && !m_hideTimer.isActive()) {
m_hideTimer.start(400, this);
}
}
void PopupView::closeThisAndParentPopup() {
hide();
deleteLater();
callOnParent("closeThisAndParentPopup");
}
void PopupView::hideThisAndParentPopup()
{
hide();
callOnParent("hideThisAndParentPopup");
}
void PopupView::cancelHideTimer()
{
m_hideTimer.stop();
// Propagate the call down the chain of popups
callOnParent("cancelHideTimer");
}
void PopupView::enterEvent(QEvent *event)
{
Q_UNUSED(event)
// Make sure that any hide timer down the popup chain is stopped
cancelHideTimer();
}
void PopupView::leaveEvent(QEvent *event)
{
Q_UNUSED(event)
// The popups are normally closed by the icon views that created them
// in response to hover events, but when the cursor leaves a popup and
// enters a widget that isn't an icon view in the popup chain, that
// mechanism doesn't work.
//
// To make sure that the popups are closed when this happens, we call
// maybeClose() which checks if the popup is under the mouse cursor,
// and if it isn't it calls maybeClose() in the next popup in the chain
// and so on. If no popups in the chain is under the mouse cursor,
// the root popup will start the hide timer which will close the whole
// chain when it fires.
if (!m_iconView || !m_iconView->popupVisible()) {
maybeClose();
}
}
void PopupView::dragEnterEvent(QDragEnterEvent *event)
{
m_hideTimer.stop();
callOnParent("cancelHideTimer");
// If the popup is open during a drag and drop operation,
// assume that we accept the mimetype.
event->setAccepted(true);
}
void PopupView::dragLeaveEvent(QDragLeaveEvent *event)
{
if (!m_iconView || !m_iconView->popupVisible()) {
maybeClose();
}
// If the popup is open during a drag and drop operation,
// assume that we accept the mimetype.
event->setAccepted(true);
}
void PopupView::timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_hideTimer.timerId()) {
m_hideTimer.stop();
emit requestClose();
}
}
#include "moc_popupview.cpp"

View file

@ -0,0 +1,133 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef POPUPVIEW_H
#define POPUPVIEW_H
#include <QBasicTimer>
#include <QWidget>
#include <QTime>
#include <KActionCollection>
#include <KUrl>
namespace Plasma {
class FrameSvg;
class BusyWidget;
}
class QGraphicsView;
class QGraphicsScene;
class KDirModel;
class KFileItemDelegate;
class KFilePreviewGenerator;
class KNewFileMenu;
class KFileItemActions;
class QItemSelectionModel;
class QModelIndex;
class ProxyModel;
class IconView;
class PopupView : public QWidget
{
Q_OBJECT
public:
PopupView(const QModelIndex &index, const QPoint &pos,
const bool &showPreview, const QStringList &previewPlugins,
const IconView *parentView);
~PopupView();
void delayedHide();
bool dragInProgress();
static QTime lastOpenCloseTime() { return s_lastOpenClose; }
protected:
void showEvent(QShowEvent *event);
void paintEvent(QPaintEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
void resizeEvent(QResizeEvent *event);
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void timerEvent(QTimerEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
signals:
void requestClose();
private:
void createActions();
bool callOnParent(const char *method);
KUrl::List selectedUrls() const;
void showContextMenu(QWidget *widget, const QPoint &pos, const QList<QModelIndex> &indexes);
private slots:
void init();
void activated(const QModelIndex &index);
void openWithDialogAboutToShow();
void setBusy(bool);
void createBusyWidgetIfNeeded();
void contextMenuRequest(QWidget *widget, const QPoint &screenPos);
void maybeClose();
void closeThisAndParentPopup();
void hideThisAndParentPopup();
void cancelHideTimer();
void aboutToShowCreateNew();
void emptyTrashBin();
void undoTextChanged(const QString &text);
// These slots are for KonqPopupMenu
void cut();
void copy();
void paste();
void pasteTo();
void moveToTrash(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
void deleteSelectedIcons();
void renameSelectedIcon();
private:
Plasma::FrameSvg *m_background;
QGraphicsScene *m_scene;
QGraphicsView *m_view;
const IconView *m_parentView;
Plasma::BusyWidget *m_busyWidget;
IconView *m_iconView;
const ProxyModel *m_parentViewModel;
KDirModel *m_dirModel;
ProxyModel *m_model;
KFileItemDelegate *m_delegate;
QItemSelectionModel *m_selectionModel;
KFilePreviewGenerator *m_previewGenerator;
KUrl m_url;
KActionCollection m_actionCollection;
KNewFileMenu *m_newMenu;
KFileItemActions *m_itemActions;
QBasicTimer m_hideTimer;
bool m_showingMenu;
bool m_showPreview;
bool m_busy;
bool m_delayedClose;
QStringList m_previewPlugins;
static QTime s_lastOpenClose;
};
#endif

View file

@ -0,0 +1,118 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "previewpluginsmodel.h"
#include <QStringList>
#include <KServiceTypeTrader>
static bool lessThan(const KService::Ptr &a, const KService::Ptr &b)
{
return QString::localeAwareCompare(a->name(), b->name()) < 0;
}
PreviewPluginsModel::PreviewPluginsModel(QObject *parent)
: QAbstractListModel(parent)
{
plugins = KServiceTypeTrader::self()->query("ThumbCreator");
checkedRows = QVector<bool>(plugins.size(), false);
// Sort the list alphabetially
qStableSort(plugins.begin(), plugins.end(), lessThan);
}
PreviewPluginsModel::~PreviewPluginsModel()
{
}
Qt::ItemFlags PreviewPluginsModel::flags(const QModelIndex &index) const
{
Q_UNUSED(index)
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
}
QVariant PreviewPluginsModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= plugins.size()) {
return QVariant();
}
switch (role) {
case Qt::DisplayRole:
return plugins.at(index.row())->name();
case Qt::CheckStateRole:
return checkedRows.at(index.row()) ? Qt::Checked : Qt::Unchecked;
}
return QVariant();
}
bool PreviewPluginsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role != Qt::CheckStateRole) {
return false;
}
const Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
if (state == Qt::Checked) {
checkedRows[(index.row())] = true;
} else {
checkedRows[(index.row())] = false;
}
emit dataChanged(index, index);
return true;
}
int PreviewPluginsModel::indexOfPlugin(const QString &name) const
{
for (int i = 0; i < plugins.size(); i++) {
if (plugins.at(i)->desktopEntryName() == name) {
return i;
}
}
return -1;
}
void PreviewPluginsModel::setCheckedPlugins(const QStringList &list)
{
foreach (const QString &name, list) {
const int row = indexOfPlugin(name);
if (row != -1) {
checkedRows[row] = true;
emit dataChanged(index(row, 0), index(row, 0));
}
}
}
QStringList PreviewPluginsModel::checkedPlugins() const
{
QStringList list;
for (int i =0; i < checkedRows.size(); ++i) {
if (checkedRows.at(i)) {
list.append(plugins.at(i)->desktopEntryName());
}
}
return list;
}

View file

@ -0,0 +1,49 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef PREVIEWPLUGINSMODEL_H
#define PREVIEWPLUGINSMODEL_H
#include <QAbstractListModel>
#include <KService>
#include <QVector>
class QStringList;
class PreviewPluginsModel : public QAbstractListModel
{
public:
PreviewPluginsModel(QObject *parent = 0);
virtual ~PreviewPluginsModel();
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
int rowCount(const QModelIndex &parent = QModelIndex()) const { Q_UNUSED(parent) return plugins.size(); }
void setCheckedPlugins(const QStringList &list);
QStringList checkedPlugins() const;
private:
int indexOfPlugin(const QString &name) const;
private:
KService::List plugins;
QVector<bool> checkedRows;
};
#endif

View file

@ -0,0 +1,271 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
* Copyright © 2008 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "proxymodel.h"
#include <KDesktopFile>
#include <KDirModel>
#include <KStringHandler>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <kde_file.h>
ProxyModel::ProxyModel(QObject *parent)
: QSortFilterProxyModel(parent),
m_filterMode(NoFilter),
m_sortDirsFirst(true),
m_parseDesktopFiles(false),
m_patternMatchAll(true)
{
setSupportedDragActions(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction);
}
ProxyModel::~ProxyModel()
{
}
void ProxyModel::setFilterMode(FilterMode filterMode)
{
m_filterMode = filterMode;
invalidateFilter();
}
ProxyModel::FilterMode ProxyModel::filterMode() const
{
return m_filterMode;
}
void ProxyModel::setMimeTypeFilterList(const QStringList &mimeList)
{
m_mimeSet = QSet<QString>::fromList(mimeList);
invalidateFilter();
}
QStringList ProxyModel::mimeTypeFilterList() const
{
return m_mimeSet.toList();
}
void ProxyModel::setFileNameFilter(const QString &pattern)
{
m_pattern = pattern;
m_patternMatchAll = (pattern == "*");
const QStringList patterns = pattern.split(' ');
m_regExps.clear();
foreach (const QString &pattern, patterns) {
QRegExp rx(pattern);
rx.setPatternSyntax(QRegExp::Wildcard);
rx.setCaseSensitivity(Qt::CaseInsensitive);
m_regExps.append(rx);
}
}
QString ProxyModel::fileNameFilter() const
{
return m_pattern;
}
void ProxyModel::setSortDirectoriesFirst(bool enable)
{
m_sortDirsFirst = enable;
}
bool ProxyModel::sortDirectoriesFirst() const
{
return m_sortDirsFirst;
}
void ProxyModel::setParseDesktopFiles(bool enable)
{
m_parseDesktopFiles = enable;
}
bool ProxyModel::parseDesktopFiles() const
{
return m_parseDesktopFiles;
}
QModelIndex ProxyModel::indexForUrl(const KUrl &url) const
{
const KDirModel *dirModel = static_cast<KDirModel*>(sourceModel());
return mapFromSource(dirModel->indexForUrl(url));
}
KFileItem ProxyModel::itemForIndex(const QModelIndex &index) const
{
const KDirModel *dirModel = static_cast<KDirModel*>(sourceModel());
return dirModel->itemForIndex(mapToSource(index));
}
bool ProxyModel::isDir(const QModelIndex &index, const KDirModel *dirModel) const
{
KFileItem item = dirModel->itemForIndex(index);
if (item.isDir()) {
return true;
}
if (m_parseDesktopFiles && item.isDesktopFile()) {
// Check if the desktop file is a link to a directory
KDesktopFile file(item.targetUrl().path());
if (file.readType() == "Link") {
const KUrl url(file.readUrl());
if (url.isLocalFile()) {
KDE_struct_stat buf;
const QString path = url.toLocalFile(KUrl::RemoveTrailingSlash);
if (KDE::stat(path, &buf) == 0) {
return S_ISDIR(buf.st_mode);
}
}
}
}
return false;
}
#include <KDebug>
bool ProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
const KDirModel *dirModel = static_cast<KDirModel*>(sourceModel());
// When sorting by size, folders are compared using the number of items in them,
// so they need to be given precedence over regular files as the comparison criteria is different
if (m_sortDirsFirst || left.column() == KDirModel::Size) {
bool leftIsDir = isDir(left, dirModel);
bool rightIsDir = isDir(right, dirModel);
if (leftIsDir && !rightIsDir) {
return (sortOrder() == Qt::AscendingOrder); // folders > files independent of the sorting order
}
if (!leftIsDir && rightIsDir) {
return (sortOrder() == Qt::DescendingOrder); // same here
}
}
const KFileItem leftItem = dirModel->data(left, KDirModel::FileItemRole).value<KFileItem>();
const KFileItem rightItem = dirModel->data(right, KDirModel::FileItemRole).value<KFileItem>();
const int column = left.column();
int result = 0;
switch (column) {
case KDirModel::Name:
// fall through to the naturalCompare call
break;
case KDirModel::ModifiedTime: {
const KDateTime leftTime = leftItem.time(KFileItem::ModificationTime);
const KDateTime rightTime = rightItem.time(KFileItem::ModificationTime);
if (leftTime < rightTime)
result = -1;
else if (leftTime > rightTime)
result = +1;
break;
}
case KDirModel::Size: {
if (isDir(left, dirModel) && isDir(right, dirModel)) {
const int leftChildCount = dirModel->data(left, KDirModel::ChildCountRole).toInt();
const int rightChildCount = dirModel->data(right, KDirModel::ChildCountRole).toInt();
if (leftChildCount < rightChildCount)
result = -1;
else if (leftChildCount > rightChildCount)
result = +1;
} else {
const KIO::filesize_t leftSize = leftItem.size();
const KIO::filesize_t rightSize = rightItem.size();
if (leftSize < rightSize)
result = -1;
else if (leftSize > rightSize)
result = +1;
}
break;
}
case KDirModel::Type:
// add other sorting modes here
// KDirModel::data(index, Qt::DisplayRole) returns the data in index.column()
result = QString::compare(dirModel->data(left, Qt::DisplayRole).toString(),
dirModel->data(right, Qt::DisplayRole).toString());
break;
}
if (result != 0)
return result < 0;
// The following code is taken from dolphin/src/kfileitemmodel.cpp
// and ensures that the sorting order is always determined
// Copyright (C) 2011 by Peter Penz <peter.penz91@gmail.com>
result = KStringHandler::naturalCompare(leftItem.text(), rightItem.text(), Qt::CaseSensitive);
if (result != 0)
return result < 0;
result = KStringHandler::naturalCompare(leftItem.name(), rightItem.name(), Qt::CaseSensitive);
if (result != 0)
return result < 0;
return QString::compare(leftItem.url().url(), rightItem.url().url(), Qt::CaseSensitive);
}
inline bool ProxyModel::matchMimeType(const KFileItem &item) const
{
if (m_mimeSet.isEmpty()) {
return false;
}
const QString mimeType = item.determineMimeType()->name();
return m_mimeSet.contains(mimeType);
}
inline bool ProxyModel::matchPattern(const KFileItem &item) const
{
if (m_patternMatchAll) {
return true;
}
const QString name = item.name();
QListIterator<QRegExp> i(m_regExps);
while (i.hasNext()) {
if (i.next().exactMatch(name)) {
return true;
}
}
return false;
}
bool ProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
if (m_filterMode == NoFilter) {
return true;
}
const KDirModel *dirModel = static_cast<KDirModel*>(sourceModel());
const KFileItem item = dirModel->itemForIndex(dirModel->index(sourceRow, KDirModel::Name, sourceParent));
if (m_filterMode == FilterShowMatches) {
return (matchPattern(item) && matchMimeType(item));
} else {
return !(matchPattern(item) && matchMimeType(item));
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef PROXYMODEL_H
#define PROXYMODEL_H
#include <QSortFilterProxyModel>
#include <QStringList>
#include <QSet>
#include <QRegExp>
class KDirModel;
class KFileItem;
class KUrl;
class ProxyModel : public QSortFilterProxyModel
{
public:
enum FilterMode {
NoFilter = 0,
FilterShowMatches,
FilterHideMatches
};
ProxyModel(QObject *parent = 0);
~ProxyModel();
void setFilterMode(FilterMode filterMode);
FilterMode filterMode() const;
void setMimeTypeFilterList(const QStringList &mimeList);
QStringList mimeTypeFilterList() const;
void setFileNameFilter(const QString &pattern);
QString fileNameFilter() const;
void setSortDirectoriesFirst(bool enable);
bool sortDirectoriesFirst() const;
void setParseDesktopFiles(bool enable);
bool parseDesktopFiles() const;
QModelIndex indexForUrl(const KUrl &url) const;
KFileItem itemForIndex(const QModelIndex &index) const;
bool isDir(const QModelIndex &index, const KDirModel *dirModel) const;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
bool matchMimeType(const KFileItem &item) const;
bool matchPattern(const KFileItem &item) const;
private:
FilterMode m_filterMode;
QSet<QString> m_mimeSet;
QList<QRegExp> m_regExps;
QString m_pattern;
bool m_sortDirsFirst;
bool m_parseDesktopFiles;
bool m_patternMatchAll;
};
#endif

View file

@ -0,0 +1,101 @@
/*
* Copyright © 2008, 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "style.h"
#include <QPainter>
#include <QStyleOption>
#include <plasma/framesvg.h>
FolderViewStyle::FolderViewStyle()
: QCommonStyle()
{
m_frame = new Plasma::FrameSvg(this);
m_frame->setImagePath("widgets/viewitem");
m_frame->setCacheAllRenderedFrames(true);
m_frame->setElementPrefix("normal");
}
FolderViewStyle::~FolderViewStyle()
{
}
void FolderViewStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
{
switch (element)
{
case PE_PanelItemViewItem:
{
const bool hover = (option->state & State_MouseOver);
const bool selected = (option->state & State_Selected);
if (selected && hover) {
m_frame->setElementPrefix("selected+hover");
} else if (selected) {
m_frame->setElementPrefix("selected");
} else if (hover) {
m_frame->setElementPrefix("hover");
} else {
m_frame->setElementPrefix("normal");
}
if (selected || hover) {
m_frame->resizeFrame(option->rect.size());
m_frame->paintFrame(painter, option->rect.topLeft());
}
break;
}
case PE_FrameFocusRect:
{
//QColor color = option->palette.color(QPalette::Text);
QColor color = Qt::white;
color.setAlphaF(.33);
QColor transparent = color;
transparent.setAlphaF(0);
QLinearGradient g1(0, option->rect.top(), 0, option->rect.bottom());
g1.setColorAt(0, color);
g1.setColorAt(1, transparent);
QLinearGradient g2(option->rect.left(), 0, option->rect.right(), 0);
g2.setColorAt(0, transparent);
g2.setColorAt(.5, color);
g2.setColorAt(1, transparent);
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(QPen(g1, 0));
painter->setBrush(Qt::NoBrush);
painter->drawRoundedRect(QRectF(option->rect).adjusted(.5, .5, -.5, -.5), 2, 2);
painter->setPen(QPen(g2, 0));
painter->drawLine(QLineF(option->rect.left() + 2, option->rect.bottom() + .5,
option->rect.right() - 2, option->rect.bottom() + .5));
painter->restore();
break;
}
default:
return QCommonStyle::drawPrimitive(element, option, painter, widget);
}
}

View file

@ -0,0 +1,44 @@
/*
* Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef STYLE_H
#define STYLE_H
#include <QCommonStyle>
namespace Plasma {
class FrameSvg;
}
// This widget style is used to draw the view item backgrounds
class FolderViewStyle : public QCommonStyle
{
public:
FolderViewStyle();
~FolderViewStyle();
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
private:
mutable Plasma::FrameSvg *m_frame;
};
#endif

View file

@ -0,0 +1,308 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "tooltipwidget.h"
#include "abstractitemview.h"
#include "proxymodel.h"
#include <QApplication>
#include <QGraphicsSceneHoverEvent>
#include <QModelIndex>
#include <KDesktopFile>
#include <KDirModel>
#include <KLocale>
#include <KIO/PreviewJob>
#include <Plasma/ToolTipManager>
#include <cmath>
ToolTipWidget::ToolTipWidget(AbstractItemView *parent)
: QGraphicsWidget(parent), m_view(parent), m_previewJob(0)
{
Plasma::ToolTipManager::self()->registerWidget(this);
}
void ToolTipWidget::updateToolTip(const QModelIndex &index, const QRectF &rect)
{
if (!index.isValid()) {
// Send a fake hover leave event to the widget to trick the tooltip
// manager into doing a delayed hide.
QGraphicsSceneHoverEvent event(QEvent::GraphicsSceneHoverLeave);
QApplication::sendEvent(this, &event);
m_preview = QPixmap();
m_item = KFileItem();
m_index = QModelIndex();
return;
}
setGeometry(rect);
m_item = static_cast<ProxyModel*>(m_view->model())->itemForIndex(index);
m_index = index;
m_preview = QPixmap();
// If a preview job is still running (from a previously hovered item),
// wait 200 ms before starting a new one. This is done to throttle
// the number of preview jobs that are started when the user moves
// the cursor over the icon view.
if (m_previewJob) {
m_previewTimer.start(200, this);
} else {
if (m_previewTimer.isActive()) {
m_previewTimer.stop();
}
startPreviewJob();
}
Plasma::ToolTipManager::self()->show(this);
}
static qreal convertToReal(const QString &string)
{
const int pos = string.indexOf('/');
if (pos != -1) {
const int left = string.left(pos).toInt();
const int right = string.mid(pos + 1).toInt();
return right > 0 ? qreal(left) / qreal(right) : 0.0;
}
return qreal(string.toInt());
}
QString ToolTipWidget::metaInfo() const
{
const QString mimetype = m_item.mimetype();
if (!mimetype.startsWith(QLatin1String("audio/")) &&
!mimetype.startsWith(QLatin1String("image/")) &&
!m_item.mimeTypePtr()->is("application/vnd.oasis.opendocument.text"))
{
return QString();
}
KFileMetaInfo info = m_item.metaInfo(true, KFileMetaInfo::TechnicalInfo | KFileMetaInfo::ContentInfo);
QString text;
if (mimetype.startsWith(QLatin1String("audio/"))) {
// ### Disabled because the strigi ID3 analyzer is broken
#if 0
const QString title = info.item("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#title").value().toString();
const QString artist = info.item("http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#performer").value().toString();
const QString album = info.item("http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#musicAlbum").value().toString();
if (!artist.isEmpty() || !title.isEmpty() || !album.isEmpty()) {
text += "<p><table border='0' cellspacing='0' cellpadding='0'>";
if (!artist.isEmpty()) {
text += QString("<tr><td>") + i18nc("Music", "Artist:") + QString(" </td><td>") + artist + QString("</td></tr>");
}
if (!title.isEmpty()) {
text += QString("<tr><td>") + i18nc("Music", "Title:") + QString(" </td><td>") + title + QString("</td></tr>");
}
if (!album.isEmpty()) {
text += QString("<tr><td>") + i18nc("Music", "Album:") + QString(" </td><td>") + album + QString("</td></tr>");
}
text += "</table>";
}
#endif
} else if (mimetype.startsWith(QLatin1String("image/"))) {
int width = info.item("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#width").value().toInt();
int height = info.item("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#height").value().toInt();
const QString camera = info.item("http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#model").value().toString();
const QString type = info.item("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").value().toString();
QString exposureTime = info.item("http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureTime").value().toString();
QString focalLength = info.item("http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLength").value().toString();
QString focal35mm = info.item("http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLengthIn35mmFilm").value().toString();
QString aperture = info.item("http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#apertureValue").value().toString();
QString iso = info.item("http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#isoSpeedRatings").value().toString();
QString created = info.item("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentCreated").value().toString();
text += "<p><table border='0' cellspacing='0' cellpadding='0'>";
if (width > 0 && height > 0) {
QString size = QString::number(width) + 'x' + QString::number(height);
// Add the megapixel count for photos
if (type == "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#Photo") {
const qreal pixels = qreal(width * height) / 1e6;
size += QString(" (") + ki18n("%1 MPixels").subs(pixels, 0, 'f', 1).toString() + QString(")");
}
text += QString("<tr><td>") + i18n("Size:") + QString(" </td><td>") + size + QString("</td></tr>");
}
if (!camera.isEmpty()) {
text += QString("<tr><td>") + i18n("Camera:") + QString(" </td><td>") + camera + QString("</td></tr>");
}
if (!focalLength.isEmpty()) {
const qreal length = convertToReal(focalLength);
focalLength = i18nc("Length in millimeters", "%1 mm", qRound(length));
if (!focal35mm.isEmpty()) {
const qreal length = convertToReal(focal35mm);
focalLength += QString(" (") + i18nc("In photography", "35 mm equivalent: %1 mm", qRound(length)) + QString(")");
}
text += QString("<tr><td>") + i18nc("On a camera", "Focal Length:") +
QString(" </td><td>") + focalLength + QString("</td></tr>");
}
if (!exposureTime.isEmpty()) {
const qreal time = convertToReal(exposureTime);
if (time < 1.0) {
exposureTime = QString("1/") + QString::number(qRound((1.0 / time)));
} else {
exposureTime = QString::number(time, 'f', 1);
}
text += QString("<tr><td>") + i18nc("On a camera", "Exposure Time:") + QString(" </td><td>") +
i18nc("Fraction of a second, or number of seconds", "%1 s", exposureTime) + QString("</td></tr>");
}
if (!aperture.isEmpty()) {
// Convert the APEX value to the F number
const qreal fnumber = std::sqrt(std::pow(2, convertToReal(aperture)));
aperture = QString("f/") + QString::number(fnumber, 'f', 1);
if (aperture.endsWith(QLatin1String(".0"))) {
aperture = aperture.left(aperture.length() - 2);
}
text += QString("<tr><td>") + i18nc("On a camera", "Aperture:") +
QString(" </td><td>") + aperture + QString("</td></tr>");
}
if (!iso.isEmpty()) {
text += QString("<tr><td>") + i18nc("On a camera", "ISO Speed:") +
QString(" </td><td>") + iso + QString("</td></tr>");
}
if (!created.isEmpty()) {
const QDateTime dateTime = QDateTime::fromString(created, "yyyy:MM:dd HH:mm:ss");
text += QString("<tr><td>") + i18n("Time:") + QString(" </td><td>") +
KGlobal::locale()->formatDateTime(dateTime, KLocale::ShortDate, true) + QString("</td></tr>");
}
text += "</table>";
} else if (m_item.mimeTypePtr()->is("application/vnd.oasis.opendocument.text")) {
int wordCount = info.item("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#wordCount").value().toInt();
int pageCount = info.item("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#pageCount").value().toInt();
const QString str1 = i18ncp("Inserted as %1 in the message below.", "1 page", "%1 pages", pageCount);
const QString str2 = i18ncp("Inserted as %2 in the message below.", "1 word", "%1 words", wordCount);
if (pageCount > 0) {
text += QString("<p>") + i18nc("%1 and %2 are the messages translated above.", "%1, %2.", str1, str2);
}
}
return text;
}
void ToolTipWidget::setContent()
{
Plasma::ToolTipContent content;
content.setMainText(m_index.data(Qt::DisplayRole).toString());
if (m_preview.isNull()) {
content.setImage(qvariant_cast<QIcon>(m_index.data(Qt::DecorationRole)));
} else {
content.setImage(m_preview);
}
QString subText;
if (m_item.isDesktopFile()) {
// Add the comment in the .desktop file to the subtext.
// Note that we don't include the mime type for .desktop files,
// since users will likely be confused about what will happen when
// they click a "Desktop configuration file" on their desktop.
KDesktopFile file(m_item.localPath());
subText = file.readComment();
} else {
if (m_item.isMimeTypeKnown()) {
subText = m_item.mimeComment();
}
if (m_item.isDir()) {
// Include information about the number of files and folders in the directory.
const QVariant value = m_index.data(KDirModel::ChildCountRole);
const int count = value.type() == QVariant::Int ? value.toInt() : KDirModel::ChildCountUnknown;
if (count != KDirModel::ChildCountUnknown) {
subText += QString("<br>") + i18ncp("Items in a folder", "1 item", "%1 items", count);
}
} else {
// File size
if (m_item.isFile()) {
subText += QString("<br>") + KGlobal::locale()->formatByteSize(m_item.size());
}
// Add meta info from the strigi analyzers
subText += metaInfo();
}
}
content.setSubText(subText);
content.setAutohide(false);
Plasma::ToolTipManager::self()->setContent(this, content);
}
void ToolTipWidget::startPreviewJob()
{
QStringList plugins;
plugins << "imagethumbnail" << "jpegthumbnail";
m_previewJob = KIO::filePreview(KFileItemList() << m_item, QSize(256, 256), &plugins);
connect(m_previewJob, SIGNAL(gotPreview(KFileItem,QPixmap)), SLOT(gotPreview(KFileItem,QPixmap)));
connect(m_previewJob, SIGNAL(finished(KJob*)), SLOT(previewJobFinished(KJob*)));
}
void ToolTipWidget::gotPreview(const KFileItem &item, const QPixmap &pixmap)
{
if (item == m_item) {
m_preview = pixmap;
setContent();
} else if (m_item.isNull()) {
m_preview = QPixmap();
}
}
void ToolTipWidget::previewJobFinished(KJob *job)
{
if (job == m_previewJob) {
m_previewJob = 0;
}
}
void ToolTipWidget::toolTipAboutToShow()
{
if (m_index.isValid()) {
setContent();
m_hideTimer.start(10000, this);
} else {
Plasma::ToolTipManager::self()->clearContent(this);
}
}
void ToolTipWidget::timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_previewTimer.timerId()) {
m_previewTimer.stop();
if (m_index.isValid()) {
startPreviewJob();
}
}
if (event->timerId() == m_hideTimer.timerId()) {
m_hideTimer.stop();
Plasma::ToolTipManager::self()->hide(this);
}
}
#include "moc_tooltipwidget.cpp"

View file

@ -0,0 +1,76 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TOOLTIPWIDGET_H
#define TOOLTIPWIDGET_H
#include <QModelIndex>
#include <QBasicTimer>
#include <QGraphicsWidget>
#include <KFileItem>
#include <QPixmap>
namespace KIO {
class PreviewJob;
}
class QModelIndex;
class AbstractItemView;
/**
* This widget registers with the plasma tooltip manager, and is moved around
* in the view and resized to the size of the hovered item, so that the tooltip
* will be positioned correctly when it's shown.
*
* It is also responsible for starting preview jobs and updating the the tooltip
* contents when a preview has been generated.
*
* While the widget is created as a child widget of the view, it is always hidden.
*/
class ToolTipWidget : public QGraphicsWidget
{
Q_OBJECT
public:
ToolTipWidget(AbstractItemView *parent);
void updateToolTip(const QModelIndex &index, const QRectF &rect);
private:
QString metaInfo() const;
void setContent();
void startPreviewJob();
void timerEvent(QTimerEvent *);
private slots:
void gotPreview(const KFileItem &item, const QPixmap &pixmap);
void previewJobFinished(KJob *job);
void toolTipAboutToShow();
private:
AbstractItemView * const m_view;
KIO::PreviewJob *m_previewJob;
KFileItem m_item;
QModelIndex m_index;
QPixmap m_preview;
QBasicTimer m_previewTimer;
QBasicTimer m_hideTimer;
};
#endif