#include "private/kfileitemmodelsortalgorithm.h"
#include "private/kfileitemmodeldirlister.h"
+#include <QApplication>
#include <QMimeData>
#include <QTimer>
// #define KFILEITEMMODEL_DEBUG
KFileItemModel::KFileItemModel(QObject* parent) :
- KItemModelBase("name", parent),
+ KItemModelBase("text", parent),
m_dirLister(0),
m_naturalSorting(KGlobalSettings::naturalSorting()),
- m_sortFoldersFirst(true),
+ m_sortDirsFirst(true),
m_sortRole(NameRole),
m_sortingProgressPercent(-1),
m_roles(),
m_pendingItemsToInsert(),
m_groups(),
m_expandedParentsCountRoot(UninitializedExpandedParentsCountRoot),
- m_expandedUrls(),
+ m_expandedDirs(),
m_urlsToExpand()
{
m_dirLister = new KFileItemModelDirLister(this);
m_dirLister->setAutoUpdate(true);
m_dirLister->setDelayedMimeTypes(true);
+ m_dirLister->setMainWindow(qApp->activeWindow());
- connect(m_dirLister, SIGNAL(started(KUrl)), this, SIGNAL(dirLoadingStarted()));
+ connect(m_dirLister, SIGNAL(started(KUrl)), this, SIGNAL(directoryLoadingStarted()));
connect(m_dirLister, SIGNAL(canceled()), this, SLOT(slotCanceled()));
connect(m_dirLister, SIGNAL(completed(KUrl)), this, SLOT(slotCompleted()));
connect(m_dirLister, SIGNAL(newItems(KFileItemList)), this, SLOT(slotNewItems(KFileItemList)));
connect(m_dirLister, SIGNAL(clear(KUrl)), this, SLOT(slotClear(KUrl)));
connect(m_dirLister, SIGNAL(infoMessage(QString)), this, SIGNAL(infoMessage(QString)));
connect(m_dirLister, SIGNAL(errorMessage(QString)), this, SIGNAL(errorMessage(QString)));
- connect(m_dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SIGNAL(redirection(KUrl,KUrl)));
+ connect(m_dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SIGNAL(directoryRedirection(KUrl,KUrl)));
+ connect(m_dirLister, SIGNAL(urlIsFileError(KUrl)), this, SIGNAL(urlIsFileError(KUrl)));
// Apply default roles that should be determined
resetRoles();
m_requestRole[NameRole] = true;
m_requestRole[IsDirRole] = true;
- m_roles.insert("name");
+ m_requestRole[IsLinkRole] = true;
+ m_roles.insert("text");
m_roles.insert("isDir");
+ m_roles.insert("isLink");
// For slow KIO-slaves like used for searching it makes sense to show results periodically even
// before the completed() or canceled() signal has been emitted.
m_itemData.clear();
}
-void KFileItemModel::loadDir(const KUrl& url)
+void KFileItemModel::loadDirectory(const KUrl& url)
{
m_dirLister->openUrl(url);
}
-void KFileItemModel::refreshDir(const KUrl& url)
+void KFileItemModel::refreshDirectory(const KUrl& url)
{
m_dirLister->openUrl(url, KDirLister::Reload);
}
-KUrl KFileItemModel::dir() const
+KUrl KFileItemModel::directory() const
{
return m_dirLister->url();
}
+void KFileItemModel::cancelDirectoryLoading()
+{
+ m_dirLister->stop();
+}
+
int KFileItemModel::count() const
{
return m_itemData.count();
}
m_itemData[index]->values = currentValues;
+ if (changedRoles.contains("text")) {
+ KUrl url = m_itemData[index]->item.url();
+ url.setFileName(currentValues["text"].toString());
+ m_itemData[index]->item.setUrl(url);
+ }
+
emit itemsChanged(KItemRangeList() << KItemRange(index, 1), changedRoles);
if (changedRoles.contains(sortRole())) {
return true;
}
-void KFileItemModel::setSortFoldersFirst(bool foldersFirst)
+void KFileItemModel::setSortDirectoriesFirst(bool dirsFirst)
{
- if (foldersFirst != m_sortFoldersFirst) {
- m_sortFoldersFirst = foldersFirst;
+ if (dirsFirst != m_sortDirsFirst) {
+ m_sortDirsFirst = dirsFirst;
resortAllItems();
}
}
-bool KFileItemModel::sortFoldersFirst() const
+bool KFileItemModel::sortDirectoriesFirst() const
{
- return m_sortFoldersFirst;
+ return m_sortDirsFirst;
}
void KFileItemModel::setShowHiddenFiles(bool show)
return m_dirLister->showingDotFiles();
}
-void KFileItemModel::setShowFoldersOnly(bool enabled)
+void KFileItemModel::setShowDirectoriesOnly(bool enabled)
{
m_dirLister->setDirOnlyMode(enabled);
}
-bool KFileItemModel::showFoldersOnly() const
+bool KFileItemModel::showDirectoriesOnly() const
{
return m_dirLister->dirOnlyMode();
}
{
startFromIndex = qMax(0, startFromIndex);
for (int i = startFromIndex; i < count(); ++i) {
- if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
+ if (data(i)["text"].toString().startsWith(text, Qt::CaseInsensitive)) {
return i;
}
}
for (int i = 0; i < startFromIndex; ++i) {
- if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
+ if (data(i)["text"].toString().startsWith(text, Qt::CaseInsensitive)) {
return i;
}
}
const KUrl url = m_itemData.at(index)->item.url();
if (expanded) {
- m_expandedUrls.insert(url);
+ m_expandedDirs.insert(url);
m_dirLister->openUrl(url, KDirLister::Keep);
} else {
- m_expandedUrls.remove(url);
+ m_expandedDirs.remove(url);
m_dirLister->stop(url);
return 0;
}
-QSet<KUrl> KFileItemModel::expandedUrls() const
+QSet<KUrl> KFileItemModel::expandedDirectories() const
{
- return m_expandedUrls;
+ return m_expandedDirs;
}
-void KFileItemModel::restoreExpandedUrls(const QSet<KUrl>& urls)
+void KFileItemModel::restoreExpandedDirectories(const QSet<KUrl>& urls)
{
m_urlsToExpand = urls;
}
-void KFileItemModel::expandParentItems(const KUrl& url)
+void KFileItemModel::expandParentDirectories(const KUrl& url)
{
const int pos = m_dirLister->url().path().length();
const KFileItem item = it.next();
if (m_filter.matches(item)) {
newVisibleItems.append(item);
- m_filteredItems.remove(item);
+ it.remove();
}
}
return m_filter.pattern();
}
-void KFileItemModel::cancelDirLoading()
-{
- m_dirLister->stop();
-}
-
QList<KFileItemModel::RoleInfo> KFileItemModel::rolesInformation()
{
static QList<RoleInfo> rolesInfo;
// Note that the parent folder must be expanded before any of its subfolders become visible.
// Therefore, some URLs in m_restoredExpandedUrls might not be visible yet
// -> we expand the first visible URL we find in m_restoredExpandedUrls.
- foreach(const KUrl& url, m_urlsToExpand) {
+ foreach (const KUrl& url, m_urlsToExpand) {
const int index = m_items.value(url, -1);
if (index >= 0) {
m_urlsToExpand.remove(url);
m_urlsToExpand.clear();
}
- emit dirLoadingCompleted();
+ emit directoryLoadingCompleted();
}
void KFileItemModel::slotCanceled()
emit itemsRemoved(KItemRangeList() << KItemRange(0, removedCount));
}
- m_expandedUrls.clear();
+ m_expandedDirs.clear();
}
void KFileItemModel::slotClear(const KUrl& url)
insertedCount = 0;
}
- // Insert item at the position targetIndex by transfering
+ // Insert item at the position targetIndex by transferring
// the ownership of the item-data from sortedItems to m_itemData.
// m_items will be inserted after the loop (see comment below)
m_itemData.insert(targetIndex, sortedItems.at(sourceIndex));
removeItems(expandedItems);
m_expandedParentsCountRoot = UninitializedExpandedParentsCountRoot;
- m_expandedUrls.clear();
+ m_expandedDirs.clear();
}
void KFileItemModel::resetRoles()
// Insert internal roles (take care to synchronize the implementation
// with KFileItemModel::roleForType() in case if a change is done).
roles.insert("isDir", IsDirRole);
+ roles.insert("isLink", IsLinkRole);
roles.insert("isExpanded", IsExpandedRole);
roles.insert("isExpandable", IsExpandableRole);
roles.insert("expandedParentsCount", ExpandedParentsCountRole);
// Insert internal roles (take care to synchronize the implementation
// with KFileItemModel::typeForRole() in case if a change is done).
roles.insert(IsDirRole, "isDir");
+ roles.insert(IsLinkRole, "isLink");
roles.insert(IsExpandedRole, "isExpanded");
roles.insert(IsExpandableRole, "isExpandable");
roles.insert(ExpandedParentsCountRole, "expandedParentsCount");
data.insert("isDir", isDir);
}
+ if (m_requestRole[IsLinkRole]) {
+ const bool isLink = item.isLink();
+ data.insert("isLink", isLink);
+ }
+
if (m_requestRole[NameRole]) {
- data.insert("name", item.text());
+ data.insert("text", item.text());
}
if (m_requestRole[SizeRole]) {
if (item.url().protocol() == QLatin1String("trash")) {
path = item.entry().stringValue(KIO::UDSEntry::UDS_EXTRA);
} else {
+ // For performance reasons cache the home-path in a static QString
+ // (see QDir::homePath() for more details)
+ static QString homePath;
+ if (homePath.isEmpty()) {
+ homePath = QDir::homePath();
+ }
+
path = item.localPath();
+ if (path.startsWith(homePath)) {
+ path.replace(0, homePath.length(), QLatin1Char('~'));
+ }
}
const int index = path.lastIndexOf(item.text());
}
}
- if (m_sortFoldersFirst || m_sortRole == SizeRole) {
+ if (m_sortDirsFirst || m_sortRole == SizeRole) {
const bool isDirA = a->item.isDir();
const bool isDirB = b->item.isDir();
if (isDirA && !isDirB) {
break;
}
- case PermissionsRole:
- case OwnerRole:
- case GroupRole:
- case TypeRole:
- case DestinationRole:
- case PathRole:
- case CommentRole:
- case TagsRole: {
+ default: {
const QByteArray role = roleForType(m_sortRole);
result = QString::compare(a->values.value(role).toString(),
b->values.value(role).toString());
break;
}
- default:
- break;
}
if (result != 0) {
bool isDirB = true;
const QString subPathB = subPath(b->item, pathB, index, &isDirB);
- if (m_sortFoldersFirst || m_sortRole == SizeRole) {
+ if (m_sortDirsFirst || m_sortRole == SizeRole) {
if (isDirA && !isDirB) {
return (sortOrder() == Qt::AscendingOrder) ? -1 : +1;
} else if (!isDirA && isDirB) {
continue;
}
- const QString name = m_itemData.at(i)->values.value("name").toString();
+ const QString name = m_itemData.at(i)->values.value("text").toString();
// Use the first character of the name as group indication
QChar newFirstChar = name.at(0).toUpper();
resortAllItems();
}
- emit dirSortingProgress(100);
+ emit directorySortingProgress(100);
} else if (itemCount > 0) {
resolvedCount = qBound(0, resolvedCount, itemCount);
const int progress = resolvedCount * 100 / itemCount;
if (m_sortingProgressPercent != progress) {
m_sortingProgressPercent = progress;
- emit dirSortingProgress(progress);
+ emit directorySortingProgress(progress);
}
}
}
static const RoleInfoMap rolesInfoMap[] = {
// | role | roleType | role translation | group translation | requires Nepomuk | requires indexer
{ 0, NoRole, 0, 0, 0, 0, false, false },
- { "name", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0, false, false },
+ { "text", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0, false, false },
{ "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), 0, 0, false, false },
{ "date", DateRole, I18N_NOOP2_NOSTRIP("@label", "Date"), 0, 0, false, false },
{ "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), 0, 0, false, false },
{ "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
{ "imageSize", ImageSizeRole, I18N_NOOP2_NOSTRIP("@label", "Image Size"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
{ "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
- { "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
- { "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
- { "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
- { "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
+ { "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
{ "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
{ "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
{ "copiedFrom", CopiedFromRole, I18N_NOOP2_NOSTRIP("@label", "Copied From"), I18N_NOOP2_NOSTRIP("@label", "Other"), true, false },
{
QElapsedTimer timer;
timer.start();
- foreach (KFileItem item, items) {
+ foreach (KFileItem item, items) { // krazy:exclude=foreach
item.determineMimeType();
if (timer.elapsed() > timeout) {
// Don't block the user interface, let the remaining items