File indexing completed on 2024-04-28 04:37:03
0001 /* 0002 SPDX-FileCopyrightText: 2010 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "helper.h" 0008 0009 #include "debug.h" 0010 #include "path.h" 0011 0012 #include <QApplication> 0013 #include <QDir> 0014 #include <QFileInfo> 0015 0016 #include <KIO/CopyJob> 0017 #include <KIO/DeleteJob> 0018 #include <KIO/StatJob> 0019 #include <KIO/StoredTransferJob> 0020 #include <KIO/MkdirJob> 0021 #include <KJobWidgets> 0022 #include <KLocalizedString> 0023 #include <KTextEditor/Document> 0024 0025 #include <interfaces/iproject.h> 0026 #include <vcs/interfaces/ibasicversioncontrol.h> 0027 #include <interfaces/iplugin.h> 0028 #include <vcs/vcsjob.h> 0029 #include <interfaces/icore.h> 0030 #include <interfaces/idocumentcontroller.h> 0031 #include <interfaces/iuicontroller.h> 0032 #include <sublime/message.h> 0033 0034 using namespace KDevelop; 0035 0036 bool KDevelop::removeUrl(const KDevelop::IProject* project, const QUrl& url, const bool isFolder) 0037 { 0038 qCDebug(PROJECT) << "Removing url:" << url << "from project" << project; 0039 0040 QWidget* window = QApplication::activeWindow(); 0041 0042 auto job = KIO::statDetails(url, KIO::StatJob::DestinationSide, KIO::StatNoDetails); 0043 KJobWidgets::setWindow(job, window); 0044 if (!job->exec()) { 0045 qCWarning(PROJECT) << "tried to remove non-existing url:" << url << project << isFolder; 0046 return true; 0047 } 0048 0049 IPlugin* vcsplugin=project->versionControlPlugin(); 0050 if(vcsplugin) { 0051 auto* vcs=vcsplugin->extension<IBasicVersionControl>(); 0052 0053 // We have a vcs and the file/folder is controller, need to make the rename through vcs 0054 if(vcs->isVersionControlled(url)) { 0055 VcsJob* job=vcs->remove(QList<QUrl>() << url); 0056 if(job) { 0057 return job->exec(); 0058 } 0059 } 0060 } 0061 0062 //if we didn't find a VCS, we remove using KIO (if the file still exists, the vcs plugin might have simply deleted the url without returning a job 0063 auto deleteJob = KIO::del(url); 0064 KJobWidgets::setWindow(deleteJob, window); 0065 if (!deleteJob->exec() && url.isLocalFile() && (QFileInfo::exists(url.toLocalFile()))) { 0066 const QString messageText = 0067 isFolder ? i18n( "Cannot remove folder <i>%1</i>.", url.toDisplayString(QUrl::PreferLocalFile) ) 0068 : i18n( "Cannot remove file <i>%1</i>.", url.toDisplayString(QUrl::PreferLocalFile) ); 0069 auto* message = new Sublime::Message(messageText, Sublime::Message::Error); 0070 ICore::self()->uiController()->postMessage(message); 0071 return false; 0072 } 0073 return true; 0074 } 0075 0076 bool KDevelop::removePath(const KDevelop::IProject* project, const KDevelop::Path& path, const bool isFolder) 0077 { 0078 return removeUrl(project, path.toUrl(), isFolder); 0079 } 0080 0081 bool KDevelop::createFile(const QUrl& file) 0082 { 0083 auto statJob = KIO::statDetails(file, KIO::StatJob::DestinationSide, KIO::StatNoDetails); 0084 KJobWidgets::setWindow(statJob, QApplication::activeWindow()); 0085 if (statJob->exec()) { 0086 const QString messageText = i18n("The file <i>%1</i> already exists.", file.toDisplayString(QUrl::PreferLocalFile)); 0087 auto* message = new Sublime::Message(messageText, Sublime::Message::Error); 0088 ICore::self()->uiController()->postMessage(message); 0089 return false; 0090 } 0091 0092 { 0093 auto uploadJob = KIO::storedPut(QByteArray("\n"), file, -1); 0094 KJobWidgets::setWindow(uploadJob, QApplication::activeWindow()); 0095 if (!uploadJob->exec()) { 0096 const QString messageText = i18n("Cannot create file <i>%1</i>.", file.toDisplayString(QUrl::PreferLocalFile)); 0097 auto* message = new Sublime::Message(messageText, Sublime::Message::Error); 0098 ICore::self()->uiController()->postMessage(message); 0099 return false; 0100 } 0101 } 0102 return true; 0103 } 0104 0105 bool KDevelop::createFile(const KDevelop::Path& file) 0106 { 0107 return createFile(file.toUrl()); 0108 } 0109 0110 bool KDevelop::createFolder(const QUrl& folder) 0111 { 0112 auto mkdirJob = KIO::mkdir(folder); 0113 KJobWidgets::setWindow(mkdirJob, QApplication::activeWindow()); 0114 if (!mkdirJob->exec()) { 0115 const QString messageText = i18n("Cannot create folder <i>%1</i>.", folder.toDisplayString(QUrl::PreferLocalFile)); 0116 auto* message = new Sublime::Message(messageText, Sublime::Message::Error); 0117 ICore::self()->uiController()->postMessage(message); 0118 return false; 0119 } 0120 return true; 0121 } 0122 0123 bool KDevelop::createFolder(const KDevelop::Path& folder) 0124 { 0125 return createFolder(folder.toUrl()); 0126 } 0127 0128 bool KDevelop::renameUrl(const KDevelop::IProject* project, const QUrl& oldname, const QUrl& newname) 0129 { 0130 bool wasVcsMoved = false; 0131 IPlugin* vcsplugin = project->versionControlPlugin(); 0132 if (vcsplugin) { 0133 auto* vcs = vcsplugin->extension<IBasicVersionControl>(); 0134 0135 // We have a vcs and the file/folder is controller, need to make the rename through vcs 0136 if (vcs->isVersionControlled(oldname)) { 0137 VcsJob* job = vcs->move(oldname, newname); 0138 if (job && !job->exec()) { 0139 return false; 0140 } 0141 wasVcsMoved = true; 0142 } 0143 } 0144 // Fallback for the case of no vcs, or not-vcs-managed file/folder 0145 0146 // try to save-as the text document, so users can directly continue to work 0147 // on the renamed url as well as keeping the undo-stack intact 0148 IDocument* document = ICore::self()->documentController()->documentForUrl(oldname); 0149 if (document && document->textDocument()) { 0150 if (!document->textDocument()->saveAs(newname)) { 0151 return false; 0152 } 0153 if (!wasVcsMoved) { 0154 // unlink the old file 0155 removeUrl(project, oldname, false); 0156 } 0157 return true; 0158 } else if (!wasVcsMoved) { 0159 // fallback for non-textdocuments (also folders e.g.) 0160 KIO::CopyJob* job = KIO::move(oldname, newname); 0161 KJobWidgets::setWindow(job, QApplication::activeWindow()); 0162 bool success = job->exec(); 0163 if (success) { 0164 // save files that where opened in this folder under the new name 0165 Path oldBasePath(oldname); 0166 Path newBasePath(newname); 0167 const auto documents = ICore::self()->documentController()->openDocuments(); 0168 for (auto* doc : documents) { 0169 auto textDoc = doc->textDocument(); 0170 if (textDoc && oldname.isParentOf(doc->url())) { 0171 const auto path = Path(textDoc->url()); 0172 const auto relativePath = oldBasePath.relativePath(path); 0173 const auto newPath = Path(newBasePath, relativePath); 0174 textDoc->saveAs(newPath.toUrl()); 0175 } 0176 } 0177 } 0178 return success; 0179 } else { 0180 return true; 0181 } 0182 } 0183 0184 bool KDevelop::renamePath(const KDevelop::IProject* project, const KDevelop::Path& oldName, const KDevelop::Path& newName) 0185 { 0186 return renameUrl(project, oldName.toUrl(), newName.toUrl()); 0187 } 0188 0189 bool KDevelop::copyUrl(const KDevelop::IProject* project, const QUrl& source, const QUrl& target) 0190 { 0191 IPlugin* vcsplugin=project->versionControlPlugin(); 0192 if(vcsplugin) { 0193 auto* vcs=vcsplugin->extension<IBasicVersionControl>(); 0194 0195 // We have a vcs and the file/folder is controller, need to make the rename through vcs 0196 if(vcs->isVersionControlled(source)) { 0197 VcsJob* job=vcs->copy(source, target); 0198 if(job) { 0199 return job->exec(); 0200 } 0201 } 0202 } 0203 0204 // Fallback for the case of no vcs, or not-vcs-managed file/folder 0205 auto job = KIO::copy(source, target); 0206 KJobWidgets::setWindow(job, QApplication::activeWindow()); 0207 return job->exec(); 0208 } 0209 0210 bool KDevelop::copyPath(const KDevelop::IProject* project, const KDevelop::Path& source, const KDevelop::Path& target) 0211 { 0212 return copyUrl(project, source.toUrl(), target.toUrl()); 0213 } 0214 0215 Path KDevelop::proposedBuildFolder(const Path& sourceFolder) 0216 { 0217 Path proposedBuildFolder; 0218 if (sourceFolder.path().contains(QLatin1String("/src/"))) { 0219 const QString srcBuildPath = sourceFolder.path().replace(QLatin1String("/src/"), QLatin1String("/build/")); 0220 Q_ASSERT(!srcBuildPath.isEmpty()); 0221 if (QDir(srcBuildPath).exists()) { 0222 proposedBuildFolder = Path(srcBuildPath); 0223 } 0224 } 0225 if (!proposedBuildFolder.isValid()) { 0226 proposedBuildFolder = Path(sourceFolder, QStringLiteral("build")); 0227 } 0228 0229 return proposedBuildFolder; 0230 }