diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index c0335c5954..535c739674 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,165 +1,159 @@ # BEGIN: Analyzers add_subdirectory(clangtidy) add_subdirectory(clazy) add_subdirectory(cppcheck) if(UNIX AND NOT (APPLE OR CYGWIN)) add_subdirectory(heaptrack) endif() # END: Analyzers # BEGIN: Debuggers add_subdirectory(debuggercommon) add_subdirectory(lldb) add_subdirectory(gdb) # END: Debuggers # BEGIN: Documentation find_package(Qt5Help CONFIG) set_package_properties(Qt5Help PROPERTIES PURPOSE "The Help module for the Qt toolkit, needed for the qthelp plugin" URL "https://www.qt.io/" TYPE OPTIONAL) if(Qt5Help_FOUND) ecm_optional_add_subdirectory(qthelp) endif() ecm_optional_add_subdirectory(manpage) # END: Documentation # BEGIN: Formatters add_subdirectory(astyle) add_subdirectory(customscript) # END: Formatters # BEGIN: Languages ecm_optional_add_subdirectory(custom-definesandincludes) # 3rdparty/qtcreator-libs uses QT_CONFIG which was added for 5.8 if(NOT Qt5_VERSION VERSION_LESS "5.8.0") ecm_optional_add_subdirectory(qmljs) else() message(WARNING "Will not build QML/JS plugin, needs Qt >= 5.8.0") endif() find_package(Clang 3.8) set(clangSearchHint "") if (NOT CLANG_FOUND) set(clangSearchHint "Please install a package providing libclang. Either pass -DLLVM_ROOT=/path/to/llvm-prefix or install the 'llvm-config' command-line utility for auto-detection.") endif() set_package_properties(Clang PROPERTIES DESCRIPTION "Clang libraries from the LLVM project. ${clangSearchHint}" PURPOSE "Used for KDevelop's C++/C support plugin." TYPE REQUIRED ) if (CLANG_FOUND) if (NOT CLANG_CLANG_LIB) message(FATAL_ERROR "Could not find the Clang C library: libclang") endif() add_library(Clang::clang UNKNOWN IMPORTED) set_property(TARGET Clang::clang PROPERTY IMPORTED_LOCATION ${CLANG_CLANG_LIB}) ecm_optional_add_subdirectory(clang) endif() # END: Languages # BEGIN: Project builders add_subdirectory(makebuilder) add_subdirectory(ninjabuilder) ecm_optional_add_subdirectory(cmakebuilder) if (KDevelop-PG-Qt_FOUND) ecm_optional_add_subdirectory(qmakebuilder) endif() # END: Project builders # BEGIN: Project managers ecm_optional_add_subdirectory(cmake) ecm_optional_add_subdirectory(custommake) ecm_optional_add_subdirectory(custom-buildsystem) if (KDevelop-PG-Qt_FOUND) ecm_optional_add_subdirectory(qmakemanager) endif() ecm_optional_add_subdirectory(genericprojectmanager) # END: Project managers # BEGIN: Runtimes add_subdirectory(android) if (UNIX) add_subdirectory(docker) add_subdirectory(flatpak) endif() # END: Runtimes # BEGIN: VCS ecm_optional_add_subdirectory(bazaar) ecm_optional_add_subdirectory(git) ecm_optional_add_subdirectory(perforce) find_package(SubversionLibrary) set_package_properties(SubversionLibrary PROPERTIES PURPOSE "Support for Subversion integration" URL "http://subversion.tigris.org" TYPE OPTIONAL) if(SubversionLibrary_FOUND) ecm_optional_add_subdirectory(subversion) endif() add_subdirectory(vcschangesview) # END: VCS # BEGIN: Others add_subdirectory(appwizard) add_subdirectory(codeutils) add_subdirectory(contextbrowser) add_subdirectory(documentswitcher) add_subdirectory(documentview) add_subdirectory(execute) add_subdirectory(executescript) add_subdirectory(externalscript) add_subdirectory(filemanager) add_subdirectory(filetemplates) add_subdirectory(grepview) add_subdirectory(openwith) add_subdirectory(outlineview) add_subdirectory(patchreview) add_subdirectory(problemreporter) add_subdirectory(projectfilter) add_subdirectory(projectmanagerview) add_subdirectory(quickopen) add_subdirectory(sourceformatter) add_subdirectory(standardoutputview) add_subdirectory(switchtobuddy) add_subdirectory(testview) -# uses QIODevice::NewOnly which was added only for 5.11 -# TODO: add code variant for older Qt -if(NOT Qt5_VERSION VERSION_LESS "5.11.0") - add_subdirectory(scratchpad) -else() - message(WARNING "Will not build scratchpad plugin, needs Qt >= 5.11.0") -endif() +add_subdirectory(scratchpad) ecm_optional_add_subdirectory(classbrowser) ecm_optional_add_subdirectory(executeplasmoid) ecm_optional_add_subdirectory(ghprovider) ecm_optional_add_subdirectory(kdeprovider) ecm_optional_add_subdirectory(konsole) if (Qt5QuickWidgets_FOUND) add_subdirectory(welcomepage) endif() find_package(OktetaKastenControllers 0.3.1 CONFIG) set_package_properties(OktetaKastenControllers PROPERTIES PURPOSE "Required for building Okteta KDevelop plugin." URL "http://kde.org/" TYPE OPTIONAL) if (OktetaKastenControllers_FOUND) find_package(KastenControllers CONFIG) set_package_properties(KastenControllers PROPERTIES PURPOSE "Required for building Okteta KDevelop plugin." URL "http://kde.org/" TYPE OPTIONAL) endif() if (OktetaKastenControllers_FOUND AND KastenControllers_FOUND) add_subdirectory(okteta) endif() # END: Others diff --git a/plugins/scratchpad/scratchpad.cpp b/plugins/scratchpad/scratchpad.cpp index 83ebe887e1..9257871d29 100644 --- a/plugins/scratchpad/scratchpad.cpp +++ b/plugins/scratchpad/scratchpad.cpp @@ -1,261 +1,261 @@ /* This file is part of KDevelop * * Copyright 2018 Amish K. Naidu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "scratchpad.h" #include "scratchpadview.h" #include "scratchpadjob.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(ScratchpadFactory, "scratchpad.json", registerPlugin(); ) class ScratchpadToolViewFactory : public KDevelop::IToolViewFactory { public: explicit ScratchpadToolViewFactory(Scratchpad* plugin) : m_plugin(plugin) {} QWidget* create(QWidget* parent = nullptr) override { return new ScratchpadView(parent, m_plugin); } Qt::DockWidgetArea defaultPosition() override { return Qt::LeftDockWidgetArea; } QString id() const override { return QStringLiteral("org.kdevelop.scratchpad"); } private: Scratchpad* const m_plugin; }; namespace { KConfigGroup scratchCommands() { return KSharedConfig::openConfig()->group("Scratchpad").group("Commands"); } KConfigGroup mimeCommands() { return KSharedConfig::openConfig()->group("Scratchpad").group("Mime Commands"); } QString commandForScratch(const QFileInfo& file) { if (scratchCommands().hasKey(file.fileName())) { return scratchCommands().readEntry(file.fileName()); } const auto suffix = file.suffix(); if (mimeCommands().hasKey(suffix)) { return mimeCommands().readEntry(suffix); } const static QHash defaultCommands = { {QStringLiteral("cpp"), QStringLiteral("g++ -std=c++11 -o /tmp/a.out $f && /tmp/a.out")}, {QStringLiteral("py"), QStringLiteral("python $f")}, {QStringLiteral("js"), QStringLiteral("node $f")}, {QStringLiteral("c"), QStringLiteral("gcc -o /tmp/a.out $f && /tmp/a.out")}, }; return defaultCommands.value(suffix); } } Scratchpad::Scratchpad(QObject* parent, const QVariantList& args) : KDevelop::IPlugin(QStringLiteral("scratchpad"), parent) , m_factory(new ScratchpadToolViewFactory(this)) , m_model(new QStandardItemModel(this)) { Q_UNUSED(args); qCDebug(PLUGIN_SCRATCHPAD) << "Scratchpad plugin is loaded!"; core()->uiController()->addToolView(i18n("Scratchpad"), m_factory); const QDir dataDir(dataDirectory()); if (!dataDir.exists()) { qCDebug(PLUGIN_SCRATCHPAD) << "Creating directory" << dataDir; dataDir.mkpath(QStringLiteral(".")); } const QFileInfoList scratches = dataDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot); for (const auto& fileInfo : scratches) { addFileToModel(fileInfo); // TODO if scratch is open (happens when restarting), set pretty name, below code doesn't work // auto* document = core()->documentController()->documentForUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath())); // if (document) { // document->setPrettyName(i18n("scratch:%1", fileInfo.fileName())); // } } } QStandardItemModel* Scratchpad::model() const { return m_model; } QString Scratchpad::dataDirectory() { const static QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kdevscratchpad/scratches/"); return dir; } void Scratchpad::openScratch(const QModelIndex& index) { const QUrl scratchUrl = QUrl::fromLocalFile(index.data(FullPathRole).toString()); auto* const document = core()->documentController()->openDocument(scratchUrl); document->setPrettyName(i18nc("prefix to distinguish scratch tabs", "scratch:%1", index.data().toString())); } void Scratchpad::runScratch(const QModelIndex& index) { qCDebug(PLUGIN_SCRATCHPAD) << "run" << index.data().toString(); auto command = index.data(RunCommandRole).toString(); command.replace(QLatin1String("$f"), index.data(FullPathRole).toString()); if (!command.isEmpty()) { auto* job = new ScratchpadJob(command, index.data().toString(), this); core()->runController()->registerJob(job); } } void Scratchpad::removeScratch(const QModelIndex& index) { const QString path = index.data(FullPathRole).toString(); if (auto* document = core()->documentController()->documentForUrl(QUrl::fromLocalFile(path))) { document->close(); } if (QFile::remove(path)) { qCDebug(PLUGIN_SCRATCHPAD) << "removed" << index.data(FullPathRole); scratchCommands().deleteEntry(index.data().toString()); m_model->removeRow(index.row()); } else { emit actionFailed(i18n("Failed to remove scratch: %1", index.data().toString())); } } void Scratchpad::createScratch(const QString& name) { if (!m_model->findItems(name).isEmpty()) { emit actionFailed(i18n("Failed to create scratch: Name already in use")); return; } QFile file(dataDirectory() + name); - if (file.open(QIODevice::NewOnly)) { // create a new file + if (!file.exists() && file.open(QIODevice::WriteOnly)) { // create a new file if it doesn't exist file.close(); } if (file.exists()) { addFileToModel(file); } else { emit actionFailed(i18n("Failed to create new scratch")); } } void Scratchpad::renameScratch(const QModelIndex& index, const QString& previousName) { const QString newName = index.data().toString(); if (newName.contains(QDir::separator())) { m_model->setData(index, previousName); // undo emit actionFailed(i18n("Failed to rename scratch: Names must not include path seperator")); return; } const QString previousPath = dataDirectory() + previousName; const QString newPath = dataDirectory() + index.data().toString(); if (previousPath == newPath) { return; } if (QFile::rename(previousPath, newPath)) { qCDebug(PLUGIN_SCRATCHPAD) << "renamed" << previousPath << "to" << newPath; m_model->setData(index, newPath, Scratchpad::FullPathRole); m_model->itemFromIndex(index)->setIcon(m_iconProvider.icon(QFileInfo(newPath))); auto config = scratchCommands(); config.deleteEntry(previousName); config.writeEntry(newName, index.data(Scratchpad::RunCommandRole)); // close old and re-open the closed document if (auto* document = core()->documentController()->documentForUrl(QUrl::fromLocalFile(previousPath))) { // FIXME is there a better way ? this feels hacky document->close(); document = core()->documentController()->openDocument(QUrl::fromLocalFile(newPath)); document->setPrettyName(i18nc("prefix to distinguish scratch tabs", "scratch:%1", index.data().toString())); } } else { qCWarning(PLUGIN_SCRATCHPAD) << "failed renaming" << previousPath << "to" << newPath; // rollback m_model->setData(index, previousName); emit actionFailed(i18n("Failed renaming scratch.")); } } void Scratchpad::addFileToModel(const QFileInfo& fileInfo) { auto* const item = new QStandardItem(m_iconProvider.icon(fileInfo), fileInfo.fileName()); item->setData(fileInfo.absoluteFilePath(), FullPathRole); const auto command = commandForScratch(fileInfo); item->setData(command, RunCommandRole); scratchCommands().writeEntry(item->text(), item->data(RunCommandRole)); m_model->appendRow(item); } void Scratchpad::setCommand(const QModelIndex& index, const QString& command) { qCDebug(PLUGIN_SCRATCHPAD) << "set command" << index.data(); m_model->setData(index, command, RunCommandRole); scratchCommands().writeEntry(index.data().toString(), command); mimeCommands().writeEntry(QFileInfo(index.data().toString()).suffix(), command); } #include "scratchpad.moc"