2 * Copyright © 2008 Fredrik Höglund <fredrik@kde.org>
3 * Copyright © 2008 Rafael Fernández López <ereslibre@kde.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
21 #include "folderview.h"
23 #include <QApplication>
26 #include <QDesktopServices>
28 #include <QGraphicsLinearLayout>
29 #include <QGraphicsView>
30 #include <QGraphicsSceneDragDropEvent>
31 #include <QItemSelectionModel>
35 #include <KAuthorized>
36 #include <KBookmarkManager>
37 #include <KConfigDialog>
38 #include <KDesktopFile>
40 #include <KFileItemDelegate>
41 #include <kfileplacesmodel.h>
42 #include <kfilepreviewgenerator.h>
43 #include <KGlobalSettings>
45 #include <KStandardShortcut>
46 #include <KStringHandler>
48 #include <kio/fileundomanager.h>
49 #include <kio/paste.h>
50 #include <KParts/BrowserExtension>
53 #include <konqmimedata.h>
54 #include <konq_operations.h>
55 #include <konq_popupmenu.h>
59 #include "plasma/corona.h"
60 #include "plasma/paintutils.h"
61 #include "plasma/theme.h"
62 #include "plasma/tooltipmanager.h"
64 #include "dirlister.h"
66 #include "folderviewadapter.h"
68 #include "iconwidget.h"
70 #include "previewpluginsmodel.h"
71 #include "proxymodel.h"
75 K_EXPORT_PLASMA_APPLET(folderview
, FolderView
)
77 MimeModel::MimeModel(QObject
*parent
)
78 : QStringListModel(parent
)
80 m_mimetypes
= KMimeType::allMimeTypes();
83 QVariant
MimeModel::data(const QModelIndex
&index
, int role
) const
85 if (!index
.isValid()) {
88 KMimeType
*mime
= static_cast<KMimeType
*>(index
.internalPointer());
90 case Qt::DisplayRole
: {
91 if (!mime
->comment().isEmpty()) {
93 if (mime
->patterns().count()) {
94 description
= mime
->patterns().join(", ");
96 description
= mime
->name();
98 return QString("%1 (%2)").arg(mime
->comment()).arg(description
);
103 case Qt::DecorationRole
:
104 return KIcon(mime
->iconName());
105 case Qt::CheckStateRole
:
106 return m_state
[mime
];
108 return QStringListModel::data(index
, role
);
112 Qt::ItemFlags
MimeModel::flags(const QModelIndex
&index
) const
114 Qt::ItemFlags itemFlags
= QStringListModel::flags(index
);
115 itemFlags
&= ~Qt::ItemIsEditable
;
116 if (!index
.isValid()) {
119 return itemFlags
| Qt::ItemIsUserCheckable
;
122 QModelIndex
MimeModel::index(int row
, int column
, const QModelIndex
&parent
) const
124 if (parent
.isValid() || row
>= m_mimetypes
.count()) {
125 return QModelIndex();
127 return createIndex(row
, column
, (void*) m_mimetypes
[row
].data());
130 int MimeModel::rowCount(const QModelIndex
&parent
) const
132 if (parent
.isValid()) {
135 return m_mimetypes
.count();
138 bool MimeModel::setData(const QModelIndex
&index
, const QVariant
&value
, int role
)
140 if (!index
.isValid()) {
144 if (role
== Qt::CheckStateRole
) {
145 KMimeType
*mime
= static_cast<KMimeType
*>(index
.internalPointer());
146 m_state
[mime
] = (Qt::CheckState
) value
.toInt();
147 emit
dataChanged(index
, index
);
151 return QStringListModel::setData(index
, value
, role
);
156 // ---------------------------------------------------------------------------
160 ProxyMimeModel::ProxyMimeModel(QObject
*parent
)
161 : QSortFilterProxyModel(parent
)
165 void ProxyMimeModel::setSourceModel(QAbstractItemModel
*sourceModel
)
167 QSortFilterProxyModel::setSourceModel(sourceModel
);
171 void ProxyMimeModel::setFilter(const QString
&filter
)
177 bool ProxyMimeModel::lessThan(const QModelIndex
&left
, const QModelIndex
&right
) const
179 KMimeType
*leftPtr
= static_cast<KMimeType
*>(left
.internalPointer());
180 KMimeType
*rightPtr
= static_cast<KMimeType
*>(right
.internalPointer());
182 return KStringHandler::naturalCompare(leftPtr
->comment(), rightPtr
->comment()) < 0;
185 bool ProxyMimeModel::filterAcceptsRow(int source_row
, const QModelIndex
&source_parent
) const
187 QModelIndex sourceIndex
= sourceModel()->index(source_row
, 0, source_parent
);
188 KMimeType
*mime
= static_cast<KMimeType
*>(sourceIndex
.internalPointer());
189 if (m_filter
.isEmpty()) {
193 bool fastRet
= mime
->comment().contains(m_filter
, Qt::CaseInsensitive
) ||
194 ((!mime
->patterns().count() || mime
->comment().isEmpty()) && mime
->name().contains(m_filter
, Qt::CaseInsensitive
));
200 foreach (const QString
&pattern
, mime
->patterns()) {
201 if (pattern
.contains(m_filter
, Qt::CaseInsensitive
)) {
211 // ---------------------------------------------------------------------------
215 // Proxy model for KFilePlacesModel that filters out hidden items.
216 class PlacesFilterModel
: public QSortFilterProxyModel
219 PlacesFilterModel(QObject
*parent
= 0) : QSortFilterProxyModel(parent
) {}
220 bool filterAcceptsRow(int row
, const QModelIndex
&parent
) const {
221 KFilePlacesModel
*model
= static_cast<KFilePlacesModel
*>(sourceModel());
222 const QModelIndex index
= model
->index(row
, 0, parent
);
223 return !model
->isHidden(index
);
229 // ---------------------------------------------------------------------------
233 FolderView::FolderView(QObject
*parent
, const QVariantList
&args
)
234 : Plasma::Containment(parent
, args
),
235 m_previewGenerator(0),
243 m_actionCollection(this)
245 setContainmentType(DesktopContainment
);
246 setAspectRatioMode(Plasma::IgnoreAspectRatio
);
247 setHasConfigurationInterface(true);
248 setAcceptHoverEvents(true);
249 setAcceptDrops(true);
251 m_dirModel
= new KDirModel(this);
252 m_dirModel
->setDropsAllowed(KDirModel::DropOnDirectory
| KDirModel::DropOnLocalExecutable
);
254 m_model
= new ProxyModel(this);
255 m_model
->setSourceModel(m_dirModel
);
256 m_model
->setSortLocaleAware(true);
257 m_model
->setFilterCaseSensitivity(Qt::CaseInsensitive
);
259 m_delegate
= new KFileItemDelegate(this);
260 m_selectionModel
= new QItemSelectionModel(m_model
, this);
262 if (args
.count() > 0) {
263 setUrl(KUrl(args
.value(0).toString()));
268 // As we use some part of konqueror libkonq must be added to have translations
269 KGlobal::locale()->insertCatalog("libkonq");
272 void FolderView::init()
276 // Find out about icon and font settings changes
277 connect(KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()), SLOT(fontSettingsChanged()));
278 connect(KGlobalSettings::self(), SIGNAL(iconChanged(int)), SLOT(iconSettingsChanged(int)));
280 // Find out about theme changes
281 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(themeChanged()));
283 // Find out about network availability changes
284 connect(Solid::Networking::notifier(), SIGNAL(statusChanged(Solid::Networking::Status
)),
285 SLOT(networkStatusChanged(Solid::Networking::Status
)));
287 KConfigGroup cg
= config();
288 m_customLabel
= cg
.readEntry("customLabel", "");
289 m_customIconSize
= cg
.readEntry("customIconSize", 0);
290 m_showPreviews
= cg
.readEntry("showPreviews", true);
291 m_drawShadows
= cg
.readEntry("drawShadows", true);
292 m_numTextLines
= cg
.readEntry("numTextLines", 2);
293 m_textColor
= cg
.readEntry("textColor", QColor(Qt::transparent
));
294 m_iconsLocked
= cg
.readEntry("iconsLocked", false);
295 m_alignToGrid
= cg
.readEntry("alignToGrid", false);
296 m_previewPlugins
= cg
.readEntry("previewPlugins", QStringList() << "imagethumbnail" << "jpegthumbnail");
297 m_sortDirsFirst
= cg
.readEntry("sortDirsFirst", true);
298 m_sortColumn
= cg
.readEntry("sortColumn", int(KDirModel::Name
));
299 m_filterFiles
= cg
.readEntry("filterFiles", "*");
300 m_filterType
= cg
.readEntry("filter", 0);
301 m_filterFilesMimeList
= cg
.readEntry("mimeFilter", QStringList());
303 m_flow
= isContainment() ? QListView::TopToBottom
: QListView::LeftToRight
;
304 m_flow
= static_cast<QListView::Flow
>(cg
.readEntry("flow", static_cast<int>(m_flow
)));
306 m_model
->setFilterMode(ProxyModel::filterModeFromInt(m_filterType
));
307 m_model
->setMimeTypeFilterList(m_filterFilesMimeList
);
308 m_model
->setFilterFixedString(m_filterFiles
);
309 m_model
->setSortDirectoriesFirst(m_sortDirsFirst
);
310 m_model
->sort(m_sortColumn
!= -1 ? m_sortColumn
: KDirModel::Name
, Qt::AscendingOrder
);
312 DirLister
*lister
= new DirLister(this);
313 lister
->setDelayedMimeTypes(true);
314 lister
->setAutoErrorHandlingEnabled(false, 0);
316 m_dirModel
->setDirLister(lister
);
318 if (!m_url
.isValid()) {
320 //FIXME: 4.3 Need to update folderview's description
321 QString path
= QDir::homePath();
322 if (isContainment()) {
323 QString desktopPath
= KGlobalSettings::desktopPath();
324 QDir
desktopFolder(desktopPath
);
326 if (desktopPath
!= QDir::homePath() && desktopFolder
.exists()) {
327 path
= QString("desktop:/");
330 setUrl(cg
.readEntry("url", KUrl(path
)));
333 KConfigGroup cg
= config();
334 cg
.writeEntry("url", m_url
);
337 // TODO: 4.3 Check if the URL is a remote URL, and if it is check the network status
338 // and display a message saying it's not available, instead of trying to open
339 // the URL and waiting for the job to time out.
340 lister
->openUrl(m_url
);
342 if (isContainment()) {
348 if (isContainment()) {
350 // Set a low Z value so applets don't end up below the icon view
351 m_iconView
->setZValue(INT_MIN
);
354 connect(QApplication::clipboard(), SIGNAL(dataChanged()), SLOT(clipboardDataChanged()));
357 FolderView::~FolderView()
362 void FolderView::saveState(KConfigGroup
&config
) const
368 void FolderView::createConfigurationInterface(KConfigDialog
*parent
)
370 QWidget
*widgetFilter
= new QWidget
;
371 QWidget
*widgetDisplay
= new QWidget
;
372 QWidget
*widgetLocation
= new QWidget
;
373 uiFilter
.setupUi(widgetFilter
);
374 uiDisplay
.setupUi(widgetDisplay
);
375 uiLocation
.setupUi(widgetLocation
);
377 if (!m_placesModel
) {
378 m_placesModel
= new KFilePlacesModel(this);
381 PlacesFilterModel
*placesFilter
= new PlacesFilterModel(parent
);
382 placesFilter
->setSourceModel(m_placesModel
);
383 uiLocation
.placesCombo
->setModel(placesFilter
);
385 QString desktopPath
= KGlobalSettings::desktopPath();
386 QDir
desktopFolder(desktopPath
);
388 bool desktopVisible
= desktopPath
!= QDir::homePath() && desktopFolder
.exists();
389 uiLocation
.showDesktopFolder
->setVisible(desktopVisible
);
391 if (desktopVisible
&& m_url
== KUrl("desktop:/")) {
392 uiLocation
.showDesktopFolder
->setChecked(true);
393 uiLocation
.placesCombo
->setEnabled(false);
394 uiLocation
.lineEdit
->setEnabled(false);
397 for (int i
= 0; i
< placesFilter
->rowCount(); i
++) {
398 KUrl url
= m_placesModel
->url(placesFilter
->mapToSource(placesFilter
->index(i
, 0)));
399 if (url
.equals(m_url
, KUrl::CompareWithoutTrailingSlash
)) {
400 index
= placesFilter
->index(i
, 0);
404 if (index
.isValid()) {
405 uiLocation
.placesCombo
->setCurrentIndex(index
.row());
406 uiLocation
.showPlace
->setChecked(true);
407 uiLocation
.lineEdit
->setEnabled(false);
409 uiLocation
.showCustomFolder
->setChecked(true);
410 uiLocation
.lineEdit
->setUrl(m_url
);
411 uiLocation
.placesCombo
->setEnabled(false);
415 uiLocation
.lineEdit
->setMode(KFile::Directory
);
416 uiFilter
.filterFilesPattern
->setText(m_filterFiles
);
418 MimeModel
*mimeModel
= new MimeModel(uiFilter
.filterFilesList
);
419 ProxyMimeModel
*pMimeModel
= new ProxyMimeModel(uiFilter
.filterFilesList
);
420 pMimeModel
->setSourceModel(mimeModel
);
421 uiFilter
.filterFilesList
->setModel(pMimeModel
);
423 // The label is not shown when the applet is acting as a containment,
424 // so don't confuse the user by making it editable.
425 if (isContainment()) {
426 uiDisplay
.lblCustomLabel
->hide();
427 uiDisplay
.labelEdit
->hide();
430 uiDisplay
.labelEdit
->setText(m_titleText
);
432 const QList
<int> iconSizes
= QList
<int>() << 16 << 22 << 32 << 48 << 64 << 128;
433 uiDisplay
.sizeSlider
->setRange(0, iconSizes
.size() - 1);
434 uiDisplay
.sizeSlider
->setValue(iconSizes
.indexOf(iconSize().width()));
436 uiDisplay
.sortCombo
->addItem(i18nc("Sort Icons", "Unsorted"), -1);
437 uiDisplay
.sortCombo
->addItem(m_actionCollection
.action("sort_name")->text(), KDirModel::Name
);
438 uiDisplay
.sortCombo
->addItem(m_actionCollection
.action("sort_size")->text(), KDirModel::Size
);
439 uiDisplay
.sortCombo
->addItem(m_actionCollection
.action("sort_type")->text(), KDirModel::Type
);
440 uiDisplay
.sortCombo
->addItem(m_actionCollection
.action("sort_date")->text(), KDirModel::ModifiedTime
);
442 uiDisplay
.flowCombo
->addItem(i18n("Top to Bottom"), QListView::TopToBottom
);
443 uiDisplay
.flowCombo
->addItem(i18n("Left to Right"), QListView::LeftToRight
);
445 uiDisplay
.alignToGrid
->setChecked(m_alignToGrid
);
446 uiDisplay
.lockInPlace
->setChecked(m_iconsLocked
);
447 uiDisplay
.drawShadows
->setChecked(m_drawShadows
);
448 uiDisplay
.showPreviews
->setChecked(m_showPreviews
);
449 uiDisplay
.previewsAdvanced
->setEnabled(m_showPreviews
);
450 uiDisplay
.numLinesEdit
->setValue(m_numTextLines
);
452 if (m_textColor
!= Qt::transparent
) {
453 uiDisplay
.colorButton
->setColor(m_textColor
);
455 uiDisplay
.colorButton
->setColor(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
));
458 for (int i
= 0; i
< uiDisplay
.sortCombo
->maxCount(); i
++) {
459 if (m_sortColumn
== uiDisplay
.sortCombo
->itemData(i
).toInt()) {
460 uiDisplay
.sortCombo
->setCurrentIndex(i
);
465 for (int i
= 0; i
< uiDisplay
.flowCombo
->maxCount(); i
++) {
466 if (m_flow
== uiDisplay
.flowCombo
->itemData(i
).toInt()) {
467 uiDisplay
.flowCombo
->setCurrentIndex(i
);
472 // Hide the icon arrangement controls when we're not acting as a containment,
473 // since this option doesn't make much sense in the applet.
474 if (!isContainment()) {
475 uiDisplay
.flowLabel
->hide();
476 uiDisplay
.flowCombo
->hide();
479 connect(uiFilter
.searchMimetype
, SIGNAL(textChanged(QString
)), pMimeModel
, SLOT(setFilter(QString
)));
481 parent
->addPage(widgetLocation
, i18nc("Title of the page that lets the user choose which location should the folderview show", "Location"), "folder");
482 parent
->addPage(widgetDisplay
, i18nc("Title of the page that lets the user choose how the folderview should be shown", "Display"), "preferences-desktop-display");
483 parent
->addPage(widgetFilter
, i18nc("Title of the page that lets the user choose how to filter the folderview contents", "Filter"), "view-filter");
484 parent
->setButtons(KDialog::Ok
| KDialog::Cancel
| KDialog::Apply
);
486 connect(parent
, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
487 connect(parent
, SIGNAL(okClicked()), this, SLOT(configAccepted()));
488 connect(uiLocation
.showPlace
, SIGNAL(toggled(bool)), uiLocation
.placesCombo
, SLOT(setEnabled(bool)));
489 connect(uiLocation
.showCustomFolder
, SIGNAL(toggled(bool)), uiLocation
.lineEdit
, SLOT(setEnabled(bool)));
490 connect(uiFilter
.filterType
, SIGNAL(currentIndexChanged(int)), this, SLOT(filterChanged(int)));
491 connect(uiFilter
.selectAll
, SIGNAL(clicked(bool)), this, SLOT(selectUnselectAll()));
492 connect(uiFilter
.deselectAll
, SIGNAL(clicked(bool)), this, SLOT(selectUnselectAll()));
493 connect(uiDisplay
.previewsAdvanced
, SIGNAL(clicked()), this, SLOT(showPreviewConfigDialog()));
494 connect(uiDisplay
.showPreviews
, SIGNAL(toggled(bool)), uiDisplay
.previewsAdvanced
, SLOT(setEnabled(bool)));
496 KConfigGroup cg
= config();
497 int filter
= cg
.readEntry("filter", 0);
498 uiFilter
.filterType
->setCurrentIndex(filter
);
499 filterChanged(filter
);
501 QStringList selectedItems
= cg
.readEntry("mimeFilter", QStringList());
503 if (selectedItems
.count()) {
504 for (int i
= 0; i
< pMimeModel
->rowCount(); i
++) {
505 const QModelIndex index
= pMimeModel
->index(i
, 0);
506 const KMimeType
*mime
= static_cast<KMimeType
*>(pMimeModel
->mapToSource(index
).internalPointer());
507 if (selectedItems
.contains(mime
->name())) {
508 selectedItems
.removeAll(mime
->name());
509 uiFilter
.filterFilesList
->model()->setData(index
, Qt::Checked
, Qt::CheckStateRole
);
515 void FolderView::configAccepted()
519 if (uiLocation
.showDesktopFolder
->isChecked()) {
520 url
= KUrl("desktop:/");
521 } else if (uiLocation
.showPlace
->isChecked()) {
522 PlacesFilterModel
*filter
= static_cast<PlacesFilterModel
*>(uiLocation
.placesCombo
->model());
523 KFilePlacesModel
*model
= static_cast<KFilePlacesModel
*>(filter
->sourceModel());
524 url
= model
->url(filter
->mapToSource(filter
->index(uiLocation
.placesCombo
->currentIndex(), 0)));
526 url
= uiLocation
.lineEdit
->url();
530 url
= KUrl(QDir::homePath());
533 // Now, we have to iterate over all items (not only the filtered ones). For that reason we have
534 // to ask the source model, not the proxy model.
535 QStringList selectedItems
;
536 ProxyMimeModel
*proxyModel
= static_cast<ProxyMimeModel
*>(uiFilter
.filterFilesList
->model());
537 for (int i
= 0; i
< proxyModel
->sourceModel()->rowCount(); i
++) {
538 const QModelIndex index
= proxyModel
->sourceModel()->index(i
, 0);
539 if (index
.model()->data(index
, Qt::CheckStateRole
).toInt() == Qt::Checked
) {
540 selectedItems
<< static_cast<KMimeType
*>(index
.internalPointer())->name();
544 int filterType
= uiFilter
.filterType
->currentIndex();
545 KConfigGroup cg
= config();
546 bool needReload
= false;
548 if (m_drawShadows
!= uiDisplay
.drawShadows
->isChecked()) {
549 m_drawShadows
= uiDisplay
.drawShadows
->isChecked();
550 cg
.writeEntry("drawShadows", m_drawShadows
);
553 if (m_showPreviews
!= uiDisplay
.showPreviews
->isChecked() ||
554 (m_previewGenerator
&& m_previewPlugins
!= m_previewGenerator
->enabledPlugins()))
556 m_showPreviews
= uiDisplay
.showPreviews
->isChecked();
557 cg
.writeEntry("showPreviews", m_showPreviews
);
558 cg
.writeEntry("previewPlugins", m_previewPlugins
);
560 m_previewGenerator
->setEnabledPlugins(m_previewPlugins
);
561 m_previewGenerator
->setPreviewShown(m_showPreviews
);
565 const QColor color
= uiDisplay
.colorButton
->color();
566 if ((m_textColor
!= Qt::transparent
&& color
!= m_textColor
) ||
567 (m_textColor
== Qt::transparent
&& color
!= Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
)))
570 cg
.writeEntry("textColor", m_textColor
);
573 if (m_numTextLines
!= uiDisplay
.numLinesEdit
->value()) {
574 m_numTextLines
= uiDisplay
.numLinesEdit
->value();
575 cg
.writeEntry("numTextLines", m_numTextLines
);
578 const QList
<int> iconSizes
= QList
<int>() << 16 << 22 << 32 << 48 << 64 << 128;
579 int size
= iconSizes
.at(uiDisplay
.sizeSlider
->value());
580 if (size
!= iconSize().width())
582 m_customIconSize
= size
;
583 cg
.writeEntry("customIconSize", m_customIconSize
);
585 // This is to force the preview images to be regenerated with the new size
586 if (m_showPreviews
) {
591 int sortColumn
= uiDisplay
.sortCombo
->itemData(uiDisplay
.sortCombo
->currentIndex()).toInt();
592 if (m_sortColumn
!= sortColumn
) {
593 m_sortColumn
= sortColumn
;
594 if (m_sortColumn
!= -1) {
595 m_model
->invalidate();
596 m_model
->sort(m_sortColumn
, Qt::AscendingOrder
);
598 updateSortActionsState();
599 cg
.writeEntry("sortColumn", m_sortColumn
);
602 int flow
= uiDisplay
.flowCombo
->itemData(uiDisplay
.flowCombo
->currentIndex()).toInt();
603 if (m_flow
!= flow
) {
604 m_flow
= static_cast<QListView::Flow
>(flow
);
605 cg
.writeEntry("flow", flow
);
608 if (m_alignToGrid
!= uiDisplay
.alignToGrid
->isChecked()) {
609 m_alignToGrid
= uiDisplay
.alignToGrid
->isChecked();
610 cg
.writeEntry("alignToGrid", m_alignToGrid
);
611 m_actionCollection
.action("auto_align")->setChecked(m_alignToGrid
);
614 if (m_iconsLocked
!= uiDisplay
.lockInPlace
->isChecked()) {
615 m_iconsLocked
= uiDisplay
.lockInPlace
->isChecked();
616 cg
.writeEntry("iconsLocked", m_iconsLocked
);
617 m_actionCollection
.action("lock_icons")->setChecked(m_iconsLocked
);
620 const QString label
= uiDisplay
.labelEdit
->text();
621 if ((m_customLabel
.isEmpty() && label
!= m_titleText
) ||
622 (!m_customLabel
.isEmpty() && label
!= m_customLabel
))
624 m_customLabel
= label
;
626 cg
.writeEntry("customLabel", m_customLabel
);
629 if (m_url
!= url
|| m_filterFiles
!= uiFilter
.filterFilesPattern
->text() ||
630 m_filterFilesMimeList
!= selectedItems
|| m_filterType
!= filterType
)
632 m_model
->setFilterFixedString(uiFilter
.filterFilesPattern
->text());
633 m_filterFiles
= uiFilter
.filterFilesPattern
->text();
634 m_filterFilesMimeList
= selectedItems
;
635 m_filterType
= filterType
;
638 cg
.writeEntry("url", m_url
);
639 cg
.writeEntry("filterFiles", m_filterFiles
);
640 cg
.writeEntry("filter", m_filterType
);
641 cg
.writeEntry("mimeFilter", m_filterFilesMimeList
);
643 m_model
->setMimeTypeFilterList(m_filterFilesMimeList
);
644 m_model
->setFilterMode(ProxyModel::filterModeFromInt(m_filterType
));
649 updateIconViewState();
653 updateListViewState();
657 m_dirModel
->dirLister()->openUrl(m_url
);
660 m_delayedSaveTimer
.start(5000, this);
661 emit
configNeedsSaving();
664 void FolderView::showPreviewConfigDialog()
666 QWidget
*widget
= new QWidget
;
667 uiPreviewConfig
.setupUi(widget
);
669 PreviewPluginsModel
*model
= new PreviewPluginsModel(this);
670 model
->setCheckedPlugins(m_previewPlugins
);
672 uiPreviewConfig
.listView
->setModel(model
);
674 KDialog
*dialog
= new KDialog
;
675 dialog
->setMainWidget(widget
);
677 if (dialog
->exec() == KDialog::Accepted
) {
678 m_previewPlugins
= model
->checkedPlugins();
686 void FolderView::updateListViewState()
688 QPalette palette
= m_listView
->palette();
689 palette
.setColor(QPalette::Text
, m_textColor
!= Qt::transparent
? m_textColor
:
690 Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
));
691 m_listView
->setPalette(palette
);
693 const QFont font
= Plasma::Theme::defaultTheme()->font(Plasma::Theme::DesktopFont
);
694 if (m_listView
->font() != font
) {
695 m_listView
->setFont(font
);
697 m_listView
->setDrawShadows(m_drawShadows
);
698 m_listView
->setIconSize(iconSize());
699 m_listView
->setWordWrap(m_numTextLines
> 1);
702 void FolderView::updateIconViewState()
704 QPalette palette
= m_iconView
->palette();
705 palette
.setColor(QPalette::Text
, m_textColor
!= Qt::transparent
? m_textColor
:
706 Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
));
707 m_iconView
->setPalette(palette
);
709 m_iconView
->setDrawShadows(m_drawShadows
);
710 m_iconView
->setIconSize(iconSize());
711 m_iconView
->setGridSize(gridSize());
712 m_iconView
->setFlow(m_flow
);
713 m_iconView
->setWordWrap(m_numTextLines
> 1);
714 m_iconView
->setAlignToGrid(m_alignToGrid
);
715 m_iconView
->setIconsMoveable(!m_iconsLocked
);
718 m_label
->setPalette(palette
);
719 m_label
->setDrawShadow(m_drawShadows
);
723 void FolderView::setupIconView()
729 m_iconView
= new IconView(this);
730 m_iconView
->setModel(m_model
);
731 m_iconView
->setItemDelegate(m_delegate
);
732 m_iconView
->setSelectionModel(m_selectionModel
);
733 m_iconView
->setFont(Plasma::Theme::defaultTheme()->font(Plasma::Theme::DesktopFont
));
735 if (!isContainment()) {
736 m_label
= new Label(this);
737 m_label
->setText(m_titleText
);
740 updateIconViewState();
742 const QStringList data
= config().readEntry("savedPositions", QStringList());
743 m_iconView
->setIconPositionsData(data
);
745 connect(m_iconView
, SIGNAL(activated(QModelIndex
)), SLOT(activated(QModelIndex
)));
746 connect(m_iconView
, SIGNAL(indexesMoved(QModelIndexList
)), SLOT(indexesMoved(QModelIndexList
)));
747 connect(m_iconView
, SIGNAL(contextMenuRequest(QWidget
*,QPoint
)), SLOT(contextMenuRequest(QWidget
*,QPoint
)));
748 connect(m_iconView
, SIGNAL(busy(bool)), SLOT(setBusy(bool)));
750 FolderViewAdapter
*adapter
= new FolderViewAdapter(m_iconView
);
751 m_previewGenerator
= new KFilePreviewGenerator(adapter
, m_model
);
752 m_previewGenerator
->setPreviewShown(m_showPreviews
);
753 m_previewGenerator
->setEnabledPlugins(m_previewPlugins
);
755 QGraphicsLinearLayout
*layout
= new QGraphicsLinearLayout(Qt::Vertical
, this);
756 layout
->setContentsMargins(0, 0, 0, 0);
757 layout
->setSpacing(0);
759 layout
->addItem(m_label
);
761 layout
->addItem(m_iconView
);
766 void FolderView::fontSettingsChanged()
768 const QFont font
= Plasma::Theme::defaultTheme()->font(Plasma::Theme::DesktopFont
);
770 if (m_iconView
&& m_iconView
->font() != font
) {
771 m_iconView
->setFont(font
);
772 m_iconView
->setGridSize(gridSize());
775 if (m_label
&& m_label
->font() != font
) {
776 m_label
->setFont(font
);
780 void FolderView::iconSettingsChanged(int group
)
782 if (group
== KIconLoader::Desktop
&& m_iconView
)
784 const int size
= (m_customIconSize
!= 0) ?
785 m_customIconSize
: KIconLoader::global()->currentSize(KIconLoader::Desktop
);
787 m_iconView
->setIconSize(QSize(size
, size
));
789 else if (group
== KIconLoader::Panel
&& m_listView
)
791 const int size
= (m_customIconSize
!= 0) ?
792 m_customIconSize
: KIconLoader::global()->currentSize(KIconLoader::Panel
);
794 m_listView
->setIconSize(QSize(size
, size
));
798 void FolderView::themeChanged()
800 if (m_textColor
!= Qt::transparent
) {
805 QPalette palette
= m_iconView
->palette();
806 palette
.setColor(QPalette::Text
, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
));
807 m_iconView
->setPalette(palette
);
811 updateListViewState();
815 QPalette palette
= m_label
->palette();
816 palette
.setColor(QPalette::Text
, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
));
817 m_label
->setPalette(palette
);
821 void FolderView::networkStatusChanged(Solid::Networking::Status status
)
823 if (status
== Solid::Networking::Connected
&& !m_url
.isLocalFile() &&
824 m_url
.protocol() != "desktop") {
829 void FolderView::clipboardDataChanged()
831 const QMimeData
*mimeData
= QApplication::clipboard()->mimeData();
832 if (KonqMimeData::decodeIsCutSelection(mimeData
)) {
833 KUrl::List urls
= KUrl::List::fromMimeData(mimeData
);
835 // TODO Mark the cut icons as cut
838 // Update the paste action
839 if (QAction
*action
= m_actionCollection
.action("paste"))
841 const QString actionText
= KIO::pasteActionText();
842 if (!actionText
.isEmpty()) {
843 action
->setText(actionText
);
844 action
->setEnabled(true);
846 action
->setText(i18n("&Paste"));
847 action
->setEnabled(false);
852 void FolderView::saveIconPositions() const
858 const QStringList data
= m_iconView
->iconPositionsData();
859 if (!data
.isEmpty()) {
860 config().writeEntry("savedPositions", data
);
862 config().deleteEntry("savedPositions");
866 void FolderView::paintInterface(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
, const QRect
&contentRect
)
870 Q_UNUSED(contentRect
)
873 void FolderView::constraintsEvent(Plasma::Constraints constraints
)
875 if (constraints
& Plasma::FormFactorConstraint
) {
876 if (isContainment()) {
877 setBackgroundHints(Applet::NoBackground
);
878 } else if (formFactor() == Plasma::Planar
|| formFactor() == Plasma::MediaCenter
) {
879 setBackgroundHints(Applet::TranslucentBackground
);
882 if (formFactor() == Plasma::Planar
|| formFactor() == Plasma::MediaCenter
) {
883 // Clean up the icon widget
885 disconnect(m_dirModel
->dirLister(), SIGNAL(newItems(KFileItemList
)), this, SLOT(updateIconWidget()));
886 disconnect(m_dirModel
->dirLister(), SIGNAL(itemsDeleted(KFileItemList
)), this, SLOT(updateIconWidget()));
887 disconnect(m_dirModel
->dirLister(), SIGNAL(clear()), this, SLOT(updateIconWidget()));
895 if (!isContainment()) {
896 // Give the applet a sane size
899 setAspectRatioMode(Plasma::IgnoreAspectRatio
);
901 // Clean up the icon view
907 // Set up the icon widget
908 m_iconWidget
= new IconWidget(this);
909 m_iconWidget
->setModel(m_dirModel
);
910 m_iconWidget
->setIcon(m_icon
.isNull() ? KIcon("user-folder") : m_icon
);
911 connect(m_iconWidget
, SIGNAL(clicked()), SLOT(iconWidgetClicked()));
915 // We need to update the tooltip (and maybe the icon) when the contents of the folder changes
916 connect(m_dirModel
->dirLister(), SIGNAL(newItems(KFileItemList
)), SLOT(updateIconWidget()));
917 connect(m_dirModel
->dirLister(), SIGNAL(itemsDeleted(KFileItemList
)), SLOT(updateIconWidget()));
918 connect(m_dirModel
->dirLister(), SIGNAL(clear()), SLOT(updateIconWidget()));
920 m_listView
= new ListView
;
921 m_listView
->setItemDelegate(m_delegate
);
922 m_listView
->setModel(m_model
);
923 m_listView
->setSelectionModel(m_selectionModel
);
925 connect(m_listView
, SIGNAL(activated(QModelIndex
)), SLOT(activated(QModelIndex
)));
926 connect(m_listView
, SIGNAL(contextMenuRequest(QWidget
*,QPoint
)), SLOT(contextMenuRequest(QWidget
*,QPoint
)));
928 FolderViewAdapter
*adapter
= new FolderViewAdapter(m_listView
);
929 m_previewGenerator
= new KFilePreviewGenerator(adapter
, m_model
);
930 m_previewGenerator
->setPreviewShown(m_showPreviews
);
931 m_previewGenerator
->setEnabledPlugins(m_previewPlugins
);
933 updateListViewState();
935 m_dialog
= new Dialog
;
936 m_dialog
->setGraphicsWidget(m_listView
); // Ownership is transferred to the scene in the dialog
938 QGraphicsLinearLayout
*layout
= new QGraphicsLinearLayout(Qt::Vertical
, this);
939 layout
->setContentsMargins(0, 0, 0, 0);
940 layout
->setSpacing(0);
941 layout
->addItem(m_iconWidget
);
944 setAspectRatioMode(Plasma::ConstrainedSquare
);
948 if (constraints
& Plasma::ScreenConstraint
) {
949 Plasma::Corona
*c
= corona();
950 disconnect(c
, SIGNAL(availableScreenRegionChanged()), this, SLOT(updateScreenRegion()));
951 if (isContainment()) {
953 updateScreenRegion();
954 connect(c
, SIGNAL(availableScreenRegionChanged()), this, SLOT(updateScreenRegion()));
956 m_iconView
->setContentsMargins(0, 0, 0, 0);
962 void FolderView::updateScreenRegion()
964 Plasma::Corona
*c
= corona();
970 QRect availRect
= c
->availableScreenRegion(screen()).boundingRect();
971 QRect screenRect
= c
->screenGeometry(screen());
972 m_iconView
->setContentsMargins(availRect
.x() - screenRect
.x(),
973 availRect
.y() - screenRect
.y(),
974 screenRect
.right() - availRect
.right(),
975 screenRect
.bottom() - availRect
.bottom());
978 void FolderView::mousePressEvent(QGraphicsSceneMouseEvent
*event
)
980 if (isContainment() && event
->widget()->window()->inherits("DashboardView")) {
981 emit
releaseVisualFocus();
985 Containment::mousePressEvent(event
);
988 void FolderView::dragEnterEvent(QGraphicsSceneDragDropEvent
*event
)
990 const QString appletMimeType
= static_cast<Plasma::Corona
*>(scene())->appletMimeType();
991 event
->setAccepted(isContainment() && immutability() == Plasma::Mutable
&&
992 event
->mimeData()->hasFormat(appletMimeType
));
995 void FolderView::dragMoveEvent(QGraphicsSceneDragDropEvent
*event
)
997 const QString appletMimeType
= static_cast<Plasma::Corona
*>(scene())->appletMimeType();
998 event
->setAccepted(isContainment() && event
->mimeData()->hasFormat(appletMimeType
));
1001 void FolderView::dropEvent(QGraphicsSceneDragDropEvent
*event
)
1003 const QString appletMimeType
= static_cast<Plasma::Corona
*>(scene())->appletMimeType();
1004 if (isContainment() && event
->mimeData()->hasFormat(appletMimeType
)) {
1005 Containment::dropEvent(event
);
1009 void FolderView::setUrl(const KUrl
&url
)
1013 if (!m_customLabel
.isEmpty()) {
1014 m_titleText
= m_customLabel
;
1015 } else if (m_url
== KUrl("desktop:/")) {
1016 m_titleText
= i18n("Desktop Folder");
1018 m_titleText
= m_url
.pathOrUrl();
1020 if (!m_placesModel
) {
1021 m_placesModel
= new KFilePlacesModel(this);
1023 const QModelIndex index
= m_placesModel
->closestItem(url
);
1024 if (index
.isValid()) {
1025 m_titleText
= m_titleText
.right(m_titleText
.length() - m_placesModel
->url(index
).pathOrUrl().length());
1027 if (!m_titleText
.isEmpty()) {
1028 if (m_titleText
.at(0) == '/') {
1029 m_titleText
.remove(0, 1);
1032 if (layoutDirection() == Qt::RightToLeft
) {
1033 m_titleText
.prepend(" < ");
1035 m_titleText
.prepend(" > ");
1039 m_titleText
.prepend(m_placesModel
->text(index
));
1044 m_label
->setText(m_titleText
);
1050 void FolderView::createActions()
1052 KIO::FileUndoManager
*manager
= KIO::FileUndoManager::self();
1054 // Remove the Shift+Delete shortcut from the cut action, since it's used for deleting files
1055 KAction
*cut
= KStandardAction::cut(this, SLOT(cut()), this);
1056 KShortcut cutShortCut
= cut
->shortcut();
1057 cutShortCut
.remove(Qt::SHIFT
+ Qt::Key_Delete
);
1058 cut
->setShortcut(cutShortCut
);
1060 KAction
*copy
= KStandardAction::copy(this, SLOT(copy()), this);
1062 KAction
*undo
= KStandardAction::undo(manager
, SLOT(undo()), this);
1063 connect(manager
, SIGNAL(undoAvailable(bool)), undo
, SLOT(setEnabled(bool)));
1064 connect(manager
, SIGNAL(undoTextChanged(QString
)), SLOT(undoTextChanged(QString
)));
1065 undo
->setEnabled(manager
->undoAvailable());
1067 KAction
*paste
= KStandardAction::paste(this, SLOT(paste()), this);
1068 KAction
*pasteTo
= KStandardAction::paste(this, SLOT(pasteTo()), this);
1069 pasteTo
->setEnabled(false); // Only enabled during popupMenu()
1071 QString actionText
= KIO::pasteActionText();
1072 if (!actionText
.isEmpty()) {
1073 paste
->setText(actionText
);
1075 paste
->setEnabled(false);
1078 KAction
*reload
= new KAction(i18n("&Reload"), this);
1079 connect(reload
, SIGNAL(triggered()), SLOT(refreshIcons()));
1081 KAction
*refresh
= new KAction(isContainment() ? i18n("&Refresh Desktop") : i18n("&Refresh View"), this);
1082 refresh
->setShortcut(KStandardShortcut::reload());
1083 if (isContainment()) {
1084 refresh
->setIcon(KIcon("user-desktop"));
1086 connect(refresh
, SIGNAL(triggered()), SLOT(refreshIcons()));
1088 KAction
*rename
= new KAction(KIcon("edit-rename"), i18n("&Rename"), this);
1089 rename
->setShortcut(Qt::Key_F2
);
1090 connect(rename
, SIGNAL(triggered()), SLOT(renameSelectedIcon()));
1092 KAction
*trash
= new KAction(KIcon("user-trash"), i18n("&Move to Trash"), this);
1093 trash
->setShortcut(Qt::Key_Delete
);
1094 connect(trash
, SIGNAL(triggered(Qt::MouseButtons
, Qt::KeyboardModifiers
)),
1095 SLOT(moveToTrash(Qt::MouseButtons
, Qt::KeyboardModifiers
)));
1097 KAction
*del
= new KAction(i18n("&Delete"), this);
1098 del
->setIcon(KIcon("edit-delete"));
1099 del
->setShortcut(Qt::SHIFT
+ Qt::Key_Delete
);
1100 connect(del
, SIGNAL(triggered()), SLOT(deleteSelectedIcons()));
1102 m_actionCollection
.addAction("cut", cut
);
1103 m_actionCollection
.addAction("undo", undo
);
1104 m_actionCollection
.addAction("copy", copy
);
1105 m_actionCollection
.addAction("paste", paste
);
1106 m_actionCollection
.addAction("pasteto", pasteTo
);
1107 m_actionCollection
.addAction("reload", reload
);
1108 m_actionCollection
.addAction("refresh", refresh
);
1109 m_actionCollection
.addAction("rename", rename
);
1110 m_actionCollection
.addAction("trash", trash
);
1111 m_actionCollection
.addAction("del", del
);
1113 if (KAuthorized::authorize("editable_desktop_icons")) {
1114 KAction
*alignToGrid
= new KAction(i18n("Align to Grid"), this);
1115 alignToGrid
->setCheckable(true);
1116 alignToGrid
->setChecked(m_alignToGrid
);
1117 connect(alignToGrid
, SIGNAL(toggled(bool)), SLOT(toggleAlignToGrid(bool)));
1119 KAction
*lockIcons
= new KAction(i18nc("Icons on the desktop", "Lock in Place"), this);
1120 lockIcons
->setCheckable(true);
1121 lockIcons
->setChecked(m_iconsLocked
);
1122 connect(lockIcons
, SIGNAL(toggled(bool)), SLOT(toggleIconsLocked(bool)));
1124 m_sortingGroup
= new QActionGroup(this);
1125 connect(m_sortingGroup
, SIGNAL(triggered(QAction
*)), SLOT(sortingChanged(QAction
*)));
1126 QAction
*sortByName
= m_sortingGroup
->addAction(i18nc("Sort icons", "By Name"));
1127 QAction
*sortBySize
= m_sortingGroup
->addAction(i18nc("Sort icons", "By Size"));
1128 QAction
*sortByType
= m_sortingGroup
->addAction(i18nc("Sort icons", "By Type"));
1129 QAction
*sortByDate
= m_sortingGroup
->addAction(i18nc("Sort icons", "By Date"));
1131 sortByName
->setCheckable(true);
1132 sortByName
->setData(int(KDirModel::Name
));
1134 sortBySize
->setCheckable(true);
1135 sortBySize
->setData(int(KDirModel::Size
));
1137 sortByType
->setCheckable(true);
1138 sortByType
->setData(int(KDirModel::Type
));
1140 sortByDate
->setCheckable(true);
1141 sortByDate
->setData(int(KDirModel::ModifiedTime
));
1143 KAction
*dirsFirst
= new KAction(i18nc("Sort icons", "Folders First"), this);
1144 dirsFirst
->setCheckable(true);
1145 dirsFirst
->setChecked(m_sortDirsFirst
);
1146 connect(dirsFirst
, SIGNAL(toggled(bool)), SLOT(toggleDirectoriesFirst(bool)));
1148 QMenu
*sortMenu
= new QMenu(i18n("Sort Icons"));
1149 sortMenu
->addAction(sortByName
);
1150 sortMenu
->addAction(sortBySize
);
1151 sortMenu
->addAction(sortByType
);
1152 sortMenu
->addAction(sortByDate
);
1153 sortMenu
->addSeparator();
1154 sortMenu
->addAction(dirsFirst
);
1156 QMenu
*iconsMenu
= new QMenu
;
1157 iconsMenu
->addMenu(sortMenu
);
1158 iconsMenu
->addSeparator();
1159 iconsMenu
->addAction(alignToGrid
);
1160 iconsMenu
->addAction(lockIcons
);
1162 QAction
*iconsMenuAction
= new KAction(i18n("Icons"), this);
1163 iconsMenuAction
->setIcon(KIcon("preferences-desktop-icons"));
1164 iconsMenuAction
->setMenu(iconsMenu
);
1166 // Create the new menu
1167 m_newMenu
= new KNewMenu(&m_actionCollection
, view(), "new_menu");
1168 connect(m_newMenu
->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowCreateNew()));
1170 m_actionCollection
.addAction("lock_icons", lockIcons
);
1171 m_actionCollection
.addAction("auto_align", alignToGrid
);
1172 m_actionCollection
.addAction("icons_menu", iconsMenuAction
);
1173 m_actionCollection
.addAction("sort_name", sortByName
);
1174 m_actionCollection
.addAction("sort_size", sortBySize
);
1175 m_actionCollection
.addAction("sort_type", sortByType
);
1176 m_actionCollection
.addAction("sort_date", sortByDate
);
1178 updateSortActionsState();
1181 // Note: We have to create our own action collection, because the one Plasma::Applet
1182 // provides can only be manipulated indirectly, and we need to be able to pass
1183 // a pointer to the collection to KNewMenu and KonqPopupMenu.
1184 // But we still have to add all the actions to the collection in Plasma::Applet
1185 // in order for the shortcuts to work.
1186 addAction("cut", cut
);
1187 addAction("undo", undo
);
1188 addAction("copy", copy
);
1189 addAction("paste", paste
);
1190 addAction("reload", reload
);
1191 addAction("rename", rename
);
1192 addAction("trash", trash
);
1193 addAction("del", del
);
1196 QList
<QAction
*> FolderView::contextualActions()
1198 QList
<QAction
*> actions
;
1200 if (KAuthorized::authorize("action/kdesktop_rmb"))
1202 if (QAction
*action
= m_actionCollection
.action("new_menu")) {
1203 actions
.append(action
);
1204 QAction
*separator
= new QAction(this);
1205 separator
->setSeparator(true);
1206 actions
.append(separator
);
1209 actions
.append(m_actionCollection
.action("undo"));
1210 actions
.append(m_actionCollection
.action("paste"));
1212 QAction
*separator
= new QAction(this);
1213 separator
->setSeparator(true);
1214 actions
.append(separator
);
1217 if (QAction
*iconsMenu
= m_actionCollection
.action("icons_menu")) {
1218 actions
.append(iconsMenu
);
1222 actions
.append(m_actionCollection
.action("refresh"));
1224 separator
= new QAction(this);
1225 separator
->setSeparator(true);
1226 actions
.append(separator
);
1232 void FolderView::aboutToShowCreateNew()
1235 m_newMenu
->slotCheckUpToDate();
1236 m_newMenu
->setPopupFiles(m_url
);
1240 KUrl::List
FolderView::selectedUrls() const
1243 foreach (const QModelIndex
&index
, m_selectionModel
->selectedIndexes())
1245 KFileItem item
= m_model
->itemForIndex(index
);
1246 // Prefer the local URL if there is one, since we can't trash remote URL's
1247 const QString path
= item
.localPath();
1248 if (!path
.isEmpty()) {
1251 urls
.append(item
.url());
1257 void FolderView::copy()
1259 QMimeData
*mimeData
= m_model
->mimeData(m_selectionModel
->selectedIndexes());
1260 QApplication::clipboard()->setMimeData(mimeData
);
1263 void FolderView::cut()
1265 QMimeData
*mimeData
= m_model
->mimeData(m_selectionModel
->selectedIndexes());
1266 KonqMimeData::addIsCutSelection(mimeData
, true);
1267 QApplication::clipboard()->setMimeData(mimeData
);
1270 void FolderView::paste()
1272 KonqOperations::doPaste(view(), m_url
);
1275 void FolderView::pasteTo()
1277 KUrl::List urls
= selectedUrls();
1278 Q_ASSERT(urls
.count() == 1);
1279 KonqOperations::doPaste(view(), urls
.first());
1282 void FolderView::refreshIcons()
1284 m_dirModel
->dirLister()->updateDirectory(m_url
);
1287 void FolderView::toggleIconsLocked(bool locked
)
1289 m_iconsLocked
= locked
;
1292 m_iconView
->setIconsMoveable(!locked
);
1295 config().writeEntry("iconsLocked", locked
);
1296 emit
configNeedsSaving();
1299 void FolderView::toggleAlignToGrid(bool align
)
1301 m_alignToGrid
= align
;
1304 m_iconView
->setAlignToGrid(align
);
1307 config().writeEntry("alignToGrid", align
);
1308 emit
configNeedsSaving();
1310 m_delayedSaveTimer
.start(5000, this);
1313 void FolderView::toggleDirectoriesFirst(bool enable
)
1315 m_sortDirsFirst
= enable
;
1317 m_model
->setSortDirectoriesFirst(m_sortDirsFirst
);
1318 if (m_sortColumn
!= -1) {
1319 m_model
->invalidate();
1320 m_delayedSaveTimer
.start(5000, this);
1323 config().writeEntry("sortDirsFirst", m_sortDirsFirst
);
1324 emit
configNeedsSaving();
1327 void FolderView::sortingChanged(QAction
*action
)
1329 int column
= action
->data().toInt();
1331 if (column
!= m_sortColumn
) {
1332 m_model
->invalidate();
1333 m_model
->sort(column
, Qt::AscendingOrder
);
1334 m_sortColumn
= column
;
1335 config().writeEntry("sortColumn", m_sortColumn
);
1336 emit
configNeedsSaving();
1337 m_delayedSaveTimer
.start(5000, this);
1341 void FolderView::updateSortActionsState()
1343 foreach (QAction
*action
, m_sortingGroup
->actions()) {
1344 action
->setChecked(action
->data() == int(m_sortColumn
));
1349 void FolderView::filterChanged(int index
)
1351 uiFilter
.filterFilesPattern
->setEnabled(index
!= 0);
1352 uiFilter
.searchMimetype
->setEnabled(index
!= 0);
1353 uiFilter
.filterFilesList
->setEnabled(index
!= 0);
1354 uiFilter
.selectAll
->setEnabled(index
!= 0);
1355 uiFilter
.deselectAll
->setEnabled(index
!= 0);
1358 void FolderView::selectUnselectAll()
1360 Qt::CheckState state
= sender() == uiFilter
.selectAll
? Qt::Checked
: Qt::Unchecked
;
1361 for (int i
= 0; i
< uiFilter
.filterFilesList
->model()->rowCount(); i
++) {
1362 const QModelIndex index
= uiFilter
.filterFilesList
->model()->index(i
, 0);
1363 uiFilter
.filterFilesList
->model()->setData(index
, state
, Qt::CheckStateRole
);
1367 void FolderView::moveToTrash(Qt::MouseButtons buttons
, Qt::KeyboardModifiers modifiers
)
1370 if (m_iconView
&& m_iconView
->renameInProgress()) {
1374 KonqOperations::Operation op
= (modifiers
& Qt::ShiftModifier
) ?
1375 KonqOperations::DEL
: KonqOperations::TRASH
;
1377 KonqOperations::del(view(), op
, selectedUrls());
1380 void FolderView::deleteSelectedIcons()
1382 if (m_iconView
&& m_iconView
->renameInProgress()) {
1386 KonqOperations::del(view(), KonqOperations::DEL
, selectedUrls());
1389 void FolderView::renameSelectedIcon()
1392 m_iconView
->renameSelectedIcon();
1396 void FolderView::undoTextChanged(const QString
&text
)
1398 if (QAction
*action
= m_actionCollection
.action("undo")) {
1399 action
->setText(text
);
1403 void FolderView::activated(const QModelIndex
&index
)
1405 const KFileItem item
= m_model
->itemForIndex(index
);
1408 if (m_dialog
&& m_dialog
->isVisible()) {
1412 emit
releaseVisualFocus();
1415 void FolderView::indexesMoved(const QModelIndexList
&indexes
)
1419 // If the user has rearranged the icons, the view is no longer sorted
1420 if (m_sortColumn
!= -1) {
1422 updateSortActionsState();
1423 config().writeEntry("sortColumn", m_sortColumn
);
1424 emit
configNeedsSaving();
1427 m_delayedSaveTimer
.start(5000, this);
1430 void FolderView::contextMenuRequest(QWidget
*widget
, const QPoint
&screenPos
)
1432 showContextMenu(widget
, screenPos
, m_selectionModel
->selectedIndexes());
1435 void FolderView::showContextMenu(QWidget
*widget
, const QPoint
&pos
, const QModelIndexList
&indexes
)
1437 if (!KAuthorized::authorize("action/kdesktop_rmb") || indexes
.isEmpty()) {
1441 KFileItemList items
;
1442 bool hasRemoteFiles
= false;
1443 bool isTrashLink
= false;
1445 foreach (const QModelIndex
&index
, indexes
) {
1446 KFileItem item
= m_model
->itemForIndex(index
);
1447 hasRemoteFiles
|= item
.localPath().isEmpty();
1451 // Check if we're showing the menu for the trash link
1452 if (items
.count() == 1 && items
.at(0).isDesktopFile()) {
1453 KDesktopFile
file(items
.at(0).localPath());
1454 if (file
.readType() == "Link" && file
.readUrl() == "trash:/") {
1459 QAction
* pasteTo
= m_actionCollection
.action("pasteto");
1461 pasteTo
->setEnabled(m_actionCollection
.action("paste")->isEnabled());
1462 pasteTo
->setText(m_actionCollection
.action("paste")->text());
1465 QList
<QAction
*> editActions
;
1466 editActions
.append(m_actionCollection
.action("rename"));
1468 KConfigGroup
configGroup(KGlobal::config(), "KDE");
1469 bool showDeleteCommand
= configGroup
.readEntry("ShowDeleteCommand", false);
1471 // Don't add the "Move to Trash" action if we're showing the menu for the trash link
1473 if (!hasRemoteFiles
) {
1474 editActions
.append(m_actionCollection
.action("trash"));
1476 showDeleteCommand
= true;
1479 if (showDeleteCommand
) {
1480 editActions
.append(m_actionCollection
.action("del"));
1483 KParts::BrowserExtension::ActionGroupMap actionGroups
;
1484 actionGroups
.insert("editactions", editActions
);
1486 KParts::BrowserExtension::PopupFlags flags
= KParts::BrowserExtension::ShowProperties
;
1488 // Use the Dolphin setting for showing the "Copy To" and "Move To" actions
1489 KConfig
dolphin("dolphinrc");
1490 if (KConfigGroup(&dolphin
, "General").readEntry("ShowCopyMoveMenu", false)) {
1491 flags
|= KParts::BrowserExtension::ShowUrlOperations
;
1494 // m_newMenu can be NULL here but KonqPopupMenu does handle this.
1495 KonqPopupMenu
*contextMenu
= new KonqPopupMenu(items
, m_url
, m_actionCollection
, m_newMenu
,
1496 KonqPopupMenu::ShowNewWindow
, flags
, widget
,
1497 KBookmarkManager::userBookmarksManager(),
1500 contextMenu
->exec(pos
);
1504 pasteTo
->setEnabled(false);
1508 void FolderView::updateIconWidget()
1510 if (!m_iconWidget
) {
1514 if (!m_placesModel
) {
1515 m_placesModel
= new KFilePlacesModel(this);
1518 const QModelIndex index
= m_placesModel
->closestItem(m_url
);
1520 // TODO: Custom icon
1522 KFileItem item
= m_dirModel
->itemForIndex(QModelIndex());
1523 if (!item
.isNull() && item
.iconName() != "inode-directory") {
1524 m_icon
= KIcon(item
.iconName(), 0, item
.overlays());
1525 } else if (m_url
.protocol() == "desktop") {
1526 m_icon
= KIcon("user-desktop");
1527 } else if (m_url
.protocol() == "trash") {
1528 m_icon
= m_model
->rowCount() > 0 ? KIcon("user-trash-full") : KIcon("user-trash");
1529 } else if (index
.isValid()) {
1530 m_icon
= m_placesModel
->icon(index
);
1532 m_icon
= KIcon("user-folder");
1535 m_iconWidget
->setIcon(m_icon
);
1536 m_iconWidget
->update();
1540 foreach (const KFileItem
&item
, m_dirModel
->dirLister()->items()) {
1548 const QString str1
= i18ncp("Inserted as %1 in the message below.", "1 folder", "%1 folders", nFolders
);
1549 const QString str2
= i18ncp("Inserted as %2 in the message below.", "1 file", "%1 files", nFiles
);
1553 subText
= i18nc("%1 and %2 are the messages translated above.", "%1, %2.", str1
, str2
);
1555 subText
= i18np("1 file.", "%1 files.", nFiles
);
1558 // Update the tooltip
1559 Plasma::ToolTipContent data
;
1560 data
.setMainText(m_titleText
);
1561 data
.setSubText(subText
);
1562 data
.setImage(m_icon
);
1563 Plasma::ToolTipManager::self()->setContent(m_iconWidget
, data
);
1566 void FolderView::iconWidgetClicked()
1568 if (m_dialog
->isVisible()) {
1571 m_dialog
->show(this);
1575 QSize
FolderView::iconSize() const
1577 const int defaultSize
= KIconLoader::global()->currentSize(m_listView
? KIconLoader::Panel
: KIconLoader::Desktop
);
1578 const int size
= (m_customIconSize
!= 0) ? m_customIconSize
: defaultSize
;
1579 return QSize(size
, size
);
1582 QSize
FolderView::gridSize() const
1584 const QFontMetrics
fm(Plasma::Theme::defaultTheme()->font(Plasma::Theme::DesktopFont
));
1585 const int textHeight
= fm
.lineSpacing() * m_numTextLines
;
1586 QSize size
= iconSize();
1587 size
.rheight() = size
.height() + textHeight
+ 16;
1588 size
.rwidth() = qMax(size
.width() * 2, fm
.averageCharWidth() * 10);
1592 void FolderView::timerEvent(QTimerEvent
*event
)
1594 if (event
->timerId() == m_delayedSaveTimer
.timerId()) {
1595 m_delayedSaveTimer
.stop();
1596 saveIconPositions();
1597 emit
configNeedsSaving();
1600 Containment::timerEvent(event
);
1603 #include "folderview.moc"