1
/***************************************************************************
2
* Copyright (C) 2010 - 2011 by Ingomar Wesp <ingomar@wesp.name> *
4
* This program is free software; you can redistribute it and/or modify *
5
* it under the terms of the GNU General Public License as published by *
6
* the Free Software Foundation; either version 2 of the License, or *
7
* (at your option) any later version. *
9
* This program is distributed in the hope that it will be useful, *
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12
* GNU General Public License for more details. *
14
* You should have received a copy of the GNU General Public License *
15
* along with this program; if not, write to the *
16
* Free Software Foundation, Inc., *
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18
***************************************************************************/
19
#include "popuplauncherlist.h"
23
#include <QtCore/QEvent>
24
#include <QtCore/QMimeData>
25
#include <QtCore/QPointer>
26
#include <QtCore/QPointF>
27
#include <QtCore/QRectF>
28
#include <QtCore/QUrl>
29
#include <QtGui/QApplication>
30
#include <QtGui/QBrush>
31
#include <QtGui/QDrag>
32
#include <QtGui/QGraphicsItem>
33
#include <QtGui/QGraphicsLinearLayout>
34
#include <QtGui/QGraphicsSceneDragDropEvent>
35
#include <QtGui/QGraphicsSceneMouseEvent>
36
#include <QtGui/QGraphicsSceneResizeEvent>
37
#include <QtGui/QGraphicsWidget>
38
#include <QtGui/QIcon>
39
#include <QtGui/QPainter>
40
#include <QtGui/QSizePolicy>
41
#include <QtGui/QStyleOptionGraphicsItem>
42
#include <QtGui/QWidget>
46
#include <KIconLoader>
50
#include <Plasma/Plasma>
51
#include <Plasma/IconWidget>
52
#include <Plasma/Theme>
53
#include <Plasma/ToolTipContent>
54
#include <Plasma/ToolTipManager>
60
#include "launcherdata.h"
65
namespace Quicklaunch {
67
class DropMarker : public Launcher {
70
DropMarker(PopupLauncherList *parent)
71
: Launcher(LauncherData(), parent)
79
const QStyleOptionGraphicsItem *option,
82
// This mirrors the behavior of the panel spacer committed by mart
83
// workspace/plasma/desktop/containments/panel/panel.cpp R875513)
84
QColor brushColor(Theme::defaultTheme()->color(Theme::TextColor));
85
brushColor.setAlphaF(0.3);
87
painter->setRenderHint(QPainter::Antialiasing);
88
painter->setPen(Qt::NoPen);
89
painter->setBrush(QBrush(brushColor));
91
painter->drawRoundedRect(contentsRect(), 4, 4);
92
Launcher::paint(painter, option, widget);
96
PopupLauncherList::PopupLauncherList(QGraphicsItem *parent)
98
QGraphicsWidget(parent),
100
m_preferredIconSize(),
102
m_layout(new QGraphicsLinearLayout()),
104
m_dropMarker(new DropMarker(this)),
105
m_dropMarkerIndex(-1),
108
m_layout->setOrientation(Qt::Vertical);
110
m_dropMarker->setOrientation(Qt::Horizontal);
111
m_dropMarker->setNameVisible(true);
112
m_dropMarker->setMaximumHeight(KIconLoader::SizeSmallMedium);
121
void PopupLauncherList::setPreferredIconSize(int size)
123
QSizeF newSize(size, size);
125
if (newSize == m_preferredIconSize) {
129
m_preferredIconSize = newSize;
130
m_dropMarker->setPreferredIconSize(newSize);
132
Q_FOREACH (Launcher *launcher, m_launchers) {
133
launcher->setPreferredIconSize(newSize);
137
m_placeHolder->setPreferredIconSize(newSize);
141
bool PopupLauncherList::locked() const
146
void PopupLauncherList::setLocked(bool enable)
149
setAcceptDrops(!enable);
152
QGraphicsLinearLayout * PopupLauncherList::layout() const
157
int PopupLauncherList::launcherCount() const
159
return m_launchers.size();
162
void PopupLauncherList::clear()
164
while(launcherCount() > 0) {
169
void PopupLauncherList::insert(int index, const LauncherData &launcherData)
171
QList<LauncherData> launcherDataList;
172
launcherDataList.append(launcherData);
173
insert(index, launcherDataList);
176
void PopupLauncherList::insert(int index, const QList<LauncherData> &launcherDataList)
178
if (launcherDataList.size() == 0) {
182
if (m_launchers.size() == 0 && m_placeHolder) {
186
else if (index < 0 || index > m_launchers.size()) {
187
index = m_launchers.size();
190
Q_FOREACH(const LauncherData &launcherData, launcherDataList) {
192
Launcher *launcher = new Launcher(launcherData);
194
launcher->setOrientation(Qt::Horizontal);
195
launcher->setNameVisible(true);
196
launcher->setMaximumHeight(KIconLoader::SizeSmallMedium);
198
if (m_preferredIconSize.isValid()) {
199
launcher->setPreferredIconSize(m_preferredIconSize);
202
launcher->installEventFilter(this);
203
connect(launcher, SIGNAL(clicked()), this, SIGNAL(launcherClicked()));
205
m_launchers.insert(index, launcher);
207
int layoutIndex = index;
209
if (m_dropMarkerIndex != -1) {
210
if (m_dropMarkerIndex <= index) {
217
m_layout->insertItem(layoutIndex, launcher);
222
Q_EMIT launchersChanged();
225
void PopupLauncherList::removeAt(int index)
227
int layoutIndex = index;
229
if (m_dropMarkerIndex != -1) {
230
if (m_dropMarkerIndex <= index) {
237
m_layout->removeAt(layoutIndex);
238
delete m_launchers.takeAt(index);
240
if (m_launchers.size() == 0 && m_dropMarkerIndex == -1) {
244
Q_EMIT launchersChanged();
247
LauncherData PopupLauncherList::launcherAt(int index) const
249
return m_launchers.at(index)->launcherData();
252
int PopupLauncherList::launcherIndexAtPosition(const QPointF& pos) const
254
for (int i = 0; i < m_launchers.size(); i++) {
255
if (m_launchers.at(i)->geometry().contains(pos)) {
262
bool PopupLauncherList::eventFilter(QObject *watched, QEvent *event)
264
Launcher *sourceLauncher =
265
qobject_cast<Launcher*>(watched);
267
// Start of Drag & Drop operations
268
if (sourceLauncher && !m_locked) {
270
if (event->type() == QEvent::GraphicsSceneMousePress) {
272
static_cast<QGraphicsSceneMouseEvent*>(event)->pos();
276
else if (event->type() == QEvent::GraphicsSceneMouseMove) {
278
QGraphicsSceneMouseEvent *mouseEvent =
279
static_cast<QGraphicsSceneMouseEvent*>(event);
281
if ((m_mousePressedPos - mouseEvent->pos()).manhattanLength() >=
282
QApplication::startDragDistance()) {
284
LauncherData sourceData = sourceLauncher->launcherData();
286
QMimeData *mimeData = new QMimeData();
287
sourceData.populateMimeData(mimeData);
289
QPointer<QDrag> drag = new QDrag(mouseEvent->widget());
290
drag->setMimeData(mimeData);
291
drag->setPixmap(sourceLauncher->icon().pixmap(16, 16));
293
int launcherIndex = m_launchers.indexOf(sourceLauncher);
295
removeAt(launcherIndex);
297
Qt::DropAction dropAction = drag->exec();
299
if (dropAction != Qt::MoveAction) {
301
insert(launcherIndex, sourceData);
310
void PopupLauncherList::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
314
Qt::DropAction proposedAction = event->proposedAction();
316
if (proposedAction != Qt::CopyAction && proposedAction != Qt::MoveAction) {
318
Qt::DropActions possibleActions = event->possibleActions();
320
if (possibleActions & Qt::CopyAction) {
321
event->setProposedAction(Qt::CopyAction);
323
else if (possibleActions & Qt::MoveAction) {
324
event->setProposedAction(Qt::MoveAction);
326
event->setAccepted(false);
331
// Initialize drop marker
332
const QMimeData *mimeData = event->mimeData();
334
if (LauncherData::canDecode(mimeData)) {
335
QList<LauncherData> data = LauncherData::fromMimeData(mimeData);
337
if (data.size() > 0) {
339
if (data.size() == 1) {
340
m_dropMarker->setLauncherData(data.at(0));
342
m_dropMarker->setLauncherData(LauncherData());
343
m_dropMarker->setIcon("document-multiple");
345
m_dropMarker->setText(i18n("Multiple items"));
348
if (m_launchers.size() != 0) {
349
m_dropMarkerIndex = determineDropMarkerIndex(
350
mapFromScene(event->scenePos()));
354
m_dropMarkerIndex = 0;
357
m_layout->insertItem(m_dropMarkerIndex, m_dropMarker);
358
m_dropMarker->show();
362
event->setAccepted(false);
366
event->setAccepted(false);
371
void PopupLauncherList::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
373
// DragMoveEvents are always preceded by DragEnterEvents
374
Q_ASSERT(m_dropMarkerIndex != -1);
376
int newDropMarkerIndex =
377
determineDropMarkerIndex(mapFromScene(event->scenePos()));
379
if (newDropMarkerIndex != m_dropMarkerIndex) {
381
m_layout->removeAt(m_dropMarkerIndex);
382
m_layout->insertItem(newDropMarkerIndex, m_dropMarker);
384
m_dropMarkerIndex = newDropMarkerIndex;
388
void PopupLauncherList::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
392
if (m_dropMarkerIndex != -1) {
394
m_dropMarker->hide();
395
m_layout->removeAt(m_dropMarkerIndex);
396
m_dropMarker->setLauncherData(LauncherData());
397
m_dropMarkerIndex = -1;
399
if (m_launchers.size() == 0) {
405
void PopupLauncherList::dropEvent(QGraphicsSceneDragDropEvent *event)
407
int dropIndex = m_dropMarkerIndex;
409
if (dropIndex != -1) {
410
m_dropMarker->hide();
411
m_layout->removeAt(m_dropMarkerIndex);
412
m_dropMarker->setLauncherData(LauncherData());
413
m_dropMarkerIndex = -1;
416
const QMimeData *mimeData = event->mimeData();
418
if (LauncherData::canDecode(mimeData)) {
420
QList<LauncherData> data = LauncherData::fromMimeData(mimeData);
421
insert(dropIndex, data);
427
void PopupLauncherList::onPlaceHolderActivated()
429
Q_ASSERT(m_placeHolder);
430
Plasma::ToolTipManager::self()->show(m_placeHolder);
433
void PopupLauncherList::initPlaceHolder()
435
Q_ASSERT(!m_placeHolder);
437
m_placeHolder = new Plasma::IconWidget(KIcon("fork"), QString(), this);
438
m_placeHolder->setPreferredIconSize(m_dropMarker->preferredIconSize());
440
Plasma::ToolTipContent tcp(
442
i18n("Add launchers by Drag and Drop or by using the context menu."),
443
m_placeHolder->icon());
444
Plasma::ToolTipManager::self()->setContent(m_placeHolder, tcp);
446
connect(m_placeHolder, SIGNAL(activated()), SLOT(onPlaceHolderActivated()));
447
m_layout->addItem(m_placeHolder);
450
void PopupLauncherList::deletePlaceHolder()
452
Q_ASSERT(m_placeHolder);
454
m_layout->removeAt(0);
456
delete m_placeHolder;
460
int PopupLauncherList::determineDropMarkerIndex(const QPointF &localPos) const
466
// Determine the new index of the drop marker.
467
const int itemCount = m_layout->count();
470
while (index + 1 < itemCount && localPos.y() > m_layout->itemAt(index + 1)->geometry().top()) {
477
#include "popuplauncherlist.moc"