add more spacing
[personal-kdebase.git] / workspace / plasma / applets / icon / icon.cpp
blob96a673684ce5c3bdbd2bde0cfa76d4482a7e5d92
1 /***************************************************************************
2 * Copyright 2007 by Aaron Seigo <aseigo@kde.org *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
20 #include "icon.h"
22 #include <QGraphicsSceneDragDropEvent>
23 #include <QGraphicsSceneMouseEvent>
24 #include <QGraphicsItem>
25 #include <QEvent>
26 #include <QMimeData>
27 #include <QGraphicsLinearLayout>
29 #include <KGlobalSettings>
30 #include <KDebug>
31 #include <KDesktopFile>
32 #include <KIconLoader>
33 #include <KLocale>
34 #include <KMenu>
35 #include <KPropertiesDialog>
36 #include <KRun>
37 #include <KSharedConfig>
38 #include <KShell>
39 #include <KUrl>
40 #include <KWindowSystem>
41 #include <kio/copyjob.h>
42 #include <kio/netaccess.h>
44 #include <Plasma/Theme>
45 #include <Plasma/IconWidget>
46 #include <Plasma/Containment>
47 #include <Plasma/ToolTipManager>
49 IconApplet::IconApplet(QObject *parent, const QVariantList &args)
50 : Plasma::Applet(parent, args),
51 m_icon(0),
52 m_dialog(0)
54 setAcceptDrops(true);
55 setBackgroundHints(NoBackground);
56 setHasConfigurationInterface(true);
57 m_icon = new Plasma::IconWidget(this);
59 if (args.count() > 0) {
60 setUrl(args.value(0).toString());
61 m_icon->setText(m_text);
64 resize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Desktop)));
65 //kDebug() << "sized to:" << geometry();
68 void IconApplet::init()
70 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
71 layout->setContentsMargins(0, 0, 0, 0);
72 layout->setSpacing(0);
74 layout->addItem(m_icon);
76 KConfigGroup cg = config();
78 if (!m_url.isValid()) {
79 setUrl(cg.readEntry("Url", m_url));
81 setDisplayLines(2);
83 registerAsDragHandle(m_icon);
84 Plasma::ToolTipManager::self()->registerWidget(m_icon);
86 setAspectRatioMode(Plasma::ConstrainedSquare);
88 // we do this right away since we may have our config
89 // read shortly by the containment. usually applets don't need
90 // this, but desktop icons requires some hacks.
92 // in particular, if we were created with a url passed into via
93 // the args parameter in the ctor, then there won't be an entry
94 // in our config, and desktop icons support banks on the fact
95 // that there will be
96 cg.writeEntry("Url", m_url);
99 IconApplet::~IconApplet()
101 delete m_dialog;
104 void IconApplet::saveState(KConfigGroup &cg) const
106 cg.writeEntry("Url", m_url);
109 void IconApplet::setUrl(const KUrl& url)
111 m_url = KIO::NetAccess::mostLocalUrl(url, 0);
113 m_mimetype = KMimeType::findByUrl(url);
115 if (m_url.isLocalFile() && KDesktopFile::isDesktopFile(m_url.toLocalFile())) {
116 KDesktopFile f(m_url.toLocalFile());
117 m_text = f.readName();
118 //corrupted desktop file?
119 if (m_text.isNull()) {
120 m_text = m_url.fileName();
122 m_icon->setIcon(f.readIcon());
124 m_genericName = f.readGenericName();
125 } else {
126 m_text = m_url.fileName();
128 if(m_text.isEmpty() && m_url.isLocalFile()) {
129 //handle special case like the / folder
130 m_text = m_url.directory();
131 }else if(m_text.isEmpty()) {
132 //if we can't find a name, at least take the protocol name, like trash, remote etc.
133 m_text = m_url.protocol();
136 m_icon->setIcon(KMimeType::iconNameForUrl(url));
139 if (m_icon->icon().isNull()) {
140 m_icon->setIcon("unknown");
143 kDebug() << "url was" << url << "and is" << m_url;
146 void IconApplet::openUrl()
148 if (m_url.isValid()) {
149 emit releaseVisualFocus();
150 KRun *run = new KRun(m_url, 0);
154 void IconApplet::constraintsEvent(Plasma::Constraints constraints)
156 setBackgroundHints(NoBackground);
158 if (constraints & Plasma::FormFactorConstraint) {
159 disconnect(m_icon, SIGNAL(activated()), this, SLOT(openUrl()));
160 disconnect(m_icon, SIGNAL(clicked()), this, SLOT(openUrl()));
162 if (formFactor() == Plasma::Planar ||
163 formFactor() == Plasma::MediaCenter) {
164 connect(m_icon, SIGNAL(activated()), this, SLOT(openUrl()));
165 m_icon->setText(m_text);
166 //FIXME TOOL TIP MANAGER
167 //m_icon->setToolTip(Plasma::ToolTipData());
168 m_icon->setDrawBackground(true);
169 } else {
170 //in the panel the icon behaves like a button
171 connect(m_icon, SIGNAL(clicked()), this, SLOT(openUrl()));
172 m_icon->setText(QString());
173 Plasma::ToolTipContent data(m_text, m_genericName, m_icon->icon());
174 Plasma::ToolTipManager::self()->setContent(m_icon, data);
175 m_icon->setDrawBackground(false);
180 void IconApplet::showConfigurationInterface()
182 if (m_dialog == 0) {
183 m_dialog = new KPropertiesDialog(m_url, 0 /*no parent widget*/);
184 connect(m_dialog, SIGNAL(applied()), this, SLOT(acceptedPropertiesDialog()));
185 connect(m_dialog, SIGNAL(propertiesClosed()), this, SLOT(propertiesDialogClosed()));
186 m_dialog->setWindowTitle(i18n("%1 Icon Settings", m_url.fileName()));
187 m_dialog->show();
188 } else {
189 KWindowSystem::setOnDesktop(m_dialog->winId(), KWindowSystem::currentDesktop());
190 m_dialog->show();
191 KWindowSystem::activateWindow(m_dialog->winId());
195 void IconApplet::setDisplayLines(int displayLines)
197 if (m_icon) {
198 if (m_icon->numDisplayLines() == displayLines) {
199 return;
201 m_icon->setNumDisplayLines(displayLines);
202 update();
206 int IconApplet::displayLines()
208 if (m_icon) {
209 return m_icon->numDisplayLines();
211 return 0;
214 void IconApplet::acceptedPropertiesDialog()
216 KConfigGroup cg = config();
217 m_url = m_dialog->kurl();
218 cg.writeEntry("Url", m_url);
219 setUrl(m_url);
220 update();
223 void IconApplet::propertiesDialogClosed()
225 m_dialog = 0;
228 void IconApplet::dropEvent(QGraphicsSceneDragDropEvent *event)
230 if (!KUrl::List::canDecode(event->mimeData())) {
231 return;
234 KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
236 if (urls.count() > 0) {
237 event->accept();
238 } else {
239 return;
243 if (m_url.isEmpty()) {
244 setUrl(urls.first());
245 //TODO: why we don't call updateConstraints()?
246 constraintsEvent(Plasma::FormFactorConstraint);
247 } else if (m_url.isLocalFile() &&
248 m_mimetype &&
249 (m_mimetype->is("application/x-executable") ||
250 m_mimetype->is("application/x-shellscript") ||
251 KDesktopFile::isDesktopFile(m_url.toLocalFile()))) {
253 //Parameters
254 QString params;
255 foreach (const KUrl &url, urls) {
256 if (url.isLocalFile()) {
257 params += ' ' + KShell::quoteArg(url.path());
258 } else {
259 params += ' ' + KShell::quoteArg(url.prettyUrl());
263 //Command
264 QString commandStr;
265 //Extract the command from the Desktop file
266 if (KDesktopFile::isDesktopFile(m_url.toLocalFile())) {
267 KDesktopFile f(m_url.toLocalFile());
268 KConfigGroup config = f.desktopGroup();
269 commandStr = config.readPathEntry( "Exec", QString() );
271 if (commandStr.isEmpty()) {
272 QString path = f.readUrl();
273 if (path.isEmpty()) {
274 path = f.readPath();
277 if (path.isEmpty()) {
278 return;
281 KUrl dest(path);
282 KMimeType::Ptr mime = KMimeType::findByUrl(dest);
283 if (m_mimetype->is("inode/directory")) {
284 dropUrls(urls, dest, event->modifiers());
287 } else {
288 //Else just exec the local executable
289 commandStr = KShell::quoteArg(m_url.path());
292 KRun::runCommand(commandStr + ' ' + params, 0);
293 } else if (m_mimetype->is("inode/directory")) {
294 dropUrls(urls, m_url, event->modifiers());
298 QPainterPath IconApplet::shape() const
300 return m_icon->shape();
303 //dropUrls from DolphinDropController
304 void IconApplet::dropUrls(const KUrl::List& urls,
305 const KUrl& destination,
306 Qt::KeyboardModifiers modifier)
308 kDebug() << "Source" << urls;
309 kDebug() << "Destination:" << destination;
311 Qt::DropAction action = Qt::CopyAction;
313 const bool shiftPressed = modifier & Qt::ShiftModifier;
314 const bool controlPressed = modifier & Qt::ControlModifier;
315 const bool altPressed = modifier & Qt::AltModifier;
316 if (shiftPressed && controlPressed) {
317 // shortcut for 'Link Here' is used
318 action = Qt::LinkAction;
319 } else if (shiftPressed) {
320 // shortcut for 'Move Here' is used
321 action = Qt::MoveAction;
322 } else if (controlPressed) {
323 // shortcut for 'Copy Here' is used
324 action = Qt::CopyAction;
325 } else if (altPressed) {
326 // shortcut for 'Link Here' is used
327 action = Qt::LinkAction;
328 } else {
329 // open a context menu which offers the following actions:
330 // - Move Here
331 // - Copy Here
332 // - Link Here
333 // - Cancel
335 KMenu popup(0);
337 QString seq = QKeySequence(Qt::ShiftModifier).toString();
338 seq.chop(1); // chop superfluous '+'
339 QAction* moveAction = popup.addAction(KIcon("go-jump"),
340 i18nc("@action:inmenu",
341 "&Move Here\t<shortcut>%1</shortcut>", seq));
343 seq = QKeySequence(Qt::ControlModifier).toString();
344 seq.chop(1);
345 QAction* copyAction = popup.addAction(KIcon("edit-copy"),
346 i18nc("@action:inmenu",
347 "&Copy Here\t<shortcut>%1</shortcut>", seq));
349 seq = QKeySequence(Qt::ControlModifier + Qt::ShiftModifier).toString();
350 seq.chop(1);
351 QAction* linkAction = popup.addAction(KIcon("insert-link"),
352 i18nc("@action:inmenu",
353 "&Link Here\t<shortcut>%1</shortcut>", seq));
355 popup.addSeparator();
356 popup.addAction(KIcon("process-stop"), i18nc("@action:inmenu", "Cancel"));
358 QAction* activatedAction = popup.exec(QCursor::pos());
359 if (activatedAction == moveAction) {
360 action = Qt::MoveAction;
361 } else if (activatedAction == copyAction) {
362 action = Qt::CopyAction;
363 } else if (activatedAction == linkAction) {
364 action = Qt::LinkAction;
365 } else {
366 return;
370 switch (action) {
371 case Qt::MoveAction:
372 KIO::move(urls, destination);
373 break;
375 case Qt::CopyAction:
376 KIO::copy(urls, destination);
377 break;
379 case Qt::LinkAction:
380 KIO::link(urls, destination);
381 break;
383 default:
384 break;
388 #include "icon.moc"