2 * Copyright 2007 by Christopher Blauvelt <cblauvelt@gmail.com>
3 * Copyright (C) 2007 Matt Broadstone <mbroadst@kde.org>
4 * Copyright (C) 2007 Matias Costa <m.costacano@gmail.com>
5 * Copyright (C) 2007 Montel Laurent <montel@kde.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Library General Public License version 2,
9 * or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details
16 * You should have received a copy of the GNU Library General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "iconloader.h"
25 #include <QGraphicsScene>
28 #include <KGlobalSettings>
30 #include <KAuthorized>
31 #include <KToggleAction>
32 #include <KConfigGroup>
34 static const int topBorder
= 20;
36 IconLoader::IconLoader(DefaultDesktop
*parent
)
39 m_orientation(Qt::Vertical
),
47 IconLoader::~IconLoader()
51 void IconLoader::init()
55 //load stored settings
56 KConfigGroup
cg(m_desktop
->globalConfig());
57 cg
= KConfigGroup(&cg
, "DesktopIcons");
58 m_showIcons
= cg
.readEntry("showIcons", m_showIcons
);
59 m_gridAlign
= cg
.readEntry("alignToGrid", m_gridAlign
);
60 m_orientation
= (Qt::Orientation
)cg
.readEntry("orientation", (int)m_orientation
);
61 setShowDeviceIcons(cg
.readEntry("enableMedia", m_enableMedia
));
63 setGridSize(QSizeF(150, 125));
65 connect(m_desktop
, SIGNAL(appletRemoved(Plasma::Applet
*)), this, SLOT(appletDeleted(Plasma::Applet
*)));
66 //build list of current icons
67 foreach (Plasma::Applet
* applet
, m_desktop
->applets()) {
68 if (applet
->name() == i18n("Icon")) {
73 //list ~/Desktop and add new applets
74 m_desktopDir
.setAutoUpdate(true);
75 m_desktopDir
.setAutoErrorHandlingEnabled(false, 0);
77 connect(&m_desktopDir
, SIGNAL(newItems(KFileItemList
)), this, SLOT(newItems(KFileItemList
)) );
78 connect(&m_desktopDir
, SIGNAL(deleteItem(KFileItem
)), this, SLOT(deleteItem(KFileItem
)));
80 setShowIcons(m_showIcons
);
83 void IconLoader::setShowDeviceIcons(bool show
)
85 if (m_enableMedia
!= show
) {
91 bool IconLoader::showDeviceIcons() const
96 void IconLoader::reloadConfig()
98 KConfigGroup
cg(m_desktop
->globalConfig());
99 cg
= KConfigGroup(&cg
, "DesktopIcons");
100 setGridAligned(cg
.readEntry("alignToGrid", m_gridAlign
));
101 setShowIcons(cg
.readEntry("showIcons", m_showIcons
));
102 m_orientation
= (Qt::Orientation
)cg
.readEntry("orientation", (int)m_orientation
);
103 setShowDeviceIcons(cg
.readEntry("enableMedia", m_enableMedia
));
106 void IconLoader::createMenu()
108 QAction
* alignHorizontal
= new QAction(i18n("Align Icons Horizontally"), this);
109 connect(alignHorizontal
, SIGNAL(triggered(bool)), this , SLOT(slotAlignHorizontal()));
110 actions
.append(alignHorizontal
);
112 QAction
* alignVertical
= new QAction(i18n("Align Icons Vertically"), this);
113 connect(alignVertical
, SIGNAL(triggered(bool)), this , SLOT(slotAlignVertical()));
114 actions
.append(alignVertical
);
117 QList
<QAction
*> IconLoader::contextActions()
120 return QList
<QAction
*>();
123 if (actions
.isEmpty()) {
130 void IconLoader::slotAlignHorizontal()
132 m_orientation
= Qt::Horizontal
;
136 void IconLoader::slotAlignVertical()
138 m_orientation
= Qt::Vertical
;
142 void IconLoader::configureMedia()
145 if (!m_solidEngine
) {
146 //m_solidEngine = m_desktop->dataEngine("solidnotifierengine");
147 //connect(m_solidEngine, SIGNAL(newSource(const QString&)),
148 // this, SLOT(sourceAdded(const QString&)));
151 } else if (m_solidEngine
) {
153 // remove from the lists and delete
154 foreach (Plasma::Applet
*icon
, m_solidDevices
.values()) {
157 m_solidDevices
.clear();
161 void IconLoader::addIcon(const KUrl
& url
)
165 Plasma::Applet
*newApplet
= m_desktop
->addApplet(QString("icon"),args
,0);
167 //kDebug() << "putting" << url.path() << "into the map";
168 //alignToGrid even if m_alignGrid is not set. Otherwise all the applets appear at point 0,0
169 alignToGrid(newApplet
);
170 m_iconMap
[url
.path()] = newApplet
;
174 void IconLoader::addIcon(Plasma::Applet
*applet
)
176 KConfigGroup cg
= applet
->config();
177 KUrl url
= cg
.readEntry("Url", KUrl());
178 if (!url
.isEmpty()) {
179 m_iconMap
[url
.path()] = applet
;
183 void IconLoader::deleteIcon(const KUrl
& url
)
185 Plasma::Applet
*applet
= m_iconMap
.value(url
.path());
188 m_iconMap
.remove(url
.path());
193 void IconLoader::deleteIcon(Plasma::Applet
*applet
)
195 //we must be careful because this will be entered when the applet is already
196 //in the qobject dtor so we can't invoke any applet methods
197 m_iconMap
.remove(m_iconMap
.key(applet
));
200 void IconLoader::newItems(const KFileItemList
& items
)
206 foreach (KFileItem item
, items
) {
207 //kDebug() << "adding item" << item.url();
208 if (!m_iconMap
.contains(item
.url().path())) {
214 void IconLoader::deleteItem(const KFileItem item
)
216 QString path
= item
.url().path();
217 if (!m_iconMap
.contains(path
)) {
218 //kDebug() << "Icon " << path << " not found." << endl;
221 deleteIcon(item
.url());
224 void IconLoader::appletDeleted(Plasma::Applet
*applet
)
229 void IconLoader::alignIcons()
231 QList
<Plasma::Applet
*> icons
= m_iconMap
.values();
232 if (icons
.count() == 0 || !m_showIcons
) {
236 qreal gridWidth
= gridSize().width();
237 qreal gridHeight
= gridSize().height();
239 QRectF
candidateRect(0, 0, gridWidth
, gridHeight
);
240 QList
<Plasma::Applet
*> placedIcons
;
242 foreach (Plasma::Applet
* icon
, icons
) {
243 candidateRect
= QRectF(QPointF(0.0,0.0),icon
->boundingRect().size());
244 //check if any placed icons intersect with the icon placed at various grid locations
246 candidateRect
= nextFreeRect(candidateRect
, placedIcons
);
247 if (!candidateRect
.isValid()) {
251 //mapToGrid on the center spot to eliminate conversion error
252 setToGrid(icon
, mapToGrid(candidateRect
.topLeft()));
257 QRectF
IconLoader::nextFreeRect(const QRectF itemRect
)
259 return nextFreeRect(itemRect
, m_iconMap
.values());
262 QRectF
IconLoader::nextFreeRect(const QRectF itemRect
, QList
<Plasma::Applet
*> placedItems
)
264 QRectF newRect
= itemRect
;
265 while (intersectsWithItems(newRect
, placedItems
)) {
266 newRect
= advanceAlongGrid(newRect
);
267 if (!availableGeometry().contains(newRect
)) {
268 //we've moved completely off the desktop so we should stop
275 bool IconLoader::intersectsWithItems(const QRectF item
, const QList
<Plasma::Applet
*> &items
) const
277 foreach (Plasma::Applet
* testItem
, items
) {
278 //do not use testItem->sceneBoundingRect(). If the item is not drawn yet a size of
279 //0x0 is returned which breaks the algorithm
280 if (item
.intersects(QRectF(testItem
->scenePos(), testItem
->size()))) {
287 QRectF
IconLoader::advanceAlongGrid(QRectF rect
)
289 QRectF newRect
= rect
;
290 qreal gridWidth
= m_gridSize
.width();
291 qreal gridHeight
= m_gridSize
.height();
293 if (m_orientation
== Qt::Horizontal
) {
294 newRect
.translate(gridWidth
,0);
296 newRect
.translate(0, gridHeight
);
298 if (!availableGeometry().contains(newRect
)) {
299 //we've moved off of the desktop and need to move back
300 if (m_orientation
== Qt::Horizontal
) {
301 newRect
.moveTo(0,newRect
.y()+gridHeight
);
303 newRect
.moveTo(newRect
.x()+gridWidth
,0);
309 void IconLoader::setToGrid(Plasma::Applet
* icon
, const QPoint p
)
311 //place the center of the icon in the center of the grid if it's smaller than the grid square
312 QPointF newPos
= mapFromGrid(p
);
313 if (m_gridSize
.width() > icon
->boundingRect().width()) {
314 newPos
.setX(newPos
.x() + (m_gridSize
.width()/2 - icon
->boundingRect().width()/2));
316 if (m_gridSize
.height() > icon
->boundingRect().height()) {
317 newPos
.setY(newPos
.y() + topBorder
);
319 icon
->setPos(newPos
);
322 bool IconLoader::isGridAligned() const
327 void IconLoader::setGridAligned(bool align
)
329 // if icon alignment is false now and we change
330 // to true then align all icons
331 if (!m_gridAlign
&& align
) {
332 foreach (Plasma::Applet
*applet
, m_iconMap
.values()) {
333 alignToGrid(applet
,mapToGrid(applet
->scenePos()));
339 void IconLoader::alignToGrid(Plasma::Applet
*item
)
341 QRectF freeRect
= nextFreeRect(QRectF(QPointF(0.0,0.0),item
->boundingRect().size()));
342 QPoint currentGridPos
= mapToGrid(freeRect
.topLeft());
343 alignToGrid(item
, currentGridPos
);
346 void IconLoader::alignToGrid(Plasma::Applet
*item
, const QPoint
&pos
, bool moveIntersectingItems
)
348 if (moveIntersectingItems
) {
351 setToGrid(item
, pos
);
355 QSizeF
IconLoader::gridSize() const
360 QSize
IconLoader::gridDimensions() const
362 QSizeF thisSize
= m_desktop
->contentSizeHint();
363 return QSize( int(thisSize
.width() / m_gridSize
.width()),
364 int(thisSize
.height() / m_gridSize
.height()) );
367 void IconLoader::setGridSize(const QSizeF
& gridSize
)
369 QSizeF desktopSize
= m_desktop
->contentSizeHint();
370 qreal bestMatchWidth
= desktopSize
.width()
371 / qRound(desktopSize
.width()/gridSize
.width());
372 qreal bestMatchHeight
= desktopSize
.height()
373 / qRound(desktopSize
.height()/gridSize
.height());
374 m_gridSize
= QSizeF(bestMatchWidth
, bestMatchHeight
);
376 foreach (Plasma::Applet
*item
, m_iconMap
.values()) {
382 bool IconLoader::showIcons() const
387 void IconLoader::setShowIcons(bool iconsVisible
)
389 m_showIcons
= iconsVisible
;
391 m_desktopDir
.openUrl(KGlobalSettings::desktopPath());
394 QString desktopDir
= KGlobalSettings::desktopPath();
395 foreach (Plasma::Applet
*icon
, m_iconMap
.values()) {
396 KConfigGroup cg
= icon
->config();
397 KUrl url
= cg
.readEntry("Url", KUrl());
399 //kDebug() << "checking" << url.path() << "against" << desktopDir;
400 if (url
.path().startsWith(desktopDir
)) {
401 icon
->destroy(); //the icon will be taken out of m_iconMap by the appletDeleted Slot
407 void IconLoader::sourceAdded(const QString
&source
)
410 kDebug() << "Not yet implemented.";
413 void IconLoader::sourceDeleted(const QString
&source
)
416 kDebug() << "Not yet implemented.";
419 #include "iconloader.moc"