File indexing completed on 2024-04-28 05:49:08
0001 /* This file is part of the Kate project. 0002 * 0003 * SPDX-FileCopyrightText: 2012 Christoph Cullmann <cullmann@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kateprojectitem.h" 0009 #include "kateproject.h" 0010 0011 #include <QApplication> 0012 #include <QFile> 0013 #include <QIcon> 0014 #include <QMessageBox> 0015 #include <QMimeDatabase> 0016 #include <QThread> 0017 0018 #include <KIconUtils> 0019 #include <KLocalizedString> 0020 0021 #include <KTextEditor/Document> 0022 0023 KateProjectItem::KateProjectItem(Type type, const QString &text) 0024 : QStandardItem(text) 0025 , m_type(type) 0026 { 0027 if (type == File) { 0028 auto flags = this->flags(); 0029 flags.setFlag(Qt::ItemIsDropEnabled, false); 0030 setFlags(flags); 0031 } 0032 } 0033 0034 KateProjectItem::~KateProjectItem() 0035 { 0036 delete m_icon; 0037 } 0038 0039 void KateProjectItem::slotModifiedChanged(KTextEditor::Document *doc) 0040 { 0041 if (m_icon) { 0042 delete m_icon; 0043 m_icon = nullptr; 0044 } 0045 0046 if (doc && doc->isModified()) { 0047 if (m_emblem.isEmpty()) { 0048 m_icon = new QIcon(QIcon::fromTheme(QStringLiteral("document-save"))); 0049 } else { 0050 m_icon = new QIcon(KIconUtils::addOverlay(QIcon::fromTheme(QStringLiteral("document-save")), QIcon(m_emblem), Qt::TopLeftCorner)); 0051 } 0052 } 0053 emitDataChanged(); 0054 } 0055 0056 void KateProjectItem::slotModifiedOnDisk(KTextEditor::Document *document, bool isModified, KTextEditor::Document::ModifiedOnDiskReason reason) 0057 { 0058 Q_UNUSED(document) 0059 Q_UNUSED(isModified) 0060 0061 if (m_icon) { 0062 delete m_icon; 0063 m_icon = nullptr; 0064 } 0065 0066 m_emblem.clear(); 0067 0068 if (reason != KTextEditor::Document::OnDiskUnmodified) { 0069 m_emblem = QStringLiteral("emblem-important"); 0070 } 0071 emitDataChanged(); 0072 } 0073 0074 QVariant KateProjectItem::data(int role) const 0075 { 0076 if (role == Qt::DecorationRole) { 0077 /** 0078 * this should only happen in main thread 0079 * the background thread should only construct this elements and fill data 0080 * but never query gui stuff! 0081 */ 0082 Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); 0083 return QVariant(*icon()); 0084 } 0085 0086 if (role == TypeRole) { 0087 return QVariant(m_type); 0088 } 0089 0090 return QStandardItem::data(role); 0091 } 0092 0093 bool KateProjectItem::operator<(const QStandardItem &other) const 0094 { 0095 // let directories stay first 0096 const auto thisType = data(TypeRole).toInt(); 0097 const auto otherType = other.data(TypeRole).toInt(); 0098 if (thisType != otherType) { 0099 return thisType < otherType; 0100 } 0101 0102 // case-insensitive compare of the filename 0103 return data(Qt::DisplayRole).toString().compare(other.data(Qt::DisplayRole).toString(), Qt::CaseInsensitive) < 0; 0104 } 0105 0106 QIcon *KateProjectItem::icon() const 0107 { 0108 if (m_icon) { 0109 return m_icon; 0110 } 0111 0112 switch (m_type) { 0113 case LinkedProject: 0114 case Project: 0115 m_icon = new QIcon(QIcon::fromTheme(QStringLiteral("folder-documents"))); 0116 break; 0117 0118 case Directory: 0119 m_icon = new QIcon(QIcon::fromTheme(QStringLiteral("folder"))); 0120 break; 0121 0122 case File: { 0123 // ensure we have no empty icons, that breaks layout in tree views 0124 QIcon icon = QIcon::fromTheme(QMimeDatabase().mimeTypeForUrl(QUrl::fromLocalFile(data(Qt::UserRole).toString())).iconName()); 0125 if (icon.isNull()) { 0126 icon = QIcon::fromTheme(QStringLiteral("unknown")); 0127 } 0128 if (!m_emblem.isEmpty()) { 0129 m_icon = new QIcon(KIconUtils::addOverlay(icon, QIcon(m_emblem), Qt::TopLeftCorner)); 0130 } else { 0131 m_icon = new QIcon(icon); 0132 } 0133 break; 0134 } 0135 } 0136 0137 return m_icon; 0138 } 0139 0140 void KateProjectItem::setData(const QVariant &value, int role) 0141 { 0142 if (role == Qt::EditRole) { 0143 auto newFileName = value.toString(); 0144 if (newFileName.isEmpty()) 0145 return; 0146 0147 /** 0148 * retrieve the ref to project that we stored 0149 * in KateProjectTreeViewContextMenu 0150 */ 0151 KateProject *project = data(KateProjectItem::ProjectRole).value<KateProject *>(); 0152 if (!project) { 0153 return; 0154 } 0155 0156 auto oldFileName = data(Qt::DisplayRole).toString(); 0157 auto oldName = data(Qt::UserRole).toString(); 0158 QString newName = oldName; 0159 newName.replace(oldFileName, newFileName); 0160 0161 if (oldName == newName) { 0162 return; 0163 } 0164 0165 if (!QFile::rename(oldName, newName)) { 0166 QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("File name already exists")); 0167 return; 0168 } 0169 0170 /** 0171 * Update the file2Item 0172 */ 0173 project->renameFile(newName, oldName); 0174 0175 // change internal path 0176 setData(newName, Qt::UserRole); 0177 } 0178 0179 QStandardItem::setData(value, role); 0180 }