diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ set(KDEVPLATFORM_VERSION_PATCH 0) # plugin versions listed in the .desktop files -set(KDEV_PLUGIN_VERSION 25) +set(KDEV_PLUGIN_VERSION 26) # Increase this to reset incompatible item-repositories set(KDEV_ITEMREPOSITORY_VERSION 85) diff --git a/debugger/CMakeLists.txt b/debugger/CMakeLists.txt --- a/debugger/CMakeLists.txt +++ b/debugger/CMakeLists.txt @@ -62,3 +62,5 @@ framestack/framestackmodel.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/debugger/framestack COMPONENT Devel ) + +add_subdirectory(tests) diff --git a/debugger/tests/CMakeLists.txt b/debugger/tests/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/debugger/tests/CMakeLists.txt @@ -0,0 +1,7 @@ +ecm_add_test(test_ivariablecontroller LINK_LIBRARIES + Qt5::Core + Qt5::Test + KDev::Tests + KDev::Debugger +) + diff --git a/debugger/tests/test_ivariablecontroller.h b/debugger/tests/test_ivariablecontroller.h new file mode 100644 --- /dev/null +++ b/debugger/tests/test_ivariablecontroller.h @@ -0,0 +1,53 @@ +/* + * KDevelop Debugger Support + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ +#ifndef KDEVPLATFORM_TEST_IVARIABLECONTROLLER_H +#define KDEVPLATFORM_TEST_IVARIABLECONTROLLER_H + +#include + +namespace KDevelop +{ +class TestDebugSession; + +class TestIVariableController : public QObject +{ +Q_OBJECT +public: + explicit TestIVariableController(QObject* parent = nullptr); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + /** + * Test for bug 333759. see https://bugs.kde.org/show_bug.cgi?id=333759 + */ + void updateRightAfterEnableAutoUpdate(); + void updateRightAfterEnableAutoUpdate_data(); + +private: + TestDebugSession *m_debugSession; +}; + +} +#endif // KDEVPLATFORM_TEST_IVARIABLECONTROLLER_H diff --git a/debugger/tests/test_ivariablecontroller.cpp b/debugger/tests/test_ivariablecontroller.cpp new file mode 100644 --- /dev/null +++ b/debugger/tests/test_ivariablecontroller.cpp @@ -0,0 +1,94 @@ +/* + * KDevelop Debugger Support + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ +#include "test_ivariablecontroller.h" + +#include +#include +#include +#include +#include +#include + +#include + +QTEST_MAIN(KDevelop::TestIVariableController); + +using namespace KDevelop; + +TestIVariableController::TestIVariableController(QObject* parent) + : QObject(parent) + , m_debugSession(nullptr) +{ +} + +void TestIVariableController::initTestCase() +{ + AutoTestShell::init(); + TestCore::initialize(Core::NoUi); + m_debugSession = new TestDebugSession(); + // Simulate an already started and paused debug session + m_debugSession->runToCursor(); +} + +void KDevelop::TestIVariableController::updateRightAfterEnableAutoUpdate_data() +{ + QTest::addColumn("startAt"); + QTest::addColumn("switchTo"); + QTest::addColumn("jumpTo"); + + QTest::newRow("jump to somewhere else") << 1 << 0 << 2; + QTest::newRow("jump back") << 1 << 0 << 1; +} + +void TestIVariableController::updateRightAfterEnableAutoUpdate() +{ + QFETCH(int, startAt); + QFETCH(int, switchTo); + QFETCH(int, jumpTo); + + auto frameStackModel = m_debugSession->frameStackModel(); + auto variableController = qobject_cast(m_debugSession->variableController()); + if (!variableController) { + return; + } + + frameStackModel->setCurrentThread(0); + frameStackModel->setCurrentFrame(startAt); + + int oldCounter = variableController->updatedTimes(); + + variableController->setAutoUpdate(IVariableController::UpdateNone); + frameStackModel->setCurrentFrame(switchTo); // no update + variableController->setAutoUpdate(IVariableController::UpdateLocals); // trigger update + // switch back to frame we were at before disable auto update + frameStackModel->setCurrentFrame(jumpTo); // trigger another update + + int updatedTimes = variableController->updatedTimes() - oldCounter; + QCOMPARE(updatedTimes, 2); +} + +void TestIVariableController::cleanupTestCase() +{ + delete m_debugSession; + TestCore::shutdown(); +} diff --git a/debugger/variable/variablecollection.h b/debugger/variable/variablecollection.h --- a/debugger/variable/variablecollection.h +++ b/debugger/variable/variablecollection.h @@ -38,18 +38,19 @@ #include "../interfaces/idebugsession.h" #include "../../interfaces/idebugcontroller.h" -namespace GDBDebugger { +namespace KDevMI { namespace GDB { class GdbTest; } +} namespace KDevelop { class VariableToolTip; class KDEVPLATFORMDEBUGGER_EXPORT Variable : public TreeItem { Q_OBJECT - friend class GDBDebugger::GdbTest; + friend class KDevMI::GDB::GdbTest; public: protected: Variable(TreeModel* model, TreeItem* parent, @@ -141,7 +142,7 @@ class KDEVPLATFORMDEBUGGER_EXPORT Watches : public TreeItem { Q_OBJECT - friend class GDBDebugger::GdbTest; + friend class KDevMI::GDB::GdbTest; public: Watches(TreeModel* model, TreeItem* parent); Variable* add(const QString& expression); diff --git a/debugger/variable/variabletooltip.cpp b/debugger/variable/variabletooltip.cpp --- a/debugger/variable/variabletooltip.cpp +++ b/debugger/variable/variabletooltip.cpp @@ -138,7 +138,7 @@ QHBoxLayout* buttonBox = new QHBoxLayout(); buttonBox->setContentsMargins(11, 0, 11, 6); - QPushButton* watchThisButton = new QPushButton(i18n("Watch this")); + QPushButton* watchThisButton = new QPushButton(i18n("Watch This")); buttonBox->addWidget(watchThisButton); QPushButton* stopOnChangeButton = new QPushButton(i18n("Stop on Change")); buttonBox->addWidget(stopOnChangeButton); diff --git a/interfaces/iplugin.h b/interfaces/iplugin.h --- a/interfaces/iplugin.h +++ b/interfaces/iplugin.h @@ -210,14 +210,21 @@ /** * This function is necessary because there is no proper way to signal errors from plugin constructor. - * @returns True if the plugin has encountered an error, false otherwise. + * @returns True if the plugin has encountered an error (and therefore has an error description), + * false otherwise. */ - virtual bool hasError() const; - + bool hasError() const; + /** * Description of the last encountered error, of an empty string if none. */ - virtual QString errorDescription() const; + QString errorDescription() const; + + /** + * Set a @p description of the errror encountered. An empty error + * description implies no error in the plugin. + */ + void setErrorDescription(QString const& description); /** * Get the global config page with the \p number, config pages from 0 to diff --git a/interfaces/iplugin.cpp b/interfaces/iplugin.cpp --- a/interfaces/iplugin.cpp +++ b/interfaces/iplugin.cpp @@ -78,6 +78,7 @@ IPlugin *q; ICore *core; QVector m_extensions; + QString m_errorDescription; }; IPlugin::IPlugin( const QString &componentName, QObject *parent ) @@ -184,12 +185,18 @@ bool KDevelop::IPlugin::hasError() const { - return false; + return !d->m_errorDescription.isEmpty(); } +void KDevelop::IPlugin::setErrorDescription(const QString& description) +{ + d->m_errorDescription = description; +} + + QString KDevelop::IPlugin::errorDescription() const { - return QString(); + return d->m_errorDescription; } int KDevelop::IPlugin::configPages() const diff --git a/interfaces/kdevelopplugin.desktop b/interfaces/kdevelopplugin.desktop --- a/interfaces/kdevelopplugin.desktop +++ b/interfaces/kdevelopplugin.desktop @@ -3,6 +3,7 @@ X-KDE-ServiceType=KDevelop/Plugin X-KDE-Derived=KPluginInfo Name=KDevelop Plugin +Name[ast]=Complementu KDevelop Name[bg]=KDevelop приставка Name[bs]=KDevelop dodatak Name[ca]=Connector KDevelop diff --git a/language/codecompletion/codecompletionmodel.h b/language/codecompletion/codecompletionmodel.h --- a/language/codecompletion/codecompletionmodel.h +++ b/language/codecompletion/codecompletionmodel.h @@ -135,6 +135,7 @@ friend class CompletionWorkerThread; CodeCompletionWorker* worker() const; + private: bool m_forceWaitForModel; bool m_fullCompletion; diff --git a/language/duchain/appendedlist.h b/language/duchain/appendedlist.h --- a/language/duchain/appendedlist.h +++ b/language/duchain/appendedlist.h @@ -21,10 +21,10 @@ #include #include -#include #include #include +#include #include #include @@ -190,8 +190,8 @@ } QVector m_items; /// note: non-shared, ref count of 1 when accessed with non-const methods => no detach - QStack m_freeIndicesWithData; - QStack m_freeIndices; + Stack m_freeIndicesWithData; + Stack m_freeIndices; QMutex m_mutex; QByteArray m_id; QList > > m_deleteLater; diff --git a/language/duchain/builders/abstractcontextbuilder.h b/language/duchain/builders/abstractcontextbuilder.h --- a/language/duchain/builders/abstractcontextbuilder.h +++ b/language/duchain/builders/abstractcontextbuilder.h @@ -38,6 +38,7 @@ #include "../parsingenvironment.h" #include +#include namespace KDevelop { @@ -543,7 +544,7 @@ * \todo Audit whether access to the context stack is still required, and provide * replacement functionality if possible. */ - const QStack& contextStack() const + const Stack& contextStack() const { return m_contextStack; } @@ -658,11 +659,11 @@ QualifiedIdentifier m_qIdentifier; bool m_compilingContexts : 1; bool m_recompiling : 1; - QStack m_nextContextStack; + Stack m_nextContextStack; DUContext* m_lastContext; //Here all valid declarations/uses/... will be collected QSet m_encountered; - QStack m_contextStack; + Stack m_contextStack; }; } diff --git a/language/duchain/builders/abstractdeclarationbuilder.h b/language/duchain/builders/abstractdeclarationbuilder.h --- a/language/duchain/builders/abstractdeclarationbuilder.h +++ b/language/duchain/builders/abstractdeclarationbuilder.h @@ -203,7 +203,7 @@ } private: - QStack m_declarationStack; + Stack m_declarationStack; QByteArray m_lastComment; }; diff --git a/language/duchain/builders/abstracttypebuilder.h b/language/duchain/builders/abstracttypebuilder.h --- a/language/duchain/builders/abstracttypebuilder.h +++ b/language/duchain/builders/abstracttypebuilder.h @@ -260,7 +260,7 @@ } private: - QStack m_typeStack; + Stack m_typeStack; AbstractType::Ptr m_lastType; diff --git a/language/duchain/builders/abstractusebuilder.h b/language/duchain/builders/abstractusebuilder.h --- a/language/duchain/builders/abstractusebuilder.h +++ b/language/duchain/builders/abstractusebuilder.h @@ -25,6 +25,8 @@ #include "../duchain.h" #include "../duchainlock.h" +#include + namespace KDevelop { /** @@ -206,8 +208,8 @@ private: inline ContextUseTracker& currentUseTracker() { return m_trackerStack.top(); } - QStack m_trackerStack; - QStack m_contexts; + Stack m_trackerStack; + Stack m_contexts; //Whether not encountered uses should be deleted during closeContext() bool m_finishContext; diff --git a/language/duchain/problem.h b/language/duchain/problem.h --- a/language/duchain/problem.h +++ b/language/duchain/problem.h @@ -21,8 +21,6 @@ #define KDEVPLATFORM_PROBLEM_H -#include - #include #include "../editor/documentrange.h" diff --git a/language/duchain/types/typeregister.h b/language/duchain/types/typeregister.h --- a/language/duchain/types/typeregister.h +++ b/language/duchain/types/typeregister.h @@ -116,8 +116,6 @@ Q_ASSERT(data.typeClassId == T::Identity); return static_cast(data).dynamicSize(); } -/* private: - QStack m_reUseTypes;*/ }; /** diff --git a/language/util/setrepository.cpp b/language/util/setrepository.cpp --- a/language/util/setrepository.cpp +++ b/language/util/setrepository.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include //#define DEBUG_SETREPOSITORY diff --git a/outputview/outputfilteringstrategies.cpp b/outputview/outputfilteringstrategies.cpp --- a/outputview/outputfilteringstrategies.cpp +++ b/outputview/outputfilteringstrategies.cpp @@ -260,7 +260,7 @@ // GCC - another case, eg. for #include "pixmap.xpm" which does not exists ErrorFormat( QStringLiteral("^([^:\t]+):([0-9]+):([0-9]+):([^0-9]+)"), 1, 2, 4, 3 ), // ant - ErrorFormat("\\[javac\\][\\s]+([^:\t]+):([0-9]+): (warning: .*|error: .*)", 1, 2, 3, "javac"), + ErrorFormat( QStringLiteral("\\[javac\\][\\s]+([^:\t]+):([0-9]+): (warning: .*|error: .*)"), 1, 2, 3, QStringLiteral("javac")), // GCC ErrorFormat( QStringLiteral("^([^:\t]+):([0-9]+):([^0-9]+)"), 1, 2, 3 ), // GCC @@ -414,8 +414,11 @@ // ... // Loc: [Unknown file(0)] ErrorFormat(QStringLiteral(" Loc: \\[(.*)\\(([1-9][0-9]*)\\)\\]"), 1, 2, -1), + // file:///path/to/foo.qml:7:1: Bar is not a type - ErrorFormat(QStringLiteral("(file:\\/\\/(?:.+)):([1-9][0-9]*):([1-9][0-9]*): (.+) (?:is not a type|is ambiguous\\.|is instantiated recursively)"), 1, 2, -1, 3) + // file:///path/to/foo.qml:49:5: QML Row: Binding loop detected for property "height" + // file:///path/to/foo.qml:52: TypeError: Cannot read property 'height' of null + ErrorFormat(QStringLiteral("(file:\\/\\/(?:[^:]+)):([1-9][0-9]*):(?:([1-9][0-9]*):)?"), 1, 2, -1, 3), // END: Qt }; diff --git a/outputview/tests/test_filteringstrategy.cpp b/outputview/tests/test_filteringstrategy.cpp --- a/outputview/tests/test_filteringstrategy.cpp +++ b/outputview/tests/test_filteringstrategy.cpp @@ -267,6 +267,18 @@ << "file:///path/to/foo.qml:7:1: Bar is instantiated recursively" << "/path/to/foo.qml" << 6 << 0 << FilteredItem::ErrorItem; + QTest::newRow("qml-typeerror") + << "file:///path/to/foo.qml:7: TypeError: Cannot read property 'height' of null" + << "/path/to/foo.qml" + << 6 << -1 << FilteredItem::ErrorItem; + QTest::newRow("qml-referenceerror") + << "file:///path/to/foo.qml:7: ReferenceError: readOnly is not defined" + << "/path/to/foo.qml" + << 6 << -1 << FilteredItem::ErrorItem; + QTest::newRow("qml-bindingloop") + << "file:///path/to/foo.qml:7:5: QML Row: Binding loop detected for property \"height\"" + << "/path/to/foo.qml" + << 6 << 4 << FilteredItem::ErrorItem; // END: Qt } diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory(grepview) add_subdirectory(git) add_subdirectory(bazaar) +add_subdirectory(perforce) add_subdirectory(vcschangesview) if (Grantlee5_FOUND) add_subdirectory(filetemplates) diff --git a/plugins/appwizard/kdevappwizard.json b/plugins/appwizard/kdevappwizard.json --- a/plugins/appwizard/kdevappwizard.json +++ b/plugins/appwizard/kdevappwizard.json @@ -2,17 +2,18 @@ "KPlugin": { "Authors": [ { - "Name": "Alexander Dymo" + "Name": "Alexander Dymo", + "Name[uk]": "Олександр Димо", + "Name[x-test]": "xxAlexander Dymoxx" } ], "Category": "Core", "Description": "Application Wizard", + "Description[ar]": "مُرشد تطبيق", "Description[ca@valencia]": "Assistent d'aplicació", "Description[ca]": "Assistent d'aplicació", "Description[de]": "Anwendungsassistent", - "Description[en_GB]": "Application Wizard", "Description[es]": "Asistente de aplicaciones", - "Description[et]": "Rakenduse nõustaja", "Description[fi]": "Opastettu sovelluksen luonti", "Description[gl]": "Asistente para programas", "Description[it]": "Procedura guidata applicazione", @@ -23,33 +24,45 @@ "Description[sk]": "Sprievodca aplikáciou", "Description[sl]": "Čarovnik za programe", "Description[sv]": "Programguide", + "Description[tr]": "Uygulama Sihirbazı", "Description[uk]": "Майстер створення програм", "Description[x-test]": "xxApplication Wizardxx", "Description[zh_CN]": "应用程序向导", "Icon": "project-development-new-template", "Id": "kdevappwizard", "License": "GPL", "Name": "New Project Wizard", + "Name[ar]": "مُرشد مشروع جديد", + "Name[bg]": "Съветник за нов проект", + "Name[bs]": "Čarobnjak novog projekta", "Name[ca@valencia]": "Assistent de projecte nou", "Name[ca]": "Assistent de projecte nou", + "Name[da]": "Guide til nyt projekt", "Name[de]": "Projekt-Assistent", - "Name[en_GB]": "New Project Wizard", + "Name[el]": "Οδηγός ρύθμισης νέου έργου", "Name[es]": "Asistente de nuevo proyecto", "Name[et]": "Uue projekti nõustaja", "Name[fi]": "Uuden projektin opastettu luonti", "Name[gl]": "Asistente para proxectos novos", + "Name[hu]": "Új projekt varázsló", "Name[it]": "Procedura guidata nuovo progetto", + "Name[kk]": "Жаңа жоба шебері", "Name[nb]": "Veiviser for nytt prosjekt", + "Name[nds]": "Projekt-Hölper", "Name[nl]": "Nieuwe projectenassistent", "Name[pl]": "Pomocnik nowego projektu", "Name[pt]": "Assistente de Novos Projectos", "Name[pt_BR]": "Assistente de novo projeto", + "Name[ru]": "Мастер создания проекта", "Name[sk]": "Sprievodca novým projektom", "Name[sl]": "Čarovnik za nov projekt", "Name[sv]": "Ny projektguide", + "Name[tr]": "Yeni Proje Sihirbazı", + "Name[ug]": "يېڭى قۇرۇلۇش يېتەكچىسى", "Name[uk]": "Майстер створення проекту", "Name[x-test]": "xxNew Project Wizardxx", "Name[zh_CN]": "新工程向导", + "Name[zh_TW]": "新增專案精靈", "ServiceTypes": [ "KDevelop/Plugin" ], diff --git a/plugins/bazaar/bazaarplugin.h b/plugins/bazaar/bazaarplugin.h --- a/plugins/bazaar/bazaarplugin.h +++ b/plugins/bazaar/bazaarplugin.h @@ -40,9 +40,6 @@ explicit BazaarPlugin(QObject* parent, const QVariantList& args = QVariantList()); ~BazaarPlugin() override; - bool hasError() const override; - QString errorDescription() const override; - QString name() const override; KDevelop::VcsJob* add(const QList& localLocations, RecursionMode recursion=Recursive) override; @@ -75,9 +72,6 @@ private: KDevelop::VcsPluginHelper* m_vcsPluginHelper; - - bool m_hasError; - QString m_errorDescription; }; #endif // BAZAAR_BAZAARPLUGIN_H diff --git a/plugins/bazaar/bazaarplugin.cpp b/plugins/bazaar/bazaarplugin.cpp --- a/plugins/bazaar/bazaarplugin.cpp +++ b/plugins/bazaar/bazaarplugin.cpp @@ -45,13 +45,11 @@ BazaarPlugin::BazaarPlugin(QObject* parent, const QVariantList& args) : IPlugin(QStringLiteral("kdevbazaar"), parent), - m_vcsPluginHelper(new KDevelop::VcsPluginHelper(this, this)), m_hasError(false) + m_vcsPluginHelper(new KDevelop::VcsPluginHelper(this, this)) { Q_UNUSED(args); // What is this? if (QStandardPaths::findExecutable(QStringLiteral("bzr")).isEmpty()) { - m_hasError = true; - m_errorDescription = i18n("Bazaar is not installed (bzr executable not" - " found)"); + setErrorDescription(i18n("Unable to find Bazaar (bzr) executable Is it installed on the system?")); return; } @@ -339,12 +337,3 @@ return menuExt; } -bool BazaarPlugin::hasError() const -{ - return m_hasError; -} - -QString BazaarPlugin::errorDescription() const -{ - return m_errorDescription; -} diff --git a/plugins/bazaar/kdevbazaar.json b/plugins/bazaar/kdevbazaar.json --- a/plugins/bazaar/kdevbazaar.json +++ b/plugins/bazaar/kdevbazaar.json @@ -4,18 +4,18 @@ "Authors": [ { "Email": "d82ks8djf82msd83hf8sc02lqb5gh5@gmail.com", - "Name": "Maciej Poleski" + "Name": "Maciej Poleski", + "Name[x-test]": "xxMaciej Poleskixx" } ], "Category": "Version Control", "Description": "This plugin integrates Bazaar to KDevelop", + "Description[ar]": "تكامل هذه الملحقة مطوّرك ببازار", "Description[ca@valencia]": "Este connector integra Bazaar al KDevelop", "Description[ca]": "Aquest connector integra Bazaar al KDevelop", "Description[cs]": "Tento modul integruje podporu pro Bazaar v KDevelop", "Description[de]": "Dieses Modul integriert Bazaar in KDevelop", - "Description[en_GB]": "This plugin integrates Bazaar to KDevelop", "Description[es]": "Este complemento integra Bazaar en KDevelop", - "Description[et]": "See plugin lõimib Bazaari KDevelopiga", "Description[fi]": "Tämä liitännäinen integroi Bazaarin KDevelop-ympäristöön", "Description[gl]": "Este complemento integra Bazaar con KDevelop", "Description[it]": "Questa estensione integra Bazaar in KDevelop", @@ -26,35 +26,48 @@ "Description[sk]": "Tento plugin integruje Bazaar do KDevelop.", "Description[sl]": "Vstavek v KDevelop vgradi Bazaar", "Description[sv]": "Insticksprogrammet integrerar Bazaar i KDevelop", + "Description[tr]": "Bu eklenti Bazaar'ı KDevelop'a bütünleştirir", "Description[uk]": "За допомогою цього додатка можна інтегрувати Bazaar до KDevelop", "Description[x-test]": "xxThis plugin integrates Bazaar to KDevelopxx", "Description[zh_CN]": "此插件将 Bazaar 整合到 KDevelop", "Icon": "bazaar", "Id": "kdevbazaar", "License": "GPL", "Name": "Bazaar Support", + "Name[ar]": "دعم بازار", + "Name[bg]": "Поддръжка на Bazaar", + "Name[bs]": "Bazaar podrška", "Name[ca@valencia]": "Implementació de Bazaar", "Name[ca]": "Implementació de Bazaar", "Name[cs]": "Podpora Bazaar", + "Name[da]": "Bazaar-understøttelse", "Name[de]": "Bazaar-Unterstützung", - "Name[en_GB]": "Bazaar Support", + "Name[el]": "Υποστήριξη Bazaar", "Name[es]": "Implementación de Bazaar", "Name[et]": "Bazaari toetus", "Name[fi]": "Bazaar-tuki", + "Name[ga]": "Tacaíocht Bazaar", "Name[gl]": "Soporte de Bazaar", + "Name[hu]": "Bazaar támogatás", "Name[it]": "Supporto Bazaar", + "Name[kk]": "Bazaar қолдауы", "Name[nb]": "Bazaar-støtte", + "Name[nds]": "Bazaar-Ünnerstütten", "Name[nl]": "Ondersteuning van Bazaar", "Name[nn]": "DPMS-støtte", "Name[pl]": "Obsługa Bazaar", "Name[pt]": "Suporte para o Bazaar", "Name[pt_BR]": "Suporte a Bazaar", + "Name[ru]": "Поддержка Bazaar", "Name[sk]": "Podpora Bazaar", "Name[sl]": "Podpora za Bazaar", "Name[sv]": "Stöd för Bazaar", + "Name[tr]": "Bazaar Desteği", + "Name[ug]": "Bazaar قوللىشى", "Name[uk]": "Підтримка Bazaar", "Name[x-test]": "xxBazaar Supportxx", "Name[zh_CN]": "Bazaar 支持", + "Name[zh_TW]": "Bazaar 支援", "ServiceTypes": [ "KDevelop/Plugin" ], diff --git a/plugins/classbrowser/kdevclassbrowser.json b/plugins/classbrowser/kdevclassbrowser.json --- a/plugins/classbrowser/kdevclassbrowser.json +++ b/plugins/classbrowser/kdevclassbrowser.json @@ -2,17 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "Hamish Rodda" + "Name": "Hamish Rodda", + "Name[x-test]": "xxHamish Roddaxx" } ], "Category": "Core", "Description": "This plugin provides a browsable model of the currently parsed classes and other items.", + "Description[ar]": "توفّر هذه الملحقة طرازًا قابلًا للتّصفّح للأصناف المحلّلة حاليًّا والعناصر الأخرى.", "Description[ca@valencia]": "Este connector proporciona un model navegable de les classes analitzades actualment i altres elements.", "Description[ca]": "Aquest connector proporciona un model navegable de les classes analitzades actualment i altres elements.", "Description[de]": "Dieses Modul bietet eine Liste der aktuell eingelesenen Klassen und anderer Elemente.", - "Description[en_GB]": "This plugin provides a browsable model of the currently parsed classes and other items.", "Description[es]": "Este complemento proporciona un modelo navegable de las clases actualmente analizadas y de otros elementos.", - "Description[et]": "See plugin pakub parajasti parsitavate klasside ja teiste elementide sirvitavat mudelit.", "Description[fi]": "Tämä liitännäinen tarjoaa selattavan mallin nykyisellään jäsennetyistä luokista ja muista kohteista.", "Description[gl]": "Este complemento fornece un modelo navegábel das clases e outros elementos que estean procesados.", "Description[it]": "Questa estensione fornisce un modello sfogliabile delle classi attualmente analizzate e altri elementi.", @@ -23,38 +23,50 @@ "Description[sk]": "Tento plugin poskytuje prehliadateľný model aktuálne analyzovanej triedy a iných položiek.", "Description[sl]": "Vstavek vgradi model trenutno razčlenjenih razredov in drugih predmetov, po katerih je mogoče brskati.", "Description[sv]": "Insticksprogrammet tillhandahåller en bläddringsbar modell av klasser och andra objekt som för närvarande har tolkats.", + "Description[tr]": "Bu eklenti mevcut ayrıştırılmış sınıfların ve diğer öğelerin taranabilir bir modelini sağlar.", "Description[uk]": "За допомогою цього додатка можна створити придатну для перегляду модель класів та інших елементів, над якими ви працюєте.", "Description[x-test]": "xxThis plugin provides a browsable model of the currently parsed classes and other items.xx", "Description[zh_CN]": "此插件提供了一个当前已分析类和其它项目的可浏览化视窗模型。", "Icon": "code-class", "Id": "kdevclassbrowser", "License": "GPL", "Name": "Class Browser", + "Name[ar]": "متصفّح الأصناف", + "Name[bg]": "Браузър за класове", + "Name[bs]": "Pregledač klasa", "Name[ca@valencia]": "Navegador de classes", "Name[ca]": "Navegador de classes", "Name[cs]": "Prohlížeč tříd", + "Name[da]": "Klassebrowser", "Name[de]": "Klassen-Browser", - "Name[en_GB]": "Class Browser", + "Name[el]": "Περιηγητής κλάσεων", "Name[es]": "Navegador de clases", "Name[et]": "Klassibrauser", "Name[fi]": "Luokkaselain", "Name[gl]": "Navegador de clases", + "Name[hu]": "Osztályböngésző", "Name[it]": "Browser classi", + "Name[kk]": "Класс шолғышы", "Name[nb]": "Klasseleser", + "Name[nds]": "Klassenkieker", "Name[nl]": "Klassen-browser", "Name[pl]": "Przeglądarka klas", "Name[pt]": "Navegador de Classes", "Name[pt_BR]": "Navegador de Classes", + "Name[ru]": "Дерево классов", "Name[sk]": "Prehliadač tried", "Name[sl]": "Brskalnik po razredih", "Name[sv]": "Klassbläddrare", + "Name[tr]": "Sınıf Tarayıcı", + "Name[ug]": "تىپ كۆرگۈ", "Name[uk]": "Переглядач класів", "Name[x-test]": "xxClass Browserxx", "Name[zh_CN]": "类浏览器", + "Name[zh_TW]": "類別瀏覽器", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/codeutils/kdevcodeutils.json b/plugins/codeutils/kdevcodeutils.json --- a/plugins/codeutils/kdevcodeutils.json +++ b/plugins/codeutils/kdevcodeutils.json @@ -2,12 +2,11 @@ "KPlugin": { "Category": "Utilities", "Description": "Collection of various utilities that increase productivity while programming.", + "Description[ar]": "مجموعة من أدوات مختلفة تزيد الإنتاجيّة أثناء البرمجة.", "Description[ca@valencia]": "Col·lecció de diverses utilitats que augmenten la productivitat durant la programació.", "Description[ca]": "Col·lecció de diverses utilitats que augmenten la productivitat durant la programació.", "Description[de]": "Sammlung verschiedener Werkzeuge, die die Produktivität während des Programmierens erhöhen.", - "Description[en_GB]": "Collection of various utilities that increase productivity while programming.", "Description[es]": "Colección de diversas utilidades que incrementan la productividad de la programación.", - "Description[et]": "Mitmesugused tööriistad, mis suurendavad produktiivsust programmeerimisel.", "Description[fi]": "Kokoelma sekalaisia työkaluja, jotka lisäävät ohjelmointisi tuottavuutta.", "Description[gl]": "Colección de varias utilidades que aumentan a produtividade durante a programación.", "Description[it]": "Raccolta di varie utilità che aumentano la produttività durante la programmazione.", @@ -18,36 +17,47 @@ "Description[sk]": "Zbierka rôznych utilít, ktoré zvyšujú produktivitu počas programovania.", "Description[sl]": "Zbirka raznih pripomočkov, ki povečajo učinkovitost med programiranjem.", "Description[sv]": "Samling av diverse verktyg för att öka produktiviteten vid programmering.", + "Description[tr]": "Programlama sırasında verimliliği artıran çeşitli yardımcı araçlar koleksiyonu.", "Description[uk]": "Збірка різноманітних допоміжних програм, яка підвищує продуктивність програмування.", "Description[x-test]": "xxCollection of various utilities that increase productivity while programming.xx", "Description[zh_CN]": "多种提升编程生产力的工具集合。", "Icon": "help-hint", "Id": "kdevcodeutils", "Name": "Code Utilities", + "Name[ar]": "أدوات الشِّفرات", + "Name[bs]": "Kodni alati", "Name[ca@valencia]": "Utilitats de codi", "Name[ca]": "Utilitats de codi", + "Name[da]": "Kodeværktøjer", "Name[de]": "Quelltext-Werkzeuge", - "Name[en_GB]": "Code Utilities", + "Name[el]": "Βοηθητικά προγράμματα", "Name[es]": "Utilidades de código fuente", "Name[et]": "Kooditööriistad", "Name[fi]": "Koodityökalut", "Name[gl]": "Utilidades de código", + "Name[hu]": "Kód segédprogramok", "Name[it]": "Utilità per il codice", + "Name[kk]": "Код утилиталары", "Name[nb]": "Kodeverktøy", + "Name[nds]": "Kode-Warktüüch", "Name[nl]": "Hulpmiddelen bij coderen", "Name[pl]": "Narzędzia kodu", "Name[pt]": "Utilitários de Código", "Name[pt_BR]": "Utilitários de Código", + "Name[ru]": "Утилиты для работы с кодом", "Name[sk]": "Nástroje kódu", "Name[sl]": "Pripomočki za kodo", "Name[sv]": "Kodverktyg", + "Name[tr]": "Kod Araçları", + "Name[ug]": "كود قوراللىرى", "Name[uk]": "Допоміжні засоби", "Name[x-test]": "xxCode Utilitiesxx", "Name[zh_CN]": "代码工具", + "Name[zh_TW]": "寫程式實用工具", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/contextbrowser/kdevcontextbrowser.json b/plugins/contextbrowser/kdevcontextbrowser.json --- a/plugins/contextbrowser/kdevcontextbrowser.json +++ b/plugins/contextbrowser/kdevcontextbrowser.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Name": "David Nolden" + "Name": "David Nolden", + "Name[x-test]": "xxDavid Noldenxx" } ], "Category": "Core", "Description": "This plugin shows information about the current language context in a side view, and highlights relevant declarations and uses.", "Description[ca@valencia]": "Este connector mostra informació quant al context del llenguatge actual en una vista lateral i ressalta les declaracions i els usos apropiats.", "Description[ca]": "Aquest connector mostra informació quant al context del llenguatge actual en una vista lateral i ressalta les declaracions i els usos apropiats.", "Description[de]": "Dieses Modul zeigt Informationen über den aktuellen Sprachkontext an und hebt die wichtigen Deklarationen und Vorkommen hervor.", - "Description[en_GB]": "This plugin shows information about the current language context in a side view, and highlights relevant declarations and uses.", "Description[es]": "Este complemento muestra información de contexto sobre el lenguaje actual en una vista lateral, resaltando declaraciones relevantes y sus usos.", - "Description[et]": "See plugin pakub külgvaates teavet aktiivse keele konteksti kohta ning tõstab esile asjakohased deklaratsioonid ja kasutused.", "Description[fi]": "Tämä liitännäinen näyttää tietoja nykyisestä kielikontekstista sivunäkymässä ja korostaa olennaisia esittelyjä ja käyttöjä.", "Description[gl]": "Este complemento mostra información acerca do contexto da linguaxe actual nunha vista lateral, e realza as declaracións e utilizacións relevantes.", "Description[it]": "Questa estensione mostra le informazioni sul contesto del linguaggio corrente in una vista laterale, mettendo in evidenza le dichiarazioni e gli usi.", @@ -23,34 +22,47 @@ "Description[sk]": "Tento plugin zobrazuje informácie o aktuálnom jazykovom kontexte v božnom pohľade, a zvýrazní relevantné deklarácie a použitia.", "Description[sl]": "Vstavek prikazuje podatke o trenutnem kontekstu jezika in poudari pomembne deklaracije in uporabe.", "Description[sv]": "Insticksprogrammet visar information om nuvarande språksammanhang i en sidovy, och markerar relevanta deklarationer och användningar.", + "Description[tr]": "Bu eklenti yan görünümde mevcut dil bağlamıyla ilgili bilgi gösterir, ve ilgili tanımlamaları ve kullanımları vurgular.", "Description[uk]": "За допомогою цього додатка можна переглянути у перегляді на бічній панелі відомості про поточний контекст мови, а також підсвітити пов’язані оголошення і випадки використання.", "Description[x-test]": "xxThis plugin shows information about the current language context in a side view, and highlights relevant declarations and uses.xx", "Description[zh_CN]": "此插件在侧边视图中显示关于当前语言上下文的信息,并加亮突出相关的声明和调用。", "Icon": "code-context", "Id": "kdevcontextbrowser", "License": "GPL", "Name": "Code Browser", + "Name[ar]": "متصّفح الشِّفرة", + "Name[bg]": "Браузър за низове", + "Name[bs]": "Pregledač koda", "Name[ca@valencia]": "Navegador de codi", "Name[ca]": "Navegador de codi", "Name[cs]": "Prohlížeč kódu", + "Name[da]": "Kodebrowser", "Name[de]": "Quelltext-Browser", - "Name[en_GB]": "Code Browser", + "Name[el]": "Περιηγητής κώδικα", "Name[es]": "Navegador de código", "Name[et]": "Koodibrauser", "Name[fi]": "Koodiselain", "Name[gl]": "Navegador do código", + "Name[hu]": "Kódböngésző", "Name[it]": "Browser del codice", + "Name[kk]": "Код шолғышы", "Name[nb]": "Kodeleser", + "Name[nds]": "Kodekieker", "Name[nl]": "Broncode-browser", + "Name[pa]": "ਕੋਡ ਬਰਾਊਜ਼ਰ", "Name[pl]": "Przeglądarka kodu", "Name[pt]": "Navegador do Código", "Name[pt_BR]": "Navegador de código", + "Name[ru]": "Навигация по коду", "Name[sk]": "Prehliadač kódu", "Name[sl]": "Brskalnik po kodi", "Name[sv]": "Kodbläddrare", + "Name[tr]": "Kod Tarayıcı", + "Name[ug]": "كود كۆرگۈ", "Name[uk]": "Переглядач коду", "Name[x-test]": "xxCode Browserxx", "Name[zh_CN]": "代码浏览器", + "Name[zh_TW]": "源碼瀏覽器", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/cvs/kdevcvs.json b/plugins/cvs/kdevcvs.json --- a/plugins/cvs/kdevcvs.json +++ b/plugins/cvs/kdevcvs.json @@ -2,18 +2,18 @@ "KPlugin": { "Authors": [ { - "Name": "Robert Gruber" + "Name": "Robert Gruber", + "Name[x-test]": "xxRobert Gruberxx" } ], "Category": "Version Control", "Description": "This plugin integrates CVS to KDevelop", + "Description[ar]": "تكامل هذه الملحقة CVS بِمطوّرك", "Description[ca@valencia]": "Este connector integra CVS al KDevelop", "Description[ca]": "Aquest connector integra CVS al KDevelop", "Description[cs]": "Tento modul integruje podporu pro CVS v KDevelop", "Description[de]": "Dieses Modul integriert CVS in KDevelop.", - "Description[en_GB]": "This plugin integrates CVS to KDevelop", "Description[es]": "Este complemento integra CVS en KDevelop", - "Description[et]": "See plugin lõimib CVS-i KDevelopiga", "Description[fi]": "Tämä liitännäinen integroi CVS:n KDevelopiin", "Description[gl]": "Este complemento integra CVS en KDevelop", "Description[it]": "Questa estensione integra CVS in KDevelop", @@ -24,34 +24,48 @@ "Description[sk]": "Tento plugin integruje CVS do KDevelop.", "Description[sl]": "Vstavek v KDevelop vgradi CVS", "Description[sv]": "Insticksprogrammet integrerar CVS i KDevelop", + "Description[tr]": "Bu eklenti CVS'i KDevelop içine bütünleştirir", "Description[uk]": "За допомогою цього додатка можна інтегрувати CVS до KDevelop", "Description[x-test]": "xxThis plugin integrates CVS to KDevelopxx", "Description[zh_CN]": "此插件将 CVS 整合到 KDevelop", "Icon": "cervisia", "Id": "kdevcvs", "License": "GPL", "Name": "CVS Support", + "Name[ar]": "دعم CVS", + "Name[bg]": "Поддръжка на CVS", + "Name[bs]": "CVS Podrška", "Name[ca@valencia]": "Implementació de CVS", "Name[ca]": "Implementació de CVS", "Name[cs]": "Podpora CVS", + "Name[da]": "CVS-understøttelse", "Name[de]": "CVS-Unterstützung", - "Name[en_GB]": "CVS Support", + "Name[el]": "Υποστήριξη CVS", "Name[es]": "Implementación de CVS", "Name[et]": "CVS-i toetus", "Name[fi]": "CVS-tuki", + "Name[ga]": "Tacaíocht CVS", "Name[gl]": "Soporte de CVS", + "Name[hu]": "CVS támogatás", "Name[it]": "Supporto CVS", + "Name[kk]": "CVS қолдауы", "Name[nb]": "CVS-støtte", + "Name[nds]": "CVS-Ünnerstütten", "Name[nl]": "CVS-ondersteuning", + "Name[pa]": "CVS ਸਹਿਯੋਗ", "Name[pl]": "Obsługa CVS", "Name[pt]": "Suporte para o CVS", "Name[pt_BR]": "Suporte a CVS", + "Name[ru]": "Поддержка CVS", "Name[sk]": "Podpora CVS", "Name[sl]": "Podpora za CVS", "Name[sv]": "Stöd för CVS", + "Name[tr]": "CVS Desteği", + "Name[ug]": "CVS قوللىشى", "Name[uk]": "Підтримка CVS", "Name[x-test]": "xxCVS Supportxx", "Name[zh_CN]": "CVS 支持", + "Name[zh_TW]": "CVS 支援", "ServiceTypes": [ "KDevelop/Plugin" ], diff --git a/plugins/documentswitcher/kdevdocumentswitcher.json b/plugins/documentswitcher/kdevdocumentswitcher.json --- a/plugins/documentswitcher/kdevdocumentswitcher.json +++ b/plugins/documentswitcher/kdevdocumentswitcher.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Name": "Andreas Pakulat" + "Name": "Andreas Pakulat", + "Name[x-test]": "xxAndreas Pakulatxx" } ], "Category": "Utilities", "Description": "A most-recently-used document switcher for KDevPlatform.", "Description[ca@valencia]": "Un commutador del document usat més recentment per KDevPlatform.", "Description[ca]": "Un commutador del document usat més recentment per KDevPlatform.", "Description[de]": "Ein Umschalter zwischen zuletzt geöffneten Dokumenten für KDevPlatform.", - "Description[en_GB]": "A most-recently-used document switcher for KDevPlatform.", "Description[es]": "Un cambiador de documentos recientemente usados para KDevPlatform.", - "Description[et]": "KDevPlatformi viimati kasutatud dokumentide vahetaja", "Description[fi]": "Vaihtaa tiedostoja niiden käyttöjärjestyksen perusteella", "Description[gl]": "Un selector entre documentos empregados recentemente para KDevPlatform.", "Description[it]": "Uno scambia documento utilizzato più di recente per KDevPlatform.", @@ -23,38 +22,49 @@ "Description[sk]": "Prepínač posledných použitých dokumentov pre KDevPlatform.", "Description[sl]": "Vstavek za preklapljanje med nazadnje uporabljenimi dokumenti.", "Description[sv]": "Byte till senast använda dokument för KDevelop-plattformen.", + "Description[tr]": "KDevPlatform için en-son-kullanılan belge seçici bir eklenti.", "Description[uk]": "Перемикач останніх використаних документів для KDevPlatform.", "Description[x-test]": "xxA most-recently-used document switcher for KDevPlatform.xx", "Description[zh_CN]": "KDevPlatform 的最近经常使用文档的切换器。", "Icon": "document-open-recent", "Id": "kdevdocumentswitcher", "License": "GPL", "Name": "Most-Recently-Used Document Switcher", + "Name[ar]": "مبدّل المستندات المستخدمة-حديثًا", + "Name[bg]": "Последният използван превключвател на документи", + "Name[bs]": "Mjenjač zadnjeg korištenog dokumenta", "Name[ca@valencia]": "Commutador del document usat més recentment", "Name[ca]": "Commutador del document usat més recentment", + "Name[da]": "Dokumentskifter til nyligt anvendte", "Name[de]": "Zuletzt-Verwendet-Dokumentumschalter", - "Name[en_GB]": "Most-Recently-Used Document Switcher", + "Name[el]": "Εναλλάκτης μεταξύ πρόσφατα χρησιμοποιημένων εγγράφων", "Name[es]": "Cambiador del documento usado más recientemente", "Name[et]": "Viimati kasutatud dokumentide vahetaja", "Name[fi]": "Viimeksi käytetty ensin -tiedostovaihtaja", "Name[gl]": "Selector entre documentos empregados recentemente", + "Name[hu]": "Dokumentumváltó", "Name[it]": "Scambia documento utilizzato più di recente", + "Name[kk]": "Жуырда қолданған құжаттар ауыстырғышы", "Name[nb]": "Sist-brukte dokumentbytter", + "Name[nds]": "Togrieper för de tolest bruukten Dokmenten", "Name[nl]": "Meest-recent-gebruikte documentwisselaar", "Name[pl]": "Przełączanie między ostatnio używanymi dokumentami", "Name[pt]": "Selector dos Documentos Usados Mais Recentemente", "Name[pt_BR]": "Seletor dos Documentos Usados Mais Recentemente", + "Name[ru]": "Переключатель недавних документов", "Name[sk]": "Prepínač posledných použitých dokumentov", "Name[sl]": "Preklapljanje med nazadnje uporabljenimi dokumenti", "Name[sv]": "Byte till senast använda dokument", + "Name[tr]": "Yakın Zamanda En Çok Kullanılan Belgeleri Seçici", "Name[uk]": "Перемикач нещодавно використаних документів", "Name[x-test]": "xxMost-Recently-Used Document Switcherxx", "Name[zh_CN]": "最近经常使用文档切换器", + "Name[zh_TW]": "最近使用的文件切換器", "ServiceTypes": [ "KDevelop/Plugin" ], "Version": "0.1" }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/documentview/kdevdocumentview.json b/plugins/documentview/kdevdocumentview.json --- a/plugins/documentview/kdevdocumentview.json +++ b/plugins/documentview/kdevdocumentview.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Name": "Adam Treat" + "Name": "Adam Treat", + "Name[x-test]": "xxAdam Treatxx" } ], "Category": "Utilities", "Description": "This plugin displays a graphical view of all documents currently loaded and separates them by mimetype.", "Description[ca@valencia]": "Este connector mostra una visualització gràfica de tots els documents carregats actualment, separats per tipus MIME.", "Description[ca]": "Aquest connector mostra una visualització gràfica de tots els documents carregats actualment, separats per tipus MIME.", "Description[de]": "Dieses Modul zeigt alle aktuell geladenen Dokumente getrennt nach ihren MIME-Typen an.", - "Description[en_GB]": "This plugin displays a graphical view of all documents currently loaded and separates them by mimetype.", "Description[es]": "Este complemento muestra una vista gráfica de todos los documentos actualmente cargados y los separa por su tipo MIME.", - "Description[et]": "See plugin näitab graafiliselt kõiki laaditud dokumente ja eraldab need MIME tüübi alusel.", "Description[fi]": "Tämä liitännäinen näyttää kaikkien parhaillaan ladattujen tiedostojen graafisen näkymän ja erottelee ne MIME-tyypin perusteella.", "Description[gl]": "Este complemento mostra unha vista gráfica de todos os documentos que están cargados e sepáraos segundo o seu tipo mime.", "Description[it]": "Questa estensione mostra una vista grafica di tutti i documenti attualmente caricati e li separa per il tipo MIME.", @@ -23,39 +22,51 @@ "Description[sk]": "Tento plugin zobrazí grafický pohľad všetkých dokumentov aktuálne načítaných a rozdelí ich podľa mimetype.", "Description[sl]": "Ta vstavek prikazuje vse trenutno naložene dokumente in jih ločuje glede na vrsto MIME.", "Description[sv]": "Insticksprogrammet visar en grafisk vy av alla dokument som för närvarande har laddats och delar upp dem enligt Mime-typ.", + "Description[tr]": "Bu eklenti o anda yüklenmiş olan tüm belgeleri grafiksel bir görünümde gösterir ve mime türlerine göre ayırır.", "Description[uk]": "Цей додаток відображає у графічному вигляді всі відкриті документи і впорядковує їх за типом MIME.", "Description[x-test]": "xxThis plugin displays a graphical view of all documents currently loaded and separates them by mimetype.xx", "Description[zh_CN]": "此插件显示当前已装入文档的图形视图并按照 mime 类型分类。", "Icon": "document-preview", "Id": "kdevdocumentview", "License": "LGPL", "Name": "Document View", + "Name[bg]": "Изглед за документи", + "Name[bs]": "Pregled Dokumenta", "Name[ca@valencia]": "Visor de document", "Name[ca]": "Visor de document", "Name[cs]": "Pohled na dokumenty", + "Name[da]": "Dokumentvisning", "Name[de]": "Dokumentansicht", - "Name[en_GB]": "Document View", + "Name[el]": "Προβολή εγγράφου", "Name[es]": "Vista de documento", "Name[et]": "Dokumendivaade", "Name[fi]": "Tiedostonäkymä", + "Name[ga]": "Amharc Cáipéise", "Name[gl]": "Vista do documento", + "Name[hu]": "Dokumentumnézet", "Name[it]": "Vista documento", + "Name[kk]": "Құжат көрінісі", "Name[nb]": "Dokumentvisning", + "Name[nds]": "Dokmentenansicht", "Name[nl]": "Documentweergave", "Name[pl]": "Widok dokumentu", "Name[pt]": "Área de Documentos", "Name[pt_BR]": "Área de Documentos", + "Name[ru]": "Панель документов", "Name[sk]": "Pohľad na dokumenty", "Name[sl]": "Prikaz dokumentov", "Name[sv]": "Dokumentvisning", + "Name[tr]": "Belge Görünümü", + "Name[ug]": "پۈتۈك كۆرۈنۈشى", "Name[uk]": "Перегляд документів", "Name[x-test]": "xxDocument Viewxx", "Name[zh_CN]": "文档视图", + "Name[zh_TW]": "文件檢視", "ServiceTypes": [ "KDevelop/Plugin" ], "Version": "0.1" }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/execute/CMakeLists.txt b/plugins/execute/CMakeLists.txt --- a/plugins/execute/CMakeLists.txt +++ b/plugins/execute/CMakeLists.txt @@ -1,19 +1,15 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kdevexecute\") ########### next target ############### -set(kdevexecute_PART_UIS - nativeappconfig.ui -) - set(kdevexecute_PART_SRCS projecttargetscombobox.cpp executeplugin.cpp nativeappconfig.cpp nativeappjob.cpp ) -ki18n_wrap_ui( kdevexecute_PART_SRCS ${kdevexecute_PART_UIS} ) +ki18n_wrap_ui( kdevexecute_PART_SRCS nativeappconfig.ui) kdevplatform_add_plugin(kdevexecute JSON kdevexecute.json SOURCES ${kdevexecute_PART_SRCS}) diff --git a/plugins/execute/kdevexecute.json b/plugins/execute/kdevexecute.json --- a/plugins/execute/kdevexecute.json +++ b/plugins/execute/kdevexecute.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Name": "Hamish Rodda" + "Name": "Hamish Rodda", + "Name[x-test]": "xxHamish Roddaxx" } ], "Category": "Core", "Description": "This plugin allows running of programs with no instrumentor, ie. natively by the current host.", "Description[ca@valencia]": "Este connector permet executar programes sense «instrumentor», és a dir, nativament per a la màquina actual.", "Description[ca]": "Aquest connector permet executar programes sense «instrumentor», és a dir, nativament per a la màquina actual.", "Description[de]": "Dieses Modul erlaubt das Ausführen von Programmen im Kontext des Betriebssystems.", - "Description[en_GB]": "This plugin allows running of programs with no instrumentor, ie. natively by the current host.", "Description[es]": "Este complemento permite ejecutar programas sin instrumentador (es decir, de forma nativa) en la máquina actual.", - "Description[et]": "See plugin võimaldab panna programme aktiivses masinas tööle ilma instrumentaatorita, s.t loomulikult.", "Description[fi]": "Tämä liitännäinen mahdollistaa ohjelmien suorittamisen ilman välikappaletta, ts. natiivisti nykyisellä tietokoneella.", "Description[gl]": "Este complemento permite executar programas sen instrumentador, i.e. de xeito nativo na máquina actual.", "Description[it]": "Questa estensione permette l'esecuzione dei programmi senza instrumentor, vale a dire nativamente da parte dell'host attuale.", @@ -23,34 +22,47 @@ "Description[sk]": "Tento plugin umožňuje spustenie programov bez inštrumentora, teda natívne aktuálnym hostiteľom.", "Description[sl]": "Vstavek omogoča zaganjanje programov, za katere v KDevelop ni posebnega grafičnega vmesnika.", "Description[sv]": "Insticksprogrammet tillåter att program utan instrumentering körs, dvs. direkt av nuvarande värddator.", + "Description[tr]": "Bu eklenti programların ek araç olmadan çalıştırılabilmesini sağlar, örn. mevcut istemci ile doğal olarak.", "Description[uk]": "За допомогою цього додатка можна запускати програми безпосередньо на поточному вузлі.", "Description[x-test]": "xxThis plugin allows running of programs with no instrumentor, ie. natively by the current host.xx", "Description[zh_CN]": "此插件允许以无操作者方式运行程序,例如,当前主机的原生方式。", "Icon": "system-run", "Id": "kdevexecute", "License": "GPL", "Name": "Execute Programs", + "Name[ar]": "نفّذ برامجًا", + "Name[bg]": "Изпълняване на програми", + "Name[bs]": "Izvrši programe", "Name[ca@valencia]": "Executa programes", "Name[ca]": "Executa programes", "Name[cs]": "Spustit programy", + "Name[da]": "Kør programmer", "Name[de]": "Programme ausführen", - "Name[en_GB]": "Execute Programs", + "Name[el]": "Εκτέλεση προγραμμάτων", "Name[es]": "Ejecutar programas", "Name[et]": "Programmide täitmine", "Name[fi]": "Ohjelmien suorittaminen", + "Name[ga]": "Rith Ríomhchláir", "Name[gl]": "Executar programas", + "Name[hu]": "Programok végrehajtása", "Name[it]": "Esegui i programmi", + "Name[kk]": "Бағдарламаларды орындау", "Name[nb]": "Kjør programmer", + "Name[nds]": "Programmen utföhren", "Name[nl]": "Programma's uitvoeren", "Name[pl]": "Wykonaj programy", "Name[pt]": "Execução de Programas", - "Name[pt_BR]": "Executar programas", + "Name[pt_BR]": "Executar programa", + "Name[ru]": "Запуск программ", "Name[sk]": "Spustiť programy", "Name[sl]": "Izvedi programe", "Name[sv]": "Kör program", + "Name[tr]": "Uygulamaları Çalıştır", + "Name[ug]": "پروگرامما ئىجرا قىلىش", "Name[uk]": "Виконання програм", "Name[x-test]": "xxExecute Programsxx", "Name[zh_CN]": "执行程序", + "Name[zh_TW]": "執行程式", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/execute/nativeappconfig.h b/plugins/execute/nativeappconfig.h --- a/plugins/execute/nativeappconfig.h +++ b/plugins/execute/nativeappconfig.h @@ -39,14 +39,7 @@ QString title() const override; QIcon icon() const override; private slots: - void addDep(); - void removeDep(); - void moveDependencyUp(); - void moveDependencyDown(); void activateDeps( int ); - void checkActions( const QItemSelection& , const QItemSelection& ); - void depEdited( const QString& ); - void selectItemDialog(); }; class NativeAppLauncher : public KDevelop::ILauncher diff --git a/plugins/execute/nativeappconfig.cpp b/plugins/execute/nativeappconfig.cpp --- a/plugins/execute/nativeappconfig.cpp +++ b/plugins/execute/nativeappconfig.cpp @@ -82,7 +82,7 @@ executablePath->setUrl( pc->projects().isEmpty() ? QUrl() : pc->projects().at(0)->path().toUrl() ); } } - targetDependency->setSuggestion(project); + dependencies->setSuggestion(project); //executablePath->setFilter("application/x-executable"); @@ -97,19 +97,8 @@ environment->setCurrentProfile( cfg.readEntry( ExecutePlugin::environmentGroupEntry, QString() ) ); runInTerminal->setChecked( cfg.readEntry( ExecutePlugin::useTerminalEntry, false ) ); terminal->setEditText( cfg.readEntry( ExecutePlugin::terminalEntry, terminal->itemText(0) ) ); - QVariantList deps = KDevelop::stringToQVariant( cfg.readEntry( ExecutePlugin::dependencyEntry, QString() ) ).toList(); - QStringList strDeps; - foreach( const QVariant& dep, deps ) { - QStringList deplist = dep.toStringList(); - KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel(); - KDevelop::ProjectBaseItem* pitem=itemForPath(deplist, model); - QIcon icon; - if(pitem) - icon=QIcon::fromTheme(pitem->iconName()); - - QListWidgetItem* item = new QListWidgetItem(icon, KDevelop::joinWithEscaping( deplist, '/', '\\' ), dependencies ); - item->setData( Qt::UserRole, dep ); - } + dependencies->setDependencies(KDevelop::stringToQVariant( cfg.readEntry( ExecutePlugin::dependencyEntry, QString() ) ).toList()); + dependencyAction->setCurrentIndex( dependencyAction->findData( cfg.readEntry( ExecutePlugin::dependencyActionEntry, "Nothing" ) ) ); blockSignals( b ); } @@ -124,12 +113,6 @@ dependencyAction->setItemData(2, "Install" ); dependencyAction->setItemData(3, "SudoInstall" ); - addDependency->setIcon( QIcon::fromTheme(QStringLiteral("list-add")) ); - removeDependency->setIcon( QIcon::fromTheme(QStringLiteral("list-remove")) ); - moveDepUp->setIcon( QIcon::fromTheme(QStringLiteral("go-up")) ); - moveDepDown->setIcon( QIcon::fromTheme(QStringLiteral("go-down")) ); - browseProject->setIcon(QIcon::fromTheme(QStringLiteral("folder-document"))); - //Set workingdirectory widget to ask for directories rather than files workingDirectory->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly); @@ -145,125 +128,17 @@ connect( workingDirectory, &KUrlRequester::urlSelected, this, &NativeAppConfigPage::changed ); connect( workingDirectory->lineEdit(), &KLineEdit::textEdited, this, &NativeAppConfigPage::changed ); connect( environment, &EnvironmentSelectionWidget::currentProfileChanged, this, &NativeAppConfigPage::changed ); - connect( addDependency, &QPushButton::clicked, this, &NativeAppConfigPage::addDep ); - connect( addDependency, &QPushButton::clicked, this, &NativeAppConfigPage::changed ); - connect( removeDependency, &QPushButton::clicked, this, &NativeAppConfigPage::changed ); - connect( removeDependency, &QPushButton::clicked, this, &NativeAppConfigPage::removeDep ); - connect( moveDepDown, &QPushButton::clicked, this, &NativeAppConfigPage::changed ); - connect( moveDepUp, &QPushButton::clicked, this, &NativeAppConfigPage::changed ); - connect( moveDepDown, &QPushButton::clicked, this, &NativeAppConfigPage::moveDependencyDown ); - connect( moveDepUp, &QPushButton::clicked, this, &NativeAppConfigPage::moveDependencyUp ); - connect( dependencies->selectionModel(), &QItemSelectionModel::selectionChanged, this, &NativeAppConfigPage::checkActions ); connect( dependencyAction, static_cast(&KComboBox::currentIndexChanged), this, &NativeAppConfigPage::changed ); connect( runInTerminal, &QCheckBox::toggled, this, &NativeAppConfigPage::changed ); connect( terminal, &KComboBox::editTextChanged, this, &NativeAppConfigPage::changed ); connect( terminal, static_cast(&KComboBox::currentIndexChanged), this, &NativeAppConfigPage::changed ); connect( dependencyAction, static_cast(&KComboBox::currentIndexChanged), this, &NativeAppConfigPage::activateDeps ); - connect( targetDependency, &ProjectItemLineEdit::textChanged, this, &NativeAppConfigPage::depEdited); - connect( browseProject, &QPushButton::clicked, this, &NativeAppConfigPage::selectItemDialog); -} - - -void NativeAppConfigPage::depEdited( const QString& str ) -{ - int pos; - QString tmp = str; - addDependency->setEnabled( !str.isEmpty() - && ( !targetDependency->validator() - || targetDependency->validator()->validate( tmp, pos ) == QValidator::Acceptable ) ); + connect( dependencies, &DependenciesWidget::changed, this, &NativeAppConfigPage::changed ); } void NativeAppConfigPage::activateDeps( int idx ) { - browseProject->setEnabled( dependencyAction->itemData( idx ).toString() != QLatin1String("Nothing") ); dependencies->setEnabled( dependencyAction->itemData( idx ).toString() != QLatin1String("Nothing") ); - targetDependency->setEnabled( dependencyAction->itemData( idx ).toString() != QLatin1String("Nothing") ); -} - -void NativeAppConfigPage::checkActions( const QItemSelection& selected, const QItemSelection& unselected ) -{ - Q_UNUSED( unselected ); - qCDebug(PLUGIN_EXECUTE) << "checkActions"; - if( !selected.indexes().isEmpty() ) - { - qCDebug(PLUGIN_EXECUTE) << "have selection"; - Q_ASSERT( selected.indexes().count() == 1 ); - QModelIndex idx = selected.indexes().at( 0 ); - qCDebug(PLUGIN_EXECUTE) << "index" << idx; - moveDepUp->setEnabled( idx.row() > 0 ); - moveDepDown->setEnabled( idx.row() < dependencies->count() - 1 ); - removeDependency->setEnabled( true ); - } else - { - removeDependency->setEnabled( false ); - moveDepUp->setEnabled( false ); - moveDepDown->setEnabled( false ); - } -} - -void NativeAppConfigPage::moveDependencyDown() -{ - QList list = dependencies->selectedItems(); - if( !list.isEmpty() ) - { - Q_ASSERT( list.count() == 1 ); - QListWidgetItem* item = list.at( 0 ); - int row = dependencies->row( item ); - dependencies->takeItem( row ); - dependencies->insertItem( row+1, item ); - dependencies->selectionModel()->select( dependencies->model()->index( row+1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); - } -} - -void NativeAppConfigPage::moveDependencyUp() -{ - - QList list = dependencies->selectedItems(); - if( !list.isEmpty() ) - { - Q_ASSERT( list.count() == 1 ); - QListWidgetItem* item = list.at( 0 ); - int row = dependencies->row( item ); - dependencies->takeItem( row ); - dependencies->insertItem( row-1, item ); - dependencies->selectionModel()->select( dependencies->model()->index( row-1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); - } -} - -void NativeAppConfigPage::addDep() -{ - QIcon icon; - KDevelop::ProjectBaseItem* pitem = targetDependency->currentItem(); - if(pitem) - icon = QIcon::fromTheme(pitem->iconName()); - - QListWidgetItem* item = new QListWidgetItem(icon, targetDependency->text(), dependencies); - item->setData( Qt::UserRole, targetDependency->itemPath() ); - targetDependency->setText(QLatin1String("")); - addDependency->setEnabled( false ); - dependencies->selectionModel()->clearSelection(); - item->setSelected(true); -// dependencies->selectionModel()->select( dependencies->model()->index( dependencies->model()->rowCount() - 1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); -} - -void NativeAppConfigPage::selectItemDialog() -{ - if(targetDependency->selectItemDialog()) { - addDep(); - } -} - -void NativeAppConfigPage::removeDep() -{ - QList list = dependencies->selectedItems(); - if( !list.isEmpty() ) - { - Q_ASSERT( list.count() == 1 ); - int row = dependencies->row( list.at(0) ); - delete dependencies->takeItem( row ); - - dependencies->selectionModel()->select( dependencies->model()->index( row - 1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); - } } void NativeAppConfigPage::saveToConfiguration( KConfigGroup cfg, KDevelop::IProject* project ) const @@ -278,11 +153,7 @@ cfg.writeEntry( ExecutePlugin::useTerminalEntry, runInTerminal->isChecked() ); cfg.writeEntry( ExecutePlugin::terminalEntry, terminal->currentText() ); cfg.writeEntry( ExecutePlugin::dependencyActionEntry, dependencyAction->itemData( dependencyAction->currentIndex() ).toString() ); - QVariantList deps; - for( int i = 0; i < dependencies->count(); i++ ) - { - deps << dependencies->item( i )->data( Qt::UserRole ); - } + QVariantList deps = dependencies->dependencies(); cfg.writeEntry( ExecutePlugin::dependencyEntry, KDevelop::qvariantToString( QVariant( deps ) ) ); } @@ -298,7 +169,7 @@ QString NativeAppLauncher::description() const { - return QStringLiteral("Executes Native Applications"); + return i18n("Executes Native Applications"); } QString NativeAppLauncher::id() diff --git a/plugins/execute/nativeappconfig.ui b/plugins/execute/nativeappconfig.ui --- a/plugins/execute/nativeappconfig.ui +++ b/plugins/execute/nativeappconfig.ui @@ -20,7 +20,7 @@ - Project Target: + Project &Target: projectTargetRadio @@ -60,7 +60,7 @@ - Executable: + E&xecutable: executableRadio @@ -100,10 +100,13 @@ Behavior + + QFormLayout::ExpandingFieldsGrow + - Arguments: + Ar&guments: arguments @@ -123,7 +126,7 @@ - Working Directory: + Working &Directory: workingDirectory @@ -143,7 +146,7 @@ - Environment: + E&nvironment: environment @@ -250,7 +253,7 @@ - Action: + Act&ion: dependencyAction @@ -290,159 +293,41 @@ Targets: - - targetDependency - - - - - - false - - - Enter a dependency to add to the list - - - Enter a dependency to add to the list - - - true - - - - - - - false - - - - - - - false - - - Adds the listed target to the dependency list. - - - - - - - - - - false - - - List of indirect dependent targets. - - - This list should contain targets that the application does not directly depend on, but for which an action needs to be taken before running the application. - - - true - - - true - - - - - - - false - - - Removes the selected dependencies from the list. - - - - - - - - - - false - - - Move a dependency up in the list. - - - - - - - - - - false - - - Moves the selected dependency down in the list. - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + + 0 + 0 + + + + KUrlRequester + QWidget +
kurlrequester.h
+ 1 +
+ KComboBox QComboBox
kcombobox.h
- QLineEdit - QLineEdit -
klineedit.h
-
- - QListWidget - QListWidget -
klistwidget.h
-
- - KUrlRequester - QFrame -
kurlrequester.h
-
- KDevelop::EnvironmentSelectionWidget KComboBox
util/environmentselectionwidget.h
- ProjectItemLineEdit - QLineEdit -
project/projectitemlineedit.h
-
- ProjectTargetsComboBox QComboBox
projecttargetscombobox.h
@@ -452,18 +337,18 @@ QToolButton
shell/environmentconfigurebutton.h
+ + KDevelop::DependenciesWidget + QWidget +
project/widgets/dependencieswidget.h
+ 1 +
executablePath arguments workingDirectory environment - targetDependency - addDependency - dependencies - removeDependency - moveDepUp - moveDepDown diff --git a/plugins/executescript/kdevexecutescript.json b/plugins/executescript/kdevexecutescript.json --- a/plugins/executescript/kdevexecutescript.json +++ b/plugins/executescript/kdevexecutescript.json @@ -2,54 +2,66 @@ "KPlugin": { "Authors": [ { - "Name": "Niko Sams" + "Name": "Niko Sams", + "Name[x-test]": "xxNiko Samsxx" } ], "Description": "This plugin allows running of scripts.", + "Description[ar]": "تسمح هذه الملحقة بتنفيذ السّكرِبتات.", "Description[ca@valencia]": "Este connector permet executar scripts.", "Description[ca]": "Aquest connector permet executar scripts.", "Description[de]": "Dieses Modul ermöglicht das Ausführen von Skripten.", - "Description[en_GB]": "This plugin allows running of scripts.", "Description[es]": "Este complemento permite la ejecución de scripts.", - "Description[et]": "See plugin võimaldab käivitada skripte.", "Description[fi]": "Tämä liitännäinen mahdollistaa skriptien suorittamisen.", "Description[gl]": "Este complemento permite a execución de scripts.", "Description[it]": "Questa estensione permette l'esecuzione degli script.", "Description[nl]": "Deze plugin staat het uitvoeren van scripts toe.", "Description[pl]": "Wtyczka ta pozwala na uruchamianie skryptów.", "Description[pt]": "Este 'plugin' permite a execução de programas.", - "Description[pt_BR]": "Este plugin permite a execução de scripts.", + "Description[pt_BR]": "Este plugin permite a execução de programas.", "Description[sk]": "Tento plugin povoľuje spúšťanie skriptov.", "Description[sl]": "Ta vstavek omogoča zaganjanje skript.", "Description[sv]": "Insticksprogrammet gör det möjligt att köra skript.", + "Description[tr]": "Bu eklenti betiklerin çalıştırılmasını sağlar.", "Description[uk]": "За допомогою цього додатка можна запускати скрипти.", "Description[x-test]": "xxThis plugin allows running of scripts.xx", "Description[zh_CN]": "此插件可以执行脚本.", "Icon": "system-run", "Id": "kdevexecutescript", "License": "GPL", "Name": "Execute Scripts", + "Name[ar]": "نفّذ سكرِبتات", + "Name[bg]": "Изпълнение на скриптове", + "Name[bs]": "Izvrši skruptu", "Name[ca@valencia]": "Executa scripts", "Name[ca]": "Executa scripts", "Name[cs]": "Spustit skripty", + "Name[da]": "Kør scripts", "Name[de]": "Skripte ausführen", - "Name[en_GB]": "Execute Scripts", + "Name[el]": "Εκτέλεση σεναρίων", "Name[es]": "Ejecutar scripts", "Name[et]": "Skriptide käivitamine", "Name[fi]": "Skriptien suorittaminen", + "Name[ga]": "Rith Scripteanna", "Name[gl]": "Executar scripts", + "Name[hu]": "Parancsfájlok végrehajtása", "Name[it]": "Esegui script", + "Name[kk]": "Скрипттерді орындқу", "Name[nb]": "Kjør skripter", + "Name[nds]": "Skripten utföhren", "Name[nl]": "Scripts uitvoeren", "Name[pl]": "Wykonaj skrypty", "Name[pt]": "Executar Programas", - "Name[pt_BR]": "Executar scripts", + "Name[pt_BR]": "Executar os programas", + "Name[ru]": "Запуск сценариев", "Name[sk]": "Spustiť skripty", "Name[sl]": "Izvedi skripte", "Name[sv]": "Kör skript", + "Name[tr]": "Betikleri Çalıştır", "Name[uk]": "Виконання скриптів", "Name[x-test]": "xxExecute Scriptsxx", "Name[zh_CN]": "执行脚本", + "Name[zh_TW]": "執行文稿", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/externalscript/kdevexternalscript.json b/plugins/externalscript/kdevexternalscript.json --- a/plugins/externalscript/kdevexternalscript.json +++ b/plugins/externalscript/kdevexternalscript.json @@ -2,17 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "Milian Wolff" + "Name": "Milian Wolff", + "Name[x-test]": "xxMilian Wolffxx" } ], "Category": "Utilities", "Description": "Run external scripts or applications to manipulate the editor contents or do other arbitrary actions.", + "Description[ar]": "شغّل سكرِبتات أو تطبيقات خارجيّة للتّلاعب بمحتويات المحرّر أو عمل إجراءات اعتباطيّة أخرى.", "Description[ca@valencia]": "Executa scripts externs o aplicacions per a manipular el contingut de l'editor o altres accions arbitràries.", "Description[ca]": "Executa scripts externs o aplicacions per a manipular el contingut de l'editor o altres accions arbitràries.", "Description[de]": "Führen Sie externe Skripte oder Programme zum Verändern des Editorinhalts oder für beliebige andere Aktionen aus.", - "Description[en_GB]": "Run external scripts or applications to manipulate the editor contents or do other arbitrary actions.", "Description[es]": "Ejecutar scripts externos o aplicaciones para manipular el contenido del editor o realizar otras acciones.", - "Description[et]": "Välised skriptid või rakendused, mis võimaldavad muuta redaktori sisu või ette võtta mingeid muid toiminguid.", "Description[fi]": "Suorittaa ulkoisia skriptejä tai sovelluksia editorisisällön manipuloimiseksi tai muiden satunnaisten tehtävien tekemiseksi.", "Description[gl]": "Executa scripts externos ou programas para manipular os contidos do editor ou levar a cabo outras accións.", "Description[it]": "Eseguire script o applicazioni esterne per manipolare il contenuto dell'editor o per fare altre azioni.", @@ -23,34 +23,46 @@ "Description[sk]": "Spustí externé skripty alebo aplikácie na manipuláciu s obsahom editora alebo robí iné ľubovoľné akcie.", "Description[sl]": "Zaganjajte zunanje skripte ali programe, ki upravljajo z vsebino urejevalnika ali pa opravljajo druga poljubna dejanja.", "Description[sv]": "Kör externa skript eller program för att behandla editorns innehåll eller utför andra godtyckliga åtgärder.", + "Description[tr]": "Düzenleyici içeriğini değiştirmek veya diğer keyfi eylemler için dış betikler veya uygulamalar çalıştır.", "Description[uk]": "Запускає зовнішні скрипти або програми для обробки текстових даних редактора або виконання інших потрібних дій.", "Description[x-test]": "xxRun external scripts or applications to manipulate the editor contents or do other arbitrary actions.xx", "Description[zh_CN]": "运行外部脚本或应用程序来处理编辑器内容或者执行其它任意动作。", "Icon": "system-run", "Id": "kdevexternalscript", "License": "GPL", "Name": "External Scripts", + "Name[ar]": "سكرِبتات خارجيّة", + "Name[bg]": "Външни скриптове", + "Name[bs]": "Spoljnje skripte", "Name[ca@valencia]": "Scripts externs", "Name[ca]": "Scripts externs", "Name[cs]": "Externí skripty", + "Name[da]": "Eksterne scripts", "Name[de]": "Externe Skripte", - "Name[en_GB]": "External Scripts", + "Name[el]": "Εξωτερικά σενάρια", "Name[es]": "Scripts externos", "Name[et]": "Välised skriptid", "Name[fi]": "Ulkoiset skriptit", "Name[gl]": "Scripts externos", + "Name[hu]": "Külső parancsfájlok", "Name[it]": "Script esterni", + "Name[kk]": "Сыртқы скрипттер", "Name[nb]": "Eksterne skripter", + "Name[nds]": "Extern Skripten", "Name[nl]": "Externe scripts", "Name[pl]": "Zewnętrzne skrypty", "Name[pt]": "Programas Externos", "Name[pt_BR]": "Scripts externos", + "Name[ru]": "Внешние сценарии", "Name[sk]": "Externé skripty", "Name[sl]": "Zunanji skripti", "Name[sv]": "Externa skript", + "Name[tr]": "Dış Betikler", + "Name[ug]": "سىرتقى قوليازما پروگرامما", "Name[uk]": "Зовнішні скрипти", "Name[x-test]": "xxExternal Scriptsxx", "Name[zh_CN]": "外部脚本", + "Name[zh_TW]": "外部文稿", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/filemanager/kdevfilemanager.json b/plugins/filemanager/kdevfilemanager.json --- a/plugins/filemanager/kdevfilemanager.json +++ b/plugins/filemanager/kdevfilemanager.json @@ -2,18 +2,19 @@ "KPlugin": { "Authors": [ { - "Name": "Alexander Dymo" + "Name": "Alexander Dymo", + "Name[uk]": "Олександр Димо", + "Name[x-test]": "xxAlexander Dymoxx" } ], "Category": "Core", "Description": "This plugin brings a filemanager to KDevelop.", + "Description[ar]": "تجلب هذه الملحقة مدير ملفّات إلى مطوّرك.", "Description[ca@valencia]": "Este connector proporciona un gestor de fitxers al KDevelop.", "Description[ca]": "Aquest connector proporciona un gestor de fitxers al KDevelop.", "Description[cs]": "Tento modul do KDevelop přináší správce souborů.", "Description[de]": "Dieses Modul integriert einen Datei-Browser in KDevelop.", - "Description[en_GB]": "This plugin brings a filemanager to KDevelop.", "Description[es]": "Este complemento proporciona un gestor de archivos a KDevelop.", - "Description[et]": "See plugin võimaldab kasutada KDevelopis failihaldurit.", "Description[fi]": "Tämä liitännäinen tuo tiedostohallinnan KDevelopiin.", "Description[gl]": "Este complemento incorpora un xestor de ficheiros no KDevelop.", "Description[it]": "Questa estensione porta un gestore di file in KDevelop.", @@ -24,38 +25,51 @@ "Description[sk]": "Tento plugin prináša správcu súborov do KDevelop.", "Description[sl]": "Vstavek v KDevelop vgradi upravljalnika datotek.", "Description[sv]": "Insticksprogrammet integrerar en filhanterare i KDevelop.", + "Description[tr]": "Bu eklenti KDevelop için bir dosya yönetici sağlar.", "Description[uk]": "За допомогою цього додатка можна отримати доступ до менеджера файлів у KDevelop.", "Description[x-test]": "xxThis plugin brings a filemanager to KDevelop.xx", "Description[zh_CN]": "此插件为 KDevelop 提供了一个文件管理器。", "Icon": "system-file-manager", "Id": "kdevfilemanager", "License": "GPL", "Name": "KDE File Manager Integration", + "Name[ar]": "تكامل مدير ملفّات كدي", + "Name[ast]": "Integración col xestor de ficheros KDE", + "Name[bg]": "Интегриране на файлов манипулатор на KDE", + "Name[bs]": "KDe menadžer integracije datoteke", "Name[ca@valencia]": "Integració del gestor de fitxers del KDE", "Name[ca]": "Integració del gestor de fitxers del KDE", + "Name[da]": "Integration af KDE filhåndtering", "Name[de]": "Integration der KDE-Dateiverwaltung", - "Name[en_GB]": "KDE File Manager Integration", + "Name[el]": "Ενσωμάτωση διαχειριστή αρχείων του KDE", "Name[es]": "Integración del gestor de archivos de KDE", - "Name[et]": "KDE failihalduri lõimimine", + "Name[et]": "KDE lõimimine failihalduriga", "Name[fi]": "KDE-tiedostonhallintaintegrointi", "Name[gl]": "Integración co xestor de ficheiros do KDE", + "Name[hu]": "KDE fájlkezelő integráció", "Name[it]": "Integrazione gestore di file di KDE", + "Name[kk]": "KDE файл менеджерімен біріктіру", "Name[nb]": "Integrasjon med KDE filbehandler", + "Name[nds]": "KDE-Dateiplegerünnerstütten", "Name[nl]": "KDE Bestandsbeheerder-integratie", "Name[pl]": "Integracja zarządzania plikami KDE", "Name[pt]": "Integração com o Gestor de Ficheiros do KDE", "Name[pt_BR]": "Integração com o gerenciador de arquivos do KDE", + "Name[ru]": "Интеграция файлового менеджера KDE", "Name[sk]": "Integrácia správcu súborov KDE", "Name[sl]": "Vgradnja KDE-jevega upravljalnika datotek", "Name[sv]": "Integrering av KDE:s filhanterare", + "Name[tr]": "KDE Dosya Yöneticisi Bütünleşmesi", + "Name[ug]": "KDE ھۆججەت باشقۇرغۇنىڭ يۈرۈشلەشتۈرۈلۇشى", "Name[uk]": "Інтеграція засобу керування файлами KDE", "Name[x-test]": "xxKDE File Manager Integrationxx", "Name[zh_CN]": "KDE 文件管理器整合", + "Name[zh_TW]": "KDE 檔案管理員整合", "ServiceTypes": [ "KDevelop/Plugin" ], "Version": "0.1" }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/filetemplates/kdevfiletemplates.json b/plugins/filetemplates/kdevfiletemplates.json --- a/plugins/filetemplates/kdevfiletemplates.json +++ b/plugins/filetemplates/kdevfiletemplates.json @@ -2,17 +2,18 @@ "KPlugin": { "Authors": [ { - "Name": "Alexander Dymo" + "Name": "Alexander Dymo", + "Name[uk]": "Олександр Димо", + "Name[x-test]": "xxAlexander Dymoxx" } ], "Category": "Core", "Description": "Manages templates for source files", + "Description[ar]": "تدير قوالب الملفّات المصدريّة", "Description[ca@valencia]": "Gestiona les plantilles dels fitxers de codi font", "Description[ca]": "Gestiona les plantilles dels fitxers de codi font", "Description[de]": "Verwaltung von Vorlagen für Quelltextdateien", - "Description[en_GB]": "Manages templates for source files", "Description[es]": "Gestiona plantillas para los archivos de código fuente", - "Description[et]": "Lähtekoodi failide mallide haldamine", "Description[fi]": "Hallitsee lähdekooditiedostojen malleja", "Description[gl]": "Xestiona modelos para os ficheiros de fonte", "Description[it]": "Gestisce i modelli per i file sorgente", @@ -23,33 +24,42 @@ "Description[sk]": "Spravuje šablóny pre zdrojové súbory", "Description[sl]": "Upravlja predloge za datoteke z izvorno kodo", "Description[sv]": "Hanterar mallar för källkodsfiler", + "Description[tr]": "Kaynak dosyaları için şablonları yönetir", "Description[uk]": "Керування шаблонами для початкових файлів коду", "Description[x-test]": "xxManages templates for source filesxx", "Description[zh_CN]": "管理源文件的模板", "Icon": "code-class", "Id": "kdevfiletemplates", "License": "GPL", "Name": "File Templates Configuration", + "Name[ar]": "ضبط قوالب الملفّات", + "Name[bs]": "Konfiguracija predložaka datoteka", "Name[ca@valencia]": "Configuració de les plantilles de fitxer", "Name[ca]": "Configuració de les plantilles de fitxer", + "Name[da]": "Konfiguration af filskabeloner", "Name[de]": "Einrichtung der Dateivorlagen", - "Name[en_GB]": "File Templates Configuration", + "Name[el]": "Διαμόρφωση αρχείων templates", "Name[es]": "Configuración de las plantillas de archivos", "Name[et]": "Failimallide seadistamine", "Name[fi]": "Tiedostomallien asetukset", "Name[gl]": "Configuración dos modelos de ficheiros", + "Name[hu]": "Fájl sablonok beállítása", "Name[it]": "Configurazione dei file dei modelli", + "Name[kk]": "Файл үлгілерді баптау", "Name[nb]": "Oppsett av fil-maler", "Name[nl]": "Configuratie van sjabloonbestanden", "Name[pl]": "Ustawienia szablonów plików", "Name[pt]": "Configuração dos Modelos de Ficheiros", "Name[pt_BR]": "Configuração dos modelos de arquivos", + "Name[ru]": "Настройка шаблонов файлов", "Name[sk]": "Nastavenie šablón súborov", "Name[sl]": "Nastavitev predlog dokumentov", "Name[sv]": "Inställning av filmallar", + "Name[tr]": "Dosya Şablon Yapılandırması", "Name[uk]": "Налаштовування шаблонів файлів", "Name[x-test]": "xxFile Templates Configurationxx", "Name[zh_CN]": "文件模板配置", + "Name[zh_TW]": "檔案樣本設定", "ServiceTypes": [ "KDevelop/Plugin" ], diff --git a/plugins/genericprojectmanager/kdevgenericmanager.json b/plugins/genericprojectmanager/kdevgenericmanager.json --- a/plugins/genericprojectmanager/kdevgenericmanager.json +++ b/plugins/genericprojectmanager/kdevgenericmanager.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Name": "Milian Wolff" + "Name": "Milian Wolff", + "Name[x-test]": "xxMilian Wolffxx" } ], "Category": "Project Management", "Description": "Allow KDevelop to manage generic projects", "Description[ca@valencia]": "Permet al KDevelop gestionar projectes genèrics", "Description[ca]": "Permet al KDevelop gestionar projectes genèrics", "Description[de]": "Zum Verwalten allgemeiner Projekte in KDevelop", - "Description[en_GB]": "Allow KDevelop to manage generic projects", "Description[es]": "Permite que KDevelop use proyectos genéricos", - "Description[et]": "Võimaldab KDevelopil hallata üldisi projekte", "Description[fi]": "Sallii KDevelop-ohjelman hallita yleisiä projekteja", "Description[gl]": "Permítelle a KDevelop xestionar proxectos xenéricos", "Description[it]": "Permette a KDevelop di gestire progetti generici", @@ -23,32 +22,44 @@ "Description[sk]": "Povoliť KDevelopu spravovať všeobecné projekty", "Description[sl]": "Omogoča, da KDevelop upravlja splošne projekte", "Description[sv]": "Tillåter att KDevelop hanterar generella projekt", + "Description[tr]": "KDevelop'un genel projeleri yönetmesine izin ver", "Description[uk]": "За допомогою цього додатка можна увімкнути керування загальними проектами у KDevelop", "Description[x-test]": "xxAllow KDevelop to manage generic projectsxx", "Description[zh_CN]": "允许 KDevelop 管理常规工程", "Icon": "kdevelop", "Id": "KDevGenericManager", "Name": "Generic Project Manager", + "Name[bg]": "Най-общ манипулатор на проект", + "Name[bs]": "Menadžer za generisanje projekta", "Name[ca@valencia]": "Gestor de projectes genèric", "Name[ca]": "Gestor de projectes genèric", + "Name[da]": "Håndtering af generisk projekt", "Name[de]": "Allgemeine Projektverwaltung", - "Name[en_GB]": "Generic Project Manager", + "Name[el]": "Γενικευμένος διαχειριστής έργου", "Name[es]": "Gestor de proyectos genéricos", "Name[et]": "Üldine projektihaldur", "Name[fi]": "Yleinen projektinhallinta", "Name[gl]": "Xestor de proxectos xenérico", + "Name[hu]": "Általános projektkezelő", "Name[it]": "Gestore progetto generico", + "Name[kk]": "Жалпы жоба менеджері", "Name[nb]": "Generisk prosjektbehandler", + "Name[nds]": "Allmeen Projektpleger", "Name[nl]": "Generieke projectenbeheerder", + "Name[pa]": "ਆਮ ਪਰੋਜੈਕਟ ਮੈਨੇਜਰ", "Name[pl]": "Zwykłe zarządzanie projektami", "Name[pt]": "Gestor de Projectos Genérico", - "Name[pt_BR]": "Gerenciador de projetos genérico", + "Name[pt_BR]": "Gerenciador de projeto genérico", + "Name[ru]": "Управление произвольными проектами", "Name[sk]": "Všeobecný správca projektov", "Name[sl]": "Splošni upravljalnik projektov", "Name[sv]": "Generell projekthantering", + "Name[tr]": "Genel Proje Yönetici", + "Name[ug]": "ئادەتتىكى قۇرۇلۇش باشقۇرغۇچ", "Name[uk]": "Звичайний засіб керування проектом", "Name[x-test]": "xxGeneric Project Managerxx", "Name[zh_CN]": "常规工程管理器", + "Name[zh_TW]": "一般專案管理員", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/git/gitplugin.h b/plugins/git/gitplugin.h --- a/plugins/git/gitplugin.h +++ b/plugins/git/gitplugin.h @@ -140,8 +140,6 @@ bool hasModifications(const QDir& repository); bool hasModifications(const QDir& repo, const QUrl& file); - bool hasError() const override; - QString errorDescription() const override; void registerRepositoryForCurrentBranchChanges(const QUrl& repository) override; KDevelop::CheckInRepositoryJob* isInRepository(KTextEditor::Document* document) override; @@ -216,8 +214,6 @@ /** Tells if it's older than 1.7.0 or not */ bool m_oldVersion; - bool m_hasError; - QString m_errorDescription; KDirWatch* m_watcher; QList m_branchesChange; bool m_usePrefix; diff --git a/plugins/git/gitplugin.cpp b/plugins/git/gitplugin.cpp --- a/plugins/git/gitplugin.cpp +++ b/plugins/git/gitplugin.cpp @@ -181,16 +181,14 @@ : DistributedVersionControlPlugin(parent, QStringLiteral("kdevgit")), m_oldVersion(false), m_usePrefix(true) { if (QStandardPaths::findExecutable(QStringLiteral("git")).isEmpty()) { - m_hasError = true; - m_errorDescription = i18n("git is not installed"); + setErrorDescription(i18n("Unable to find git executable. Is it installed on the system?")); return; } KDEV_USE_EXTENSION_INTERFACE( KDevelop::IBasicVersionControl ) KDEV_USE_EXTENSION_INTERFACE( KDevelop::IDistributedVersionControl ) KDEV_USE_EXTENSION_INTERFACE( KDevelop::IBranchingVersionControl ) - m_hasError = false; setObjectName(QStringLiteral("Git")); DVcsJob* versionJob = new DVcsJob(QDir::tempPath(), this, KDevelop::OutputJob::Silent); @@ -1458,16 +1456,6 @@ return new GitVcsLocationWidget(parent); } -bool GitPlugin::hasError() const -{ - return m_hasError; -} - -QString GitPlugin::errorDescription() const -{ - return m_errorDescription; -} - void GitPlugin::registerRepositoryForCurrentBranchChanges(const QUrl& repository) { QDir dir = dotGitDirectory(repository); diff --git a/plugins/git/kdevgit.json b/plugins/git/kdevgit.json --- a/plugins/git/kdevgit.json +++ b/plugins/git/kdevgit.json @@ -3,18 +3,18 @@ "Authors": [ { "Email": "powerfox@kde.ru", - "Name": "Evgeniy Ivanov" + "Name": "Evgeniy Ivanov", + "Name[x-test]": "xxEvgeniy Ivanovxx" } ], "Category": "Version Control", "Description": "This plugin integrates Git to KDevelop", + "Description[ar]": "تكامل هذه الملحقة Git بِمطوّرك", "Description[ca@valencia]": "Este connector integra Git al KDevelop", "Description[ca]": "Aquest connector integra Git al KDevelop", "Description[cs]": "Tento modul integruje podporu pro Git v KDevelop", "Description[de]": "Dieses Modul integriert Git in KDevelop.", - "Description[en_GB]": "This plugin integrates Git to KDevelop", "Description[es]": "Este complemento integra Git en KDevelop", - "Description[et]": "See plugin lõimib Giti KDevelopiga", "Description[fi]": "Tämä liitännäinen integroi Git-ohjelman KDevelop-ympäristöön", "Description[fr]": "Ce module externe intègre la gestion de Git dans KDevelop", "Description[gl]": "Este complemento integra Git en KDevelop", @@ -26,34 +26,48 @@ "Description[sk]": "Tento plugin integruje GIT do KDevelop.", "Description[sl]": "Vstavek v KDevelop vgradi Git", "Description[sv]": "Insticksprogrammet integrerar Git i KDevelop", + "Description[tr]": "Bu eklenti Git'i KDevelop'a bütünleştirir", "Description[uk]": "Цей додаток інтегрує Git із KDevelop", "Description[x-test]": "xxThis plugin integrates Git to KDevelopxx", "Description[zh_CN]": "此插件对 KDevelop 整合 Git", "Icon": "git", "Id": "kdevgit", "License": "GPL", "Name": "Git Support", + "Name[ar]": "دعم Git", + "Name[bg]": "Поддръжка на Git", + "Name[bs]": "Git podrška", "Name[ca@valencia]": "Implementació de Git", "Name[ca]": "Implementació de Git", "Name[cs]": "Podpora Git", + "Name[da]": "Git-understøttelse", "Name[de]": "Git-Unterstützung", - "Name[en_GB]": "Git Support", + "Name[el]": "Υποστήριξη Git", "Name[es]": "Implementación de Git", "Name[et]": "Giti toetus", "Name[fi]": "Git-tuki", "Name[fr]": "Gestion de Git", + "Name[ga]": "Tacaíocht Git", "Name[gl]": "Soporte de GIT", + "Name[hu]": "Git támogatás", "Name[it]": "Supporto Git", - "Name[nl]": "Git-ondersteuning", + "Name[kk]": "Git қолдауы", + "Name[nds]": "Git-Ünnerstütten", + "Name[nl]": "Git ondersteuning", + "Name[pa]": "Git ਸਹਿਯੋਗ", "Name[pl]": "Obsługa Git", "Name[pt]": "Suporte para o Git", "Name[pt_BR]": "Suporte ao Git", + "Name[ru]": "Поддержка Git", "Name[sk]": "Podpora GIT", "Name[sl]": "Podpora za Git", "Name[sv]": "Stöd för Git", + "Name[tr]": "Git Desteği", + "Name[ug]": "Git قوللىشى", "Name[uk]": "Підтримка Git", "Name[x-test]": "xxGit Supportxx", "Name[zh_CN]": "Git 支持", + "Name[zh_TW]": "Git 支援", "ServiceTypes": [ "KDevelop/Plugin" ], diff --git a/plugins/grepview/grepviewplugin.cpp b/plugins/grepview/grepviewplugin.cpp --- a/plugins/grepview/grepviewplugin.cpp +++ b/plugins/grepview/grepviewplugin.cpp @@ -127,7 +127,7 @@ QList items = ctx->items(); // verify if there is only one folder selected if ((items.count() == 1) && (items.first()->folder())) { - QAction* action = new QAction( i18n( "Find/Replace in This Folder" ), this ); + QAction* action = new QAction( i18n( "Find/Replace in This Folder..." ), this ); action->setIcon(QIcon::fromTheme(QStringLiteral("edit-find"))); m_contextMenuDirectory = items.at(0)->folder()->path().toLocalFile(); connect( action, &QAction::triggered, this, &GrepViewPlugin::showDialogFromProject); @@ -138,7 +138,7 @@ if ( context->type() == KDevelop::Context::EditorContext ) { KDevelop::EditorContext *econtext = dynamic_cast(context); if ( econtext->view()->selection() ) { - QAction* action = new QAction(QIcon::fromTheme(QStringLiteral("edit-find")), i18n("&Find/Replace in Files"), this); + QAction* action = new QAction(QIcon::fromTheme(QStringLiteral("edit-find")), i18n("&Find/Replace in Files..."), this); connect(action, &QAction::triggered, this, &GrepViewPlugin::showDialogFromMenu); extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, action); } @@ -150,7 +150,7 @@ QMimeType mimetype = QMimeDatabase().mimeTypeForUrl(fcontext->urls().at(0)); static const QMimeType directoryMime = QMimeDatabase().mimeTypeForName(QStringLiteral("inode/directory")); if (mimetype == directoryMime) { - QAction* action = new QAction( i18n( "Find/Replace in This Folder" ), this ); + QAction* action = new QAction( i18n( "Find/Replace in This Folder..." ), this ); action->setIcon(QIcon::fromTheme(QStringLiteral("edit-find"))); m_contextMenuDirectory = fcontext->urls().at(0).toLocalFile(); connect( action, &QAction::triggered, this, &GrepViewPlugin::showDialogFromProject); diff --git a/plugins/grepview/kdevgrepview.json b/plugins/grepview/kdevgrepview.json --- a/plugins/grepview/kdevgrepview.json +++ b/plugins/grepview/kdevgrepview.json @@ -2,12 +2,11 @@ "KPlugin": { "Category": "Utilities", "Description": "Allows fast searching of multiple files using patterns or regular expressions. And allow to replace it too.", + "Description[ar]": "تسمح بالبحث السريع في ملفّات متعدّدة باستخدام أنماط أو تعابير نمطيّة. وتسمح بالاستبدال أيضًا.", "Description[ca@valencia]": "Permet la cerca ràpida de múltiples fitxers usant patrons o expressions regulars. I també permet substitucions.", "Description[ca]": "Permet la cerca ràpida de múltiples fitxers usant patrons o expressions regulars. I també permet substitucions.", "Description[de]": "Ermöglicht es, Dateien mit Hilfe von Mustern und regulären Ausdrücken zu durchsuchen bzw. Ersetzungen vorzunehmen.", - "Description[en_GB]": "Allows fast searching of multiple files using patterns or regular expressions. And allow to replace it too.", "Description[es]": "Permite la búsqueda rápida de múltiples archivos usando patrones o expresiones regulares. También permite realizar sustituciones.", - "Description[et]": "Lubab mustreid või regulaaravaldisi kasutades kiiresti paljudes failides teksti otsida, samuti asendada.", "Description[fi]": "Mahdollistaa nopean useiden tiedostojen etsinnän käyttäen malleja tai säännöllisiä lausekkeita. Sallii myös korvauksen.", "Description[gl]": "Permite facer unha procura rápida en varios ficheiros empregando padróns ou expresións regulares, e tamén realizar substitucións.", "Description[it]": "Consente la ricerca veloce di file multipli usando espressioni regolari o modelli. E consente anche di sostituirli.", @@ -18,36 +17,48 @@ "Description[sk]": "Umožní rýchle hľadanie viacerých súborov pomocou vzorov alebo regulárnych výrazov a umožní ich nahradiť.", "Description[sl]": "Omogoča hitro iskanje po več datotekah z uporabo vzorcev ali regularnih izrazov. Omogoča tudi zamenjave.", "Description[sv]": "Tillåter snabb sökning i flera filer med mönster eller reguljära uttryck, och tillåter dessutom ersättning.", + "Description[tr]": "Kalıplar veya düzenli ifadeler kullanarak birden çok dosyada hızlı aramaya izin verir. Yer değiştirmeye de izin verir.", "Description[uk]": "Надає можливості швидкого пошуку та заміни у декількох файлів на основі шаблонів або формальних виразів.", "Description[x-test]": "xxAllows fast searching of multiple files using patterns or regular expressions. And allow to replace it too.xx", "Description[zh_CN]": "可以用模式或正则表达式快速搜索多个文件,还可以替换。", "Icon": "kfind", "Id": "kdevgrepview", "Name": "Find/Replace In Files", + "Name[ar]": "اعثر واستبدل في الملفّات", + "Name[bg]": "Търсене и заместване във файлове", + "Name[bs]": "Nađi/zamijeni u datotekama", "Name[ca@valencia]": "Cerca i substitució en fitxers", "Name[ca]": "Cerca i substitució en fitxers", + "Name[da]": "Find/erstat i filer", "Name[de]": "In Dateien suchen/ersetzen", - "Name[en_GB]": "Find/Replace In Files", + "Name[el]": "Αναζήτηση/Αντικατάσταση σε αρχεία", "Name[es]": "Buscar/sustituir en archivos", "Name[et]": "Failides otsimine ja asendamine", "Name[fi]": "Etsi ja korvaa tiedostoista", "Name[gl]": "Procurar/Substituír nos ficheiros", + "Name[hu]": "Keresés/csere fájlokban", "Name[it]": "Trova/Sostituisci nei file", + "Name[kk]": "Файлдарда іздеу/ауыстыру", "Name[nb]": "Finn/erstatt i filer", + "Name[nds]": "Söken un Utwesseln in Dateien", "Name[nl]": "Zoeken/vervangen in bestanden", "Name[pl]": "Znajdź/zastąp w plikach", "Name[pt]": "Procurar/Substituir nos Ficheiros", "Name[pt_BR]": "Procurar/Substituir nos arquivos", + "Name[ru]": "Поиск/замена в файлах", "Name[sk]": "Hľadať/nahradiť v súboroch", "Name[sl]": "Najdi/zamenjaj v datotekah", "Name[sv]": "Sök eller ersätt i filer", + "Name[tr]": "Bu Dosyalarda Bul ve Değiştir", + "Name[ug]": "ھۆججەت ئىچىدىن ئىزدەش/ئالماشتۇرۇش", "Name[uk]": "Пошук або заміна у файлах", "Name[x-test]": "xxFind/Replace In Filesxx", "Name[zh_CN]": "在文件中查找/替换", + "Name[zh_TW]": "在檔案中尋找/取代", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/konsole/kdevkonsoleview.json b/plugins/konsole/kdevkonsoleview.json --- a/plugins/konsole/kdevkonsoleview.json +++ b/plugins/konsole/kdevkonsoleview.json @@ -2,12 +2,11 @@ "KPlugin": { "Category": "Utilities", "Description": "This plugin provides KDevelop with an embedded konsole for quick and easy command line access.", + "Description[ar]": "توفّر هذه الملحقة لمطوّرك كونسول مضمّن لوصول سريع وسهل لسطر الأوامر", "Description[ca@valencia]": "Este connector proporciona al KDevelop un Konsole incrustat per accedir de manera ràpida i fàcil a la línia d'ordes.", "Description[ca]": "Aquest connector proporciona al KDevelop un Konsole incrustat per accedir de manera ràpida i fàcil a la línia d'ordres.", "Description[de]": "Dieses Modul stattet KDevelop mit einer eingebetteten Konsole zum einfachen Zugriff auf die Befehlszeile aus.", - "Description[en_GB]": "This plugin provides KDevelop with an embedded konsole for quick and easy command line access.", "Description[es]": "Este complemento proporciona una consola integrada a KDevelop para acceder a la línea de órdenes de forma rápida y fácil.", - "Description[et]": "See plugin pakub KDevelopile põimitud konsooli käsurea kiireks ja lihtsaks kasutamiseks.", "Description[fi]": "Tämä liitännäinen tarjoaa KDevelop-ohjelmalle upotetun pääteikkunan nopeaan ja helppoon komentorivityöskentelyyn.", "Description[gl]": "Este complemento fornécelle a KDevelop un konsole integrado para dispor de acceso rápido e sinxelo á liña de ordes.", "Description[it]": "Questa estensione dota KDevelop di una console integrata per una rapido e facile accesso alla riga di comando.", @@ -18,36 +17,48 @@ "Description[sk]": "Tento plugin poskytuje KDevelop so zabudovanou konzolou na rýchly a ľahký prístup k príkazovému riadku.", "Description[sl]": "Vstavek v KDevelop vgradi program Konsole za hiter in preprost dostop do ukazne vrstice.", "Description[sv]": "Insticksprogrammet ger KDevelop en inbyggd terminal för snabb och enkel åtkomst av kommandoraden.", + "Description[tr]": "Bu eklenti hızlı ve kolay komut satırı erişimi için KDevelop'a gömülü bir uçbirim sağlar.", "Description[uk]": "За допомогою цього додатка у KDevelop можна буде скористатися вбудованою konsole, яка пришвидшить і полегшить доступ до командного рядка.", "Description[x-test]": "xxThis plugin provides KDevelop with an embedded konsole for quick and easy command line access.xx", "Description[zh_CN]": "此插件为 KDevelop 提供了一个快速方便地访问命令行的嵌入式控制台。", "Icon": "utilities-terminal", "Id": "kdevkonsoleview", "Name": "Konsole Integration", + "Name[ar]": "تكامل كونسول", + "Name[bg]": "Интегриране на конзола", + "Name[bs]": "Integracija konzole", "Name[ca@valencia]": "Integració del Konsole", "Name[ca]": "Integració del Konsole", + "Name[da]": "Integration af Konsole", "Name[de]": "Konsole-Integration", - "Name[en_GB]": "Konsole Integration", + "Name[el]": "Ενσωμάτωση Konsole", "Name[es]": "Integración de la consola", "Name[et]": "Lõimimine Konsooliga", "Name[fi]": "Konsole-integraatio", "Name[gl]": "Integración con Konsole", + "Name[hu]": "Konsole integráció", "Name[it]": "Integrazione Konsole", + "Name[kk]": "Konsole біріктіруі", "Name[nb]": "Konsole-integrering", + "Name[nds]": "Konsool-Inbinnen", "Name[nl]": "Console-integratie", "Name[pl]": "Integracja Konsoli", "Name[pt]": "Integração com o Konsole", "Name[pt_BR]": "Integração com o Konsole", + "Name[ru]": "Интеграция Konsole", "Name[sk]": "Integrácia Konsole", "Name[sl]": "Vgradnja programa Konsole", "Name[sv]": "Integrering av Konsole", + "Name[tr]": "Konsole Bütünleşmesi", + "Name[ug]": "Konsole يۈرۈشلەشتۈرۈلۈشى", "Name[uk]": "Інтеграція з Konsole", "Name[x-test]": "xxKonsole Integrationxx", "Name[zh_CN]": "Konsole 整合", + "Name[zh_TW]": "Konsole 整合", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/konsole/kdevkonsoleviewplugin.h b/plugins/konsole/kdevkonsoleviewplugin.h --- a/plugins/konsole/kdevkonsoleviewplugin.h +++ b/plugins/konsole/kdevkonsoleviewplugin.h @@ -28,8 +28,6 @@ ~KDevKonsoleViewPlugin() override; void unload() override; - bool hasError() const override; - QString errorDescription() const override; KPluginFactory* konsoleFactory() const; diff --git a/plugins/konsole/kdevkonsoleviewplugin.cpp b/plugins/konsole/kdevkonsoleviewplugin.cpp --- a/plugins/konsole/kdevkonsoleviewplugin.cpp +++ b/plugins/konsole/kdevkonsoleviewplugin.cpp @@ -62,7 +62,9 @@ , m_konsoleFactory(konsoleFactory) , m_viewFactory(konsoleFactory ? new KDevKonsoleViewFactory(this) : nullptr) { - if (m_viewFactory) { + if(!m_viewFactory) { + setErrorDescription(i18n("Failed to load 'konsolepart' plugin")); + } else { core()->uiController()->addToolView(QStringLiteral("Konsole"), m_viewFactory); } } @@ -74,16 +76,6 @@ } } -bool KDevKonsoleViewPlugin::hasError() const -{ - return !m_viewFactory; -} - -QString KDevKonsoleViewPlugin::errorDescription() const -{ - return !m_viewFactory ? i18n("Failed to load 'konsolepart' plugin") : QString(); -} - KPluginFactory* KDevKonsoleViewPlugin::konsoleFactory() const { return m_konsoleFactory; diff --git a/plugins/openwith/kdevopenwith.json b/plugins/openwith/kdevopenwith.json --- a/plugins/openwith/kdevopenwith.json +++ b/plugins/openwith/kdevopenwith.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Name": "Andreas Pakulat" + "Name": "Andreas Pakulat", + "Name[x-test]": "xxAndreas Pakulatxx" } ], "Category": "Core", "Description": "This plugin allows one to open files with associated external applications.", "Description[ca@valencia]": "Este connector permet obrir fitxers amb les aplicacions externes associades.", "Description[ca]": "Aquest connector permet obrir fitxers amb les aplicacions externes associades.", "Description[de]": "Mit diesem Modul können Dateien mit ihnen zugewiesenen externen Anwendungen gestartet werden.", - "Description[en_GB]": "This plugin allows one to open files with associated external applications.", "Description[es]": "Este complemento permite abrir archivos con las aplicaciones externas asociadas.", - "Description[et]": "See plugin võimaldab avada väliste rakendustega seostatud faile.", "Description[fi]": "Tämä liitännäinen mahdollistaa ulkoisiin sovelluksiin liitettyjen tiedostojen avaamisen.", "Description[gl]": "Este complemento permítelle abrir ficheiros cos programas externos asociados.", "Description[nl]": "Deze plugin biedt u het openen van bestanden met geassocieerde externe toepassingen.", @@ -28,26 +27,38 @@ "Id": "kdevopenwith", "License": "GPL", "Name": "Open With", + "Name[ar]": "افتح بِـ", + "Name[bg]": "Отваряне с", + "Name[bs]": "Otvori pomoću", "Name[ca@valencia]": "Obri amb", "Name[ca]": "Obre amb", + "Name[da]": "Åbn med", "Name[de]": "Öffnen mit", - "Name[en_GB]": "Open With", + "Name[el]": "Άνοιγμα με", "Name[es]": "Abrir con", "Name[et]": "Avamine rakendusega", "Name[fi]": "Avaa ohjelmalla", "Name[gl]": "Abrir con", + "Name[hu]": "Megnyitás ezzel", "Name[it]": "Apri con", + "Name[kk]": "Мынамен ашу", + "Name[mr]": "यामध्ये उघडा", "Name[nb]": "Åpne med", + "Name[nds]": "Opmaken mit", "Name[nl]": "Openen met", "Name[pl]": "Otwórz za pomocą", "Name[pt]": "Abrir Com", "Name[pt_BR]": "Abrir com", + "Name[ru]": "Открыть с помощью", "Name[sk]": "Otvoriť s", "Name[sl]": "Odpri z", "Name[sv]": "Öppna med", + "Name[tr]": "Birlikte Aç", + "Name[ug]": "بۇنىڭدا ئېچىش", "Name[uk]": "Відкриття у зовнішніх програмах", "Name[x-test]": "xxOpen Withxx", "Name[zh_CN]": "打开方式", + "Name[zh_TW]": "開啟方式", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/outlineview/kdevoutlineview.json b/plugins/outlineview/kdevoutlineview.json --- a/plugins/outlineview/kdevoutlineview.json +++ b/plugins/outlineview/kdevoutlineview.json @@ -3,17 +3,16 @@ "Authors": [ { "Email": "arichardson.kde@gmail.com", - "Name": "Alex Richardson" + "Name": "Alex Richardson", + "Name[x-test]": "xxAlex Richardsonxx" } ], "Category": "Core", "Description": "This plugin provides a view to show the outline of the currently open document.", "Description[ca@valencia]": "Este connector proporciona una visualització que mostra una visió general del document obert actualment.", "Description[ca]": "Aquest connector proporciona una visualització que mostra una visió general del document obert actualment.", "Description[de]": "Dieses Modul zeigt eine Ansicht der Funktions-Kurzinfos im aktuell geöffneten Dokument.", - "Description[en_GB]": "This plugin provides a view to show the outline of the currently open document.", "Description[es]": "Este complemento proporciona una vista para mostrar el boceto del documento actualmente abierto.", - "Description[et]": "See plugin pakub parajasti avatud dokumendi struktuuri vaadet.", "Description[fi]": "Tämä liitännäinen tarjoaa näkymän, jossa näkyy tällä hetkellä avoimen tiedoston rakenne.", "Description[gl]": "Este complemento fornece unha vista para mostrar o esquema do documento actual.", "Description[nl]": "Deze plugin biedt zicht op de outline van het nu geopende document.", @@ -23,6 +22,7 @@ "Description[sk]": "Tento plugin poskytuje pohľad na zobrazenie obrysu aktuálne otvoreného dokumentu.", "Description[sl]": "Ta vstavek ponuja prikaz za oris trenutno odprtega dokumenta.", "Description[sv]": "Insticksprogrammet tillhandahåller en vy för att visa dispositionen av dokumentet som för närvarande är öppet.", + "Description[tr]": "Bu eklenti mevcut açık dosyanın çerçevesini görüntülemeyi sağlar.", "Description[uk]": "За допомогою цього додатка можна переглянути схему поточного відкритого документа.", "Description[x-test]": "xxThis plugin provides a view to show the outline of the currently open document.xx", "Description[zh_CN]": "此插件提供了一个当前显示当前打开文档的概要的视图。", @@ -33,18 +33,16 @@ "Name[ca@valencia]": "Visió general", "Name[ca]": "Visió general", "Name[de]": "Funktions-Kurzinfo", - "Name[en_GB]": "Outline", "Name[es]": "Boceto", - "Name[et]": "Struktuur", "Name[fi]": "Rakenne", "Name[gl]": "Esquema", - "Name[nl]": "Outline", "Name[pl]": "Zarys", "Name[pt]": "Visão Geral", "Name[pt_BR]": "Contorno", "Name[sk]": "Obrys", "Name[sl]": "Oris", "Name[sv]": "Disposition", + "Name[tr]": "Çerçeve", "Name[uk]": "Схема", "Name[x-test]": "xxOutlinexx", "Name[zh_CN]": "概要", diff --git a/plugins/patchreview/kdevpatchreview.json b/plugins/patchreview/kdevpatchreview.json --- a/plugins/patchreview/kdevpatchreview.json +++ b/plugins/patchreview/kdevpatchreview.json @@ -2,17 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "David Nolden" + "Name": "David Nolden", + "Name[x-test]": "xxDavid Noldenxx" } ], "Category": "Utilities", "Description": "This plugin allows reviewing patches directly in the editor.", + "Description[ar]": "تسمح هذه الملحقة بمراجعة الرّقعة مباشرةً في المحرّر.", "Description[ca@valencia]": "Este connector permet revisar pedaços directament en l'editor.", "Description[ca]": "Aquest connector permet revisar pedaços directament en l'editor.", "Description[de]": "Dieses Modul ermöglicht es, Patches direkt im Editor durchzusehen.", - "Description[en_GB]": "This plugin allows reviewing patches directly in the editor.", "Description[es]": "Este complemento permite la revisión de parches directamente en el editor.", - "Description[et]": "See plugin võimaldab paiku üle vaadata otse redaktoris.", "Description[fi]": "Tämä liitännäinen salli korjausten katselmoinnin suoraan editorissa.", "Description[gl]": "Este complemento permite revisar parches directamente no editor.", "Description[it]": "Questa estensione permette di rivedere le patch direttamente nell'editor.", @@ -23,39 +23,57 @@ "Description[sk]": "Tento plugin umožňuje zhodnotenie záplat priamo v editore.", "Description[sl]": "Vstavek omogoča pregled popravkov neposredno v urejevalniku.", "Description[sv]": "Insticksprogrammet gör det möjligt att direkt granska programfixar i editorn.", + "Description[tr]": "Bu eklenti yamaların doğrudan düzenleyici içerisinde gözden geçirilmesini sağlar.", "Description[uk]": "За допомогою цього додатка ви зможете рецензувати латки безпосередньо у редакторі.", "Description[x-test]": "xxThis plugin allows reviewing patches directly in the editor.xx", "Description[zh_CN]": "此插件允许在编辑器中直接审阅补丁。", "Icon": "applications-engineering", "Id": "kdevpatchreview", "License": "GPL", "Name": "Patch Review", + "Name[ar]": "مراجعة الرّقع", + "Name[bg]": "Преглед на кръпки", + "Name[bs]": "Pregled zakrpa", "Name[ca@valencia]": "Revisió del pedaç", "Name[ca]": "Revisió del pedaç", + "Name[da]": "Gennemgang af rettelser", "Name[de]": "Patch-Durchsicht", - "Name[en_GB]": "Patch Review", + "Name[el]": "Επιθεώρηση διορθώσεων", "Name[es]": "Revisión de parches", - "Name[et]": "Paikade läbivaatus", + "Name[et]": "Paikade ülevaatamine", "Name[fi]": "Korjauksen katselmointi", "Name[gl]": "Revisor de parches", + "Name[hu]": "Javítócsomag átnézés", "Name[it]": "Revisione patch", + "Name[kk]": "Жамау шолуы", "Name[nb]": "Lappegjennomgang", + "Name[nds]": "Plasternakiek", "Name[nl]": "Patchoverzicht", "Name[pl]": "Przeglądanie poprawek", "Name[pt]": "Revisão da Modificação", - "Name[pt_BR]": "Revisão da modificação", + "Name[pt_BR]": "Revisão da Modificação", + "Name[ru]": "Рецензирование патчей", "Name[sk]": "Zhodnotenie záplaty", "Name[sl]": "Pregled popravkov", "Name[sv]": "Granska programfixar", + "Name[tr]": "Yama Gözden Geçirmesi", + "Name[ug]": "ياماق باھالاش", "Name[uk]": "Рецензування латки", "Name[x-test]": "xxPatch Reviewxx", "Name[zh_CN]": "补丁审阅", + "Name[zh_TW]": "修補檢視", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Interfaces": [ - "org.kdevelop.IPatchReview" - ], - "X-KDevelop-Mode": "GUI" -} \ No newline at end of file + "org.kdevelop.IPatchReview", + "ILanguageSupport" + ], + "X-KDevelop-Language": "Diff", + "X-KDevelop-Mode": "GUI", + "X-KDevelop-SupportedMimeTypes": [ + "text/x-diff", + "text/x-patch" + ] +} diff --git a/plugins/patchreview/localpatchsource.cpp b/plugins/patchreview/localpatchsource.cpp --- a/plugins/patchreview/localpatchsource.cpp +++ b/plugins/patchreview/localpatchsource.cpp @@ -126,5 +126,5 @@ m_lpatch->setCommand(m_ui->command->text()); m_lpatch->setFilename(m_ui->filename->url()); m_lpatch->setBaseDir(m_ui->baseDir->url()); - m_lpatch->setAlreadyApplied(m_ui->applied->checkState() == Qt::Checked ); + m_lpatch->setAlreadyApplied(m_ui->applied->checkState() == Qt::Checked); } diff --git a/plugins/patchreview/patchhighlighter.h b/plugins/patchreview/patchhighlighter.h --- a/plugins/patchreview/patchhighlighter.h +++ b/plugins/patchreview/patchhighlighter.h @@ -47,7 +47,7 @@ { Q_OBJECT public: - PatchHighlighter( Diff2::DiffModel* model, KDevelop::IDocument* doc, PatchReviewPlugin* plugin ) throw( QString ); + PatchHighlighter( Diff2::DiffModel* model, KDevelop::IDocument* doc, PatchReviewPlugin* plugin, bool updatePatchFromEdits ) throw( QString ); ~PatchHighlighter() override; KDevelop::IDocument* doc(); QList< KTextEditor::MovingRange* > ranges() const; diff --git a/plugins/patchreview/patchhighlighter.cpp b/plugins/patchreview/patchhighlighter.cpp --- a/plugins/patchreview/patchhighlighter.cpp +++ b/plugins/patchreview/patchhighlighter.cpp @@ -441,12 +441,14 @@ } } -PatchHighlighter::PatchHighlighter( Diff2::DiffModel* model, IDocument* kdoc, PatchReviewPlugin* plugin ) throw( QString ) +PatchHighlighter::PatchHighlighter( Diff2::DiffModel* model, IDocument* kdoc, PatchReviewPlugin* plugin, bool updatePatchFromEdits ) throw( QString ) : m_doc( kdoc ), m_plugin( plugin ), m_model( model ), m_applying( false ) { KTextEditor::Document* doc = kdoc->textDocument(); // connect( kdoc, SIGNAL(destroyed(QObject*)), this, SLOT(documentDestroyed()) ); - connect(doc, &KTextEditor::Document::textInserted, this, &PatchHighlighter::textInserted); - connect(doc, &KTextEditor::Document::textRemoved, this, &PatchHighlighter::textRemoved); + if (updatePatchFromEdits) { + connect(doc, &KTextEditor::Document::textInserted, this, &PatchHighlighter::textInserted); + connect(doc, &KTextEditor::Document::textRemoved, this, &PatchHighlighter::textRemoved); + } connect(doc, &KTextEditor::Document::destroyed, this, &PatchHighlighter::documentDestroyed); if ( doc->lines() == 0 ) diff --git a/plugins/patchreview/patchreview.h b/plugins/patchreview/patchreview.h --- a/plugins/patchreview/patchreview.h +++ b/plugins/patchreview/patchreview.h @@ -19,6 +19,7 @@ #include #include +#include class PatchHighlighter; class PatchReviewToolViewFactory; @@ -45,10 +46,11 @@ class DiffSettings; class PatchReviewPlugin; -class PatchReviewPlugin : public KDevelop::IPlugin, public KDevelop::IPatchReview +class PatchReviewPlugin : public KDevelop::IPlugin, public KDevelop::IPatchReview, public KDevelop::ILanguageSupport { Q_OBJECT Q_INTERFACES( KDevelop::IPatchReview ) + Q_INTERFACES( KDevelop::ILanguageSupport ) public : explicit PatchReviewPlugin( QObject *parent, const QVariantList & = QVariantList() ); @@ -63,6 +65,14 @@ return m_modelList.data(); } + virtual QString name() const override { + return "diff"; + } + + virtual KDevelop::ParseJob *createParseJob(const KDevelop::IndexedString &) override { + return nullptr; + } + void seekHunk( bool forwards, const QUrl& file = QUrl() ); void setPatch( KDevelop::IPatchSource* patch ); diff --git a/plugins/patchreview/patchreview.cpp b/plugins/patchreview/patchreview.cpp --- a/plugins/patchreview/patchreview.cpp +++ b/plugins/patchreview/patchreview.cpp @@ -160,7 +160,7 @@ removeHighlighting( file ); - m_highlighters[file] = new PatchHighlighter( model, doc, this ); + m_highlighters[file] = new PatchHighlighter( model, doc, this, dynamic_cast(m_patch.data()) == nullptr ); } } catch ( const QString & str ) { qCDebug(PLUGIN_PATCHREVIEW) << "highlightFile():" << str; @@ -356,6 +356,15 @@ void PatchReviewPlugin::closeReview() { if( m_patch ) { + IDocument* patchDocument = ICore::self()->documentController()->documentForUrl( m_patch->file() ); + if (patchDocument) { + // Revert modifications to the text document which we've done in updateReview + patchDocument->setPrettyName( QString() ); + patchDocument->textDocument()->setReadWrite( true ); + KTextEditor::ModificationInterface* modif = dynamic_cast( patchDocument->textDocument() ); + modif->setModifiedOnDiskWarning( true ); + } + removeHighlighting(); m_modelList.reset( 0 ); m_depth = 0; @@ -366,8 +375,8 @@ } else emit patchChanged(); - Sublime::MainWindow* w = dynamic_cast( ICore::self()->uiController()->activeMainWindow() ); - if( w->area()->objectName() == QLatin1String("review") ) { + Sublime::Area* area = ICore::self()->uiController()->activeArea(); + if( area->objectName() == QLatin1String("review") ) { if( ICore::self()->documentController()->saveAllDocuments() ) ICore::self()->uiController()->switchToArea( QStringLiteral("code"), KDevelop::IUiController::ThisWindow ); } @@ -433,19 +442,24 @@ IDocument* futureActiveDoc = ICore::self()->documentController()->openDocument( m_patch->file() ); updateKompareModel(); + if ( !m_modelList || !futureActiveDoc || !futureActiveDoc->textDocument() ) { // might happen if e.g. openDocument dialog was cancelled by user // or under the theoretic possibility of a non-text document getting opened return; } + futureActiveDoc->textDocument()->setReadWrite( false ); futureActiveDoc->setPrettyName( i18n( "Overview" ) ); - - IDocument* buddyDoc = futureActiveDoc; - KTextEditor::ModificationInterface* modif = dynamic_cast( futureActiveDoc->textDocument() ); modif->setModifiedOnDiskWarning( false ); + Q_ASSERT( futureActiveDoc ); + ICore::self()->documentController()->activateDocument( futureActiveDoc ); + + PatchReviewToolView* toolView = qobject_cast(ICore::self()->uiController()->findToolView( i18n( "Patch Review" ), m_factory )); + Q_ASSERT( toolView ); + if( m_modelList->modelCount() < maximumFilesToOpenDirectly ) { //Open all relates files for( int a = 0; a < m_modelList->modelCount(); ++a ) { @@ -457,22 +471,13 @@ if( QFileInfo::exists( absoluteUrl.toLocalFile() ) && absoluteUrl.toLocalFile() != QLatin1String("/dev/null") ) { - buddyDoc = ICore::self()->documentController()->openDocument( absoluteUrl, KTextEditor::Range::invalid(), IDocumentController::DoNotActivate, QLatin1String(""), buddyDoc ); - - seekHunk( true, absoluteUrl ); //Jump to the first changed position + toolView->open( absoluteUrl, false ); }else{ // Maybe the file was deleted qCDebug(PLUGIN_PATCHREVIEW) << "could not open" << absoluteUrl << "because it doesn't exist"; } } } - - Q_ASSERT( futureActiveDoc ); - ICore::self()->documentController()->activateDocument( futureActiveDoc ); - - bool b = ICore::self()->uiController()->findToolView( i18n( "Patch Review" ), m_factory ); - Q_ASSERT( b ); - Q_UNUSED( b ); } void PatchReviewPlugin::setPatch( IPatchSource* patch ) { @@ -508,6 +513,7 @@ : KDevelop::IPlugin( QStringLiteral("kdevpatchreview"), parent ), m_patch( 0 ), m_factory( new PatchReviewToolViewFactory( this ) ) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IPatchReview ) + KDEV_USE_EXTENSION_INTERFACE( KDevelop::ILanguageSupport ) qRegisterMetaType( "const Diff2::DiffModel*" ); setXMLFile( QStringLiteral("kdevpatchreview.rc") ); @@ -543,7 +549,10 @@ // Only update if the url is not the patch-file, because our call to // the reload() KTextEditor function also causes this signal, // which would lead to an endless update loop. - if( m_patch && doc->url() != m_patch->file() ) + // Also, don't automatically update local patch sources, because + // they may correspond to static files which don't match any more + // after an edit was done. + if( m_patch && doc->url() != m_patch->file() && !dynamic_cast(m_patch.data()) ) forceUpdate(); } diff --git a/plugins/patchreview/patchreviewtoolview.h b/plugins/patchreview/patchreviewtoolview.h --- a/plugins/patchreview/patchreviewtoolview.h +++ b/plugins/patchreview/patchreviewtoolview.h @@ -40,6 +40,10 @@ PatchReviewToolView( QWidget* parent, PatchReviewPlugin* plugin ); ~PatchReviewToolView() override; + // opens the document which should be part of the patch, + // ensuring that the tabs are sorted correctly + void open( const QUrl& url, bool activate ) const; + signals: void dialogClosed( PatchReviewToolView* ); void stateChanged( PatchReviewToolView* ); @@ -71,8 +75,6 @@ private: void resizeEvent(QResizeEvent*) override; - void activate( const QUrl& url, KDevelop::IDocument* buddy = nullptr ) const; - void kompareModelChanged(); void showEditDialog(); diff --git a/plugins/patchreview/patchreviewtoolview.cpp b/plugins/patchreview/patchreviewtoolview.cpp --- a/plugins/patchreview/patchreviewtoolview.cpp +++ b/plugins/patchreview/patchreviewtoolview.cpp @@ -354,50 +354,71 @@ if(newUrl.isValid()) { - activate( newUrl, forwards ? current : 0 ); + open( newUrl, true ); }else{ qCDebug(PLUGIN_PATCHREVIEW) << "found no valid target url"; } } -void PatchReviewToolView::activate( const QUrl& url, IDocument* buddy ) const +void PatchReviewToolView::open( const QUrl& url, bool activate ) const { qCDebug(PLUGIN_PATCHREVIEW) << "activating url" << url; // If the document is already open in this area, just re-activate it if(KDevelop::IDocument* doc = ICore::self()->documentController()->documentForUrl(url)) { foreach(Sublime::View* view, ICore::self()->uiController()->activeArea()->views()) { if(view->document() == dynamic_cast(doc)) { - ICore::self()->documentController()->activateDocument(doc); + if (activate) { + ICore::self()->documentController()->activateDocument(doc); + } return; } } } - // If the document is not open yet, open it in the correct order - IDocument* newDoc = ICore::self()->documentController()->openDocument(url, KTextEditor::Range(), IDocumentController::DefaultMode, QString(), buddy); + QStandardItem* item = m_fileModel->itemForUrl( url ); + + IDocument* buddyDoc = nullptr; + + if (m_plugin->patch() && item) { + for (int preRow = item->row() - 1; preRow >= 0; --preRow) { + QStandardItem* preItem = m_fileModel->item(preRow); + if (!m_fileModel->isCheckable() || preItem->checkState() == Qt::Checked) { + // found valid predecessor, take it as buddy + buddyDoc = ICore::self()->documentController()->documentForUrl(preItem->index().data(VcsFileChangesModel::UrlRole).toUrl()); + if (buddyDoc) { + break; + } + } + } + if (!buddyDoc) { + buddyDoc = ICore::self()->documentController()->documentForUrl(m_plugin->patch()->file()); + } + } + + IDocument* newDoc = ICore::self()->documentController()->openDocument(url, KTextEditor::Range::invalid(), activate ? IDocumentController::DefaultMode : IDocumentController::DoNotActivate, QLatin1String(""), buddyDoc); + KTextEditor::View* view = 0; if(newDoc) - view= newDoc->activeTextView(); + view = newDoc->activeTextView(); if(view && view->cursorPosition().line() == 0) m_plugin->seekHunk( true, url ); } void PatchReviewToolView::fileItemChanged( QStandardItem* item ) { - if (item->column()!=0) + if (item->column() != 0 || !m_plugin->patch()) return; QUrl url = item->index().data(VcsFileChangesModel::UrlRole).toUrl(); if (url.isEmpty()) return; KDevelop::IDocument* doc = ICore::self()->documentController()->documentForUrl(url); if(m_fileModel->isCheckable() && item->checkState() != Qt::Checked) - { - // Eventually close the document + { // The file was deselected, so eventually close it if(doc && doc->state() == IDocument::Clean) { foreach(Sublime::View* view, ICore::self()->uiController()->activeArea()->views()) @@ -410,7 +431,8 @@ } } } else if (!doc) { - ICore::self()->documentController()->openDocument(url, KTextEditor::Range::invalid(), IDocumentController::DoNotActivate); + // Maybe the file was unchecked before, or it was just loaded. + open( url, false ); } } @@ -443,7 +465,7 @@ void PatchReviewToolView::fileDoubleClicked( const QModelIndex& idx ) { const QUrl file = idx.data(VcsFileChangesModel::UrlRole).toUrl(); - activate( file ); + open( file, true ); } void PatchReviewToolView::kompareModelChanged() { diff --git a/plugins/perforce/CMakeLists.txt b/plugins/perforce/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/plugins/perforce/CMakeLists.txt @@ -0,0 +1,14 @@ +add_subdirectory(p4clientstub) +add_subdirectory(test) + +set(kdevperforce_PART_SRCS + perforceplugin.cpp + perforcepluginmetadata.cpp +) + +kdevplatform_add_plugin(kdevperforce JSON kdevperforce.json SOURCES ${kdevperforce_PART_SRCS}) + +target_link_libraries(kdevperforce + KDev::Interfaces + KDev::Vcs +) diff --git a/plugins/perforce/debug.h b/plugins/perforce/debug.h new file mode 100644 --- /dev/null +++ b/plugins/perforce/debug.h @@ -0,0 +1,23 @@ +/*************************************************************************** + * Copyright 2010 Morten Danielsen Volden * + * * + * 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, see . * + ***************************************************************************/ +#ifndef PERFORCE_PLUGIN_DEBUG_H +#define PERFORCE_PLUGIN_DEBUG_H + +#include +Q_DECLARE_LOGGING_CATEGORY(PLUGIN_PERFORCE) + +#endif diff --git a/plugins/perforce/kdevperforce.json b/plugins/perforce/kdevperforce.json new file mode 100644 --- /dev/null +++ b/plugins/perforce/kdevperforce.json @@ -0,0 +1,105 @@ +{ + "GenericName": "Perforce VCS", + "GenericName[bg]": "Perforce VCS", + "GenericName[bs]": "Perforce VCS", + "GenericName[cs]": "Perforce VCS", + "GenericName[da]": "Perforce VCS", + "GenericName[de]": "Perforce VCS", + "GenericName[en_GB]": "Perforce VCS", + "GenericName[es]": "SCV Perforce", + "GenericName[et]": "Perforce'i versioonihaldussüsteem", + "GenericName[fi]": "Perforce-versionhallintajärjestelmä", + "GenericName[fr]": "VCS Perforce", + "GenericName[ga]": "Córas Rialaithe Leaganacha Perforce", + "GenericName[gl]": "Perforce VCS", + "GenericName[hu]": "Perforce VCS", + "GenericName[ko]": "Perforce VCS", + "GenericName[mr]": "परफोर्स व्हीसीएस", + "GenericName[nl]": "Perforce VCS", + "GenericName[pl]": "Perforce VCS", + "GenericName[pt]": "SCV Perforce", + "GenericName[pt_BR]": "VCS Perforce", + "GenericName[ro]": "Perforce VCS", + "GenericName[sk]": "Perforce VCS", + "GenericName[sv]": "Perforce versionskontrollsystem", + "GenericName[tr]": "Perforce VCS", + "GenericName[uk]": "СКВ Perforce", + "GenericName[x-test]": "xxPerforce VCSxx", + "GenericName[zh_CN]": "Perforce 版本控制系统", + "GenericName[zh_TW]": "Perforce VCS", + "KPlugin": { + "Authors": [ + { + "Name": "Morten Danielsen Volden" + } + ], + "Category": "Version Control", + "Description": "Provides Integration with Perforce Version Control System", + "Description[bg]": "Поддръжка на системата за управление на версии Perforce", + "Description[bs]": "Pruža integraciju Perforce sistemom kontrole verzija", + "Description[da]": "Giver integration med versionsstyringssystemet Perforce", + "Description[de]": "Stellt Integration mit dem Versionsverwaltungssystem Perforce zur Verfügung", + "Description[en_GB]": "Provides Integration with Perforce Version Control System", + "Description[es]": "Proporciona integración con el sistema de control de versiones Perforce", + "Description[et]": "Lõimimine versioonihaldussüsteemiga Perforce", + "Description[fi]": "Lisää integraation Perforce-versionhallintajärjestelmälle", + "Description[fr]": "Permet l'intégration avec le système de contrôle de versions Perforce", + "Description[gl]": "Fornece integración co sistema de control de versións Perforce", + "Description[hu]": "Integráció a Perforce verziókezelő rendszerrel", + "Description[ko]": "Perforce 버전 관리 시스템 통합 제공", + "Description[mr]": "परफोर्स आवृत्ती नियंत्रण प्रणाली बरोबर एकीकरण पुरवितो", + "Description[nl]": "Biedt ondersteuning voor Perforce versiecontrolesysteem", + "Description[pl]": "Dostarcza integrację z systemem kontroli wersji Perforce", + "Description[pt]": "Fornece a integração com o sistema de controlo de versões Perforce", + "Description[pt_BR]": "Fornece a integração com o sistema de controle de versões Perforce", + "Description[ro]": "Furnizează integrare cu Sistemul de Control al Versiunii Perforce", + "Description[sk]": "Poskytuje integráciu s verzionovacím systémom Perforce", + "Description[sv]": "Tillhandahåller integrering med Perforce versionskontrollsystem", + "Description[tr]": "Perforce Sürüm Denetim Sistemi ile Bütünleşme Sağlar", + "Description[uk]": "Забезпечує інтеграцію з системою керування версіями Perforce", + "Description[x-test]": "xxProvides Integration with Perforce Version Control Systemxx", + "Description[zh_CN]": "提供与 Perforce 版本控制系统的整合", + "Description[zh_TW]": "提供與 Perforce 版本控制系統的整合", + "Icon": "kdevelop", + "Id": "kdevperforce", + "License": "GPL", + "Name": "Perforce Support", + "Name[bg]": "Поддръжка на Perforce", + "Name[bs]": "Perforce podrška", + "Name[cs]": "Podpora Perforce", + "Name[da]": "Perforce-understøttelse", + "Name[de]": "Perforce-Unterstützung", + "Name[en_GB]": "Perforce Support", + "Name[es]": "Implementación de Perforce", + "Name[et]": "Perforce'i toetus", + "Name[fi]": "Perforce-tuki", + "Name[fr]": "Prise en charge de Perforce", + "Name[ga]": "Tacaíocht Perforce", + "Name[gl]": "Compatibilidade con Perforce", + "Name[hu]": "Perforce támogatás", + "Name[ko]": "Perforce 지원", + "Name[mr]": "परफोर्स समर्थन", + "Name[nds]": "Perforce-Ünnerstütten", + "Name[nl]": "Ondersteuning van Perforce", + "Name[pl]": "Obsługa Perforce", + "Name[pt]": "Suporte para Perforce", + "Name[pt_BR]": "Suporte para Perforce", + "Name[ro]": "Suport pentru Perforce", + "Name[sk]": "Podpora Perforce", + "Name[sv]": "Stöd för Perforce", + "Name[tr]": "Perforce Desteği", + "Name[uk]": "Підтримка Perforce", + "Name[x-test]": "xxPerforce Supportxx", + "Name[zh_CN]": "Perforce 支持", + "Name[zh_TW]": "Perforce 支援", + "ServiceTypes": [ + "KDevelop/Plugin" + ], + "Version": "5.0" + }, + "X-KDevelop-Category": "Global", + "X-KDevelop-Mode": "GUI", + "X-KDevelop-IRequired": [ + "org.kdevelop.IExecutePlugin" + ] +} diff --git a/plugins/perforce/p4clientstub/CMakeLists.txt b/plugins/perforce/p4clientstub/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/plugins/perforce/p4clientstub/CMakeLists.txt @@ -0,0 +1,9 @@ +project(p4clientstub) + +set(p4clientstub_SRCS main.cpp ) + +add_executable(p4clientstub ${p4clientstub_SRCS} ) + +target_link_libraries(p4clientstub + Qt5::Core +) diff --git a/plugins/perforce/p4clientstub/main.cpp b/plugins/perforce/p4clientstub/main.cpp new file mode 100644 --- /dev/null +++ b/plugins/perforce/p4clientstub/main.cpp @@ -0,0 +1,243 @@ +/*************************************************************************** + * Copyright 2013 Morten Danielsen Volden * + * * + * 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, see . * + ***************************************************************************/ + +#include +#include +#include + +bool validateNumberOfArguments(int argc, char** /*argv*/) +{ + if (argc < 3) { + return false; + } + + return true; +} + + +int fakeFstatOutput(QString const& filepath) +{ + QByteArray tmp = filepath.toUtf8(); + std::string fileText(tmp.constData(), tmp.size()); + std::cout << "... depotFile /" << fileText << std::endl;// /tools/test/new_file.txt" + std::cout << "... clientFile /home/projects" << fileText << std::endl; + std::cout << "... isMapped" << std::endl; + std::cout << "... headAction add" << std::endl; + std::cout << "... headType text" << std::endl; + std::cout << "... headTime 1285014691" << std::endl; + std::cout << "... headRev 1" << std::endl; + std::cout << "... headChange 759253" << std::endl; + std::cout << "... headModTime 1285014680" << std::endl; + std::cout << "... haveRev 1" << std::endl; + return 0; +} + +int fakeRevertOutput() +{ + return 0; +} + +int fakeSyncOutput() +{ + return 0; +} + +int fakeSubmitOutput() +{ + return 0; +} + +int fakeDiff2Output() +{ + return 0; +} + +int fakeDiffOutput() +{ + return 0; +} + +int fakeFileLogOutput(QString const& filepath) +{ + QByteArray tmp = filepath.toUtf8(); + std::string fileText(tmp.constData(), tmp.size()); + std::cout << "//depot/" << fileText << std::endl; + std::cout << "... #14 change 72 edit on 2013/02/04 15:38:35 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Log a little more out" << std::endl; + std::cout << std::endl; + std::cout << "... #13 change 67 edit on 2013/02/04 15:31:48 by mov@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Rename rand -> random_number" << std::endl; + std::cout << std::endl; + std::cout << "... #12 change 79 edit on 2013/01/29 18:02:33 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Prefer the use of std::string" << std::endl; + std::cout << std::endl; + std::cout << "... #11 change 33 edit on 2013/01/29 15:48:41 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Correct Test Class to use QString" << std::endl; + std::cout << std::endl; + std::cout << "... #10 change 76 edit on 2013/01/28 19:21:33 by vom@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Minor changes. Changed the log level of a couple of log lines." << std::endl; + std::cout << std::endl; + std::cout << "... #9 change 17 edit on 2013/01/22 15:41:16 by vom@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Just added a comment" << std::endl; + std::cout << std::endl; + std::cout << "... #8 change 97 edit on 2013/01/17 13:54:26 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Do not cleanup before we are absolutely done" << std::endl; + std::cout << std::endl; + std::cout << "... #7 change 12 edit on 2013/01/17 11:39:25 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Insert a little debugging in the test class. Be more defensive when dealing with iterators" << std::endl; + std::cout << std::endl; + std::cout << "... #6 change 60 edit on 2013/01/09 13:19:07 by vom@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " error and abort handling added to RingBuffer." << std::endl; + std::cout << std::endl; + std::cout << "... #5 change 30 edit on 2013/01/08 19:21:42 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Fix two things in cleanup. Fix item on the todo list, cleanup a map" << std::endl; + std::cout << std::endl; + std::cout << "... #4 change 27 edit on 2013/01/08 13:26:05 by vom@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Clean-up of persisted data on disk has been added" << std::endl; + std::cout << std::endl; + std::cout << "... #3 change 5 edit on 2012/12/28 13:04:16 by vom@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Support for multiple things added." << std::endl; + std::cout << std::endl; + std::cout << "... #2 change 6 edit on 2012/12/04 14:05:10 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Make Other test compile with new test class" << std::endl; + std::cout << std::endl; + std::cout << "... #1 change 1 add on 2012/12/04 13:48:25 by mvo@testbed (ktext)" << std::endl; + std::cout << std::endl; + std::cout << " Add RingBuffer" << std::endl; + std::cout << std::endl; + return 0; +} + +int fakeAnnotateOutput() +{ + std::cout << "1: #include \\\"RingBuffer.h\\\"" << std::endl; + std::cout << "1: #include \\\"inc/test/someClass.h\\\"" << std::endl; + std::cout << "1: //#include \\\"hejsa.h\\\"" << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: #include " << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: #include " << std::endl; + std::cout << "1: #include " << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: #include " << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: #include " << std::endl; + std::cout << "1: #include " << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: " << std::endl; + std::cout << "5: void fillBuffer( RingBuffer& myBuffer, std::vector& testVector )" << std::endl; + std::cout << "1: {" << std::endl; + std::cout << "1: uint64_t random_range( std::numeric_limits::max() );" << std::endl; + std::cout << "12: uint64_t random_number ( 0 );" << std::endl; + std::cout << "79: /// First fill the buffer" << std::endl; + std::cout << "1: for ( size_t i =0; i < RINGBUFFER_SIZE; ++i )" << std::endl; + std::cout << "1: {" << std::endl; + std::cout << "5: random_number = std::rand() % random_range;" << std::endl; + std::cout << "5: myBuffer.push_back ( random_number );" << std::endl; + std::cout << "5: testVector.push_back ( random_number );" << std::endl; + std::cout << "6: }" << std::endl; + std::cout << "76: }" << std::endl; + std::cout << "76: " << std::endl; + std::cout << "17: void testWithOnlyknown( RingBuffer& myBuffer, std::vector& testVector )" << std::endl; + std::cout << "17: {" << std::endl; + std::cout << "17: uint64_t random_range ( RINGBUFFER_SIZE );" << std::endl; + std::cout << "97: uint64_t random_number ( 0 );" << std::endl; + std::cout << "12: /// Perform the test run on values we have already inserted." << std::endl; + std::cout << "1: for ( size_t j =0; j < 1000000; ++j )" << std::endl; + std::cout << "1: {" << std::endl; + std::cout << "1: random_number = std::rand() % random_range;" << std::endl; + std::cout << "1: myBuffer.push_back ( testVector[random_number] );" << std::endl; + std::cout << "1: }" << std::endl; + std::cout << "67: " << std::endl; + std::cout << "67: }" << std::endl; + std::cout << "67: " << std::endl; + std::cout << "60: int main( int argc, char **argv )" << std::endl; + std::cout << "60: {" << std::endl; + std::cout << "27: RingBuffer myBuffer;" << std::endl; + std::cout << "1: std::vector testVector;" << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: std::srand( std::time ( 0 ) );" << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: fillBuffer( myBuffer, testVector );" << std::endl; + std::cout << "27: testWithOnlyknown( myBuffer, testVector );" << std::endl; + std::cout << "27: " << std::endl; + std::cout << "27: std::cout << \\\"Done Testing\\\" << std::endl;" << std::endl; + std::cout << "1: " << std::endl; + std::cout << "1: return 0;" << std::endl; + std::cout << "1: }" << std::endl; + return 0; +} + +int fakeEditOutput(QString const& filepath) +{ + QByteArray tmp = filepath.toUtf8(); + std::string fileText(tmp.constData(), tmp.size()); + std::cout << fileText << "#1 - opened for edit" << std::endl; + return 0; +} + +int fakeAddOutput(QString const& filepath) +{ + QByteArray tmp = filepath.toUtf8(); + std::string fileText(tmp.constData(), tmp.size()); + std::cout << fileText << "#1 - opened for add" << std::endl; + return 0; +} + +int main(int argc, char** argv) +{ + if (!validateNumberOfArguments(argc, argv)) { + std::cout << "Was not able to validate number of arguments: " << argc << std::endl; + return -1; + } + + if (qstrcmp(argv[1], "revert") == 0) { + return fakeRevertOutput(); + } else if (qstrcmp(argv[1], "sync") == 0) { + return fakeSyncOutput(); + } else if (qstrcmp(argv[1], "submit") == 0) { + return fakeSubmitOutput(); + } else if (qstrcmp(argv[1], "diff2") == 0) { + return fakeDiff2Output(); + } else if (qstrcmp(argv[1], "diff") == 0) { + return fakeDiffOutput(); + } else if (qstrcmp(argv[1], "filelog") == 0) { + return fakeFileLogOutput(argv[3]); + } else if (qstrcmp(argv[1], "annotate") == 0) { + return fakeAnnotateOutput(); + } else if (qstrcmp(argv[1], "edit") == 0) { + return fakeEditOutput(QString(argv[2])); + } else if (qstrcmp(argv[1], "fstat") == 0) { + return fakeFstatOutput(QString(argv[2])); + } else if (qstrcmp(argv[1], "add") == 0) { + return fakeAddOutput(QString(argv[2])); + } + return -1; +} diff --git a/plugins/perforce/perforceplugin.h b/plugins/perforce/perforceplugin.h new file mode 100644 --- /dev/null +++ b/plugins/perforce/perforceplugin.h @@ -0,0 +1,176 @@ +/*************************************************************************** + * Copyright 2010 Morten Danielsen Volden * + * * + * 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, see . * + ***************************************************************************/ + +#ifndef KDEVPERFORCEPLUGIN_H +#define KDEVPERFORCEPLUGIN_H + +#include +#include +#include +#include + + +#include +#include + +#include + +class QMenu; +class QFileInfo; +class QDir; + + +namespace KDevelop +{ +class ContextMenuExtension; +class VcsPluginHelper; +class DVcsJob; +} + + +class PerforcePlugin : public KDevelop::IPlugin, public KDevelop::ICentralizedVersionControl +{ + Q_OBJECT + Q_INTERFACES(KDevelop::IBasicVersionControl KDevelop::ICentralizedVersionControl) + + friend class PerforcePluginTest; +public: + PerforcePlugin(QObject* parent, const QVariantList & = QVariantList()); + ~PerforcePlugin() override; + + //@{ + /** Methods inherited from KDevelop::IBasicVersionControl */ + QString name() const override; + + KDevelop::VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; + + bool isVersionControlled(const QUrl& localLocation) override; + + KDevelop::VcsJob* repositoryLocation(const QUrl& localLocation) override; + + KDevelop::VcsJob* add(const QList& localLocations, + RecursionMode recursion = IBasicVersionControl::Recursive) override; + KDevelop::VcsJob* remove(const QList& localLocations) override; + + KDevelop::VcsJob* copy(const QUrl& localLocationSrc, + const QUrl& localLocationDstn) override; + KDevelop::VcsJob* move(const QUrl& localLocationSrc, + const QUrl& localLocationDst) override; + KDevelop::VcsJob* status(const QList& localLocations, + RecursionMode recursion = IBasicVersionControl::Recursive) override; + + KDevelop::VcsJob* revert(const QList& localLocations, + RecursionMode recursion = IBasicVersionControl::Recursive) override; + + KDevelop::VcsJob* update(const QList& localLocations, + const KDevelop::VcsRevision& rev = KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Head), + KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; + + KDevelop::VcsJob* commit(const QString& message, + const QList& localLocations, + KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; + + KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, + const KDevelop::VcsRevision& srcRevision, + const KDevelop::VcsRevision& dstRevision, + KDevelop::VcsDiff::Type = KDevelop::VcsDiff::DiffUnified, + KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; + + KDevelop::VcsJob* log(const QUrl& localLocation, + const KDevelop::VcsRevision& rev, + unsigned long limit = 0) override; + + KDevelop::VcsJob* log(const QUrl& localLocation, + const KDevelop::VcsRevision& rev = KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Base), + const KDevelop::VcsRevision& limit = KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Start)) override; + + KDevelop::VcsJob* annotate(const QUrl& localLocation, + const KDevelop::VcsRevision& rev = KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Head)) override; + + KDevelop::VcsJob* resolve(const QList& localLocations, + KDevelop::IBasicVersionControl::RecursionMode recursion) override; + + KDevelop::VcsJob* createWorkingCopy(const KDevelop::VcsLocation & sourceRepository, + const QUrl & destinationDirectory, + KDevelop::IBasicVersionControl::RecursionMode recursion = IBasicVersionControl::Recursive) override; + + + KDevelop::VcsLocationWidget* vcsLocation(QWidget* parent) const override; + //@} + + //@{ + /** Methods inherited from KDevelop::ICentralizedVersionControl */ + KDevelop::VcsJob* edit(const QUrl& localLocation) override; + + KDevelop::VcsJob* unedit(const QUrl& localLocation) override; + + KDevelop::VcsJob* localRevision(const QUrl& localLocation, + KDevelop::VcsRevision::RevisionType) override; + + KDevelop::VcsJob* import(const QString & commitMessage, + const QUrl & sourceDirectory, + const KDevelop::VcsLocation & destinationRepository) override; + //@} + + /// This plugin implements its own edit method + KDevelop::VcsJob* edit(const QList& localLocations); + + + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + + +public Q_SLOTS: + + /// invoked by context-menu + void ctxEdit(); +// void ctxUnedit(); +// void ctxLocalRevision(); +// void ctxImport(); + +private slots: + void parseP4StatusOutput(KDevelop::DVcsJob* job); + void parseP4DiffOutput(KDevelop::DVcsJob* job); + void parseP4LogOutput(KDevelop::DVcsJob* job); + void parseP4AnnotateOutput(KDevelop::DVcsJob* job); + + + +private: + bool isValidDirectory(const QUrl & dirPath); + KDevelop::DVcsJob* p4fstatJob(const QFileInfo& curFile, + KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); + + bool parseP4fstat(const QFileInfo& curFile, + KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); + + KDevelop::VcsJob* errorsFound(const QString& error, + KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); + + QString getRepositoryName(const QFileInfo& curFile); + + + void setEnvironmentForJob(KDevelop::DVcsJob* job, QFileInfo const& fsObject); + QList getQvariantFromLogOutput(QStringList const& outputLines); + + std::unique_ptr m_common; + QMenu* m_perforcemenu; + QString m_perforceConfigName; + QString m_perforceExecutable; + QAction* m_edit_action; +}; + +#endif // PERFORCEPLUGIN_H diff --git a/plugins/perforce/perforceplugin.cpp b/plugins/perforce/perforceplugin.cpp new file mode 100644 --- /dev/null +++ b/plugins/perforce/perforceplugin.cpp @@ -0,0 +1,696 @@ +/*************************************************************************** + * Copyright 2010 Morten Danielsen Volden * + * * + * 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, see . * + ***************************************************************************/ + +#include "perforceplugin.h" +#include "debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace KDevelop; + +namespace +{ +QString toRevisionName(const KDevelop::VcsRevision& rev, QString currentRevision=QString()) +{ + bool *ok(new bool()); + int previous = currentRevision.toInt(ok); + previous--; + QString tmp; + switch(rev.revisionType()) { + case VcsRevision::Special: + switch(rev.revisionValue().value()) { + case VcsRevision::Head: + return QStringLiteral("#head"); + case VcsRevision::Base: + return QStringLiteral("#have"); + case VcsRevision::Working: + return QStringLiteral("#have"); + case VcsRevision::Previous: + Q_ASSERT(!currentRevision.isEmpty()); + tmp.setNum(previous); + tmp.prepend("#"); + return tmp; + case VcsRevision::Start: + return QString(); + case VcsRevision::UserSpecialType: //Not used + Q_ASSERT(false && "i don't know how to do that"); + } + break; + case VcsRevision::GlobalNumber: + tmp.append("#"); + tmp.append(rev.revisionValue().toString()); + return tmp; + case VcsRevision::Date: + case VcsRevision::FileNumber: + case VcsRevision::Invalid: + case VcsRevision::UserSpecialType: + Q_ASSERT(false); + } + return QString(); +} + + +VcsItemEvent::Actions actionsFromString(QString const& changeDescription) +{ + if(changeDescription == "add") + return VcsItemEvent::Added; + if(changeDescription == "delete") + return VcsItemEvent::Deleted; + return VcsItemEvent::Modified; +} + +QDir urlDir(const QUrl& url) +{ + QFileInfo f(url.toLocalFile()); + if(f.isDir()) + return QDir(url.toLocalFile()); + else + return f.absoluteDir(); +} + +} + +Q_LOGGING_CATEGORY(PLUGIN_PERFORCE, "kdevplatform.plugins.perforce") + +PerforcePlugin::PerforcePlugin(QObject* parent, const QVariantList&): + KDevelop::IPlugin("kdevperforce", parent) + , m_common(new KDevelop::VcsPluginHelper(this, this)) + , m_perforcemenu(nullptr) + , m_perforceConfigName("p4config.txt") + , m_perforceExecutable("p4") + , m_edit_action(nullptr) +{ + QProcessEnvironment currentEviron(QProcessEnvironment::systemEnvironment()); + QString tmp(currentEviron.value("P4CONFIG")); + if (tmp.isEmpty()) { + // We require the P4CONFIG variable to be set because the perforce command line client will need it + setErrorDescription(i18n("The variable P4CONFIG is not set. Is perforce installed on the system?")); + return; + } else { + m_perforceConfigName = tmp; + } + qCDebug(PLUGIN_PERFORCE) << "The value of P4CONFIG is : " << tmp; + + KDEV_USE_EXTENSION_INTERFACE(KDevelop::IBasicVersionControl) + KDEV_USE_EXTENSION_INTERFACE(KDevelop::ICentralizedVersionControl) + +} + +PerforcePlugin::~PerforcePlugin() +{ +} + +QString PerforcePlugin::name() const +{ + return i18n("Perforce"); +} + +KDevelop::VcsImportMetadataWidget* PerforcePlugin::createImportMetadataWidget(QWidget* /*parent*/) +{ + return nullptr; +} + +bool PerforcePlugin::isValidDirectory(const QUrl & dirPath) +{ + const QFileInfo finfo(dirPath.toLocalFile()); + QDir dir = finfo.isDir() ? QDir(dirPath.toLocalFile()) : finfo.absoluteDir(); + + do { + if (dir.exists(m_perforceConfigName)) { + return true; + } + } while (dir.cdUp()); + return false; +} + +bool PerforcePlugin::isVersionControlled(const QUrl& localLocation) +{ + QFileInfo fsObject(localLocation.toLocalFile()); + if (fsObject.isDir()) { + return isValidDirectory(localLocation); + } + return parseP4fstat(fsObject, KDevelop::OutputJob::Silent); +} + +DVcsJob* PerforcePlugin::p4fstatJob(const QFileInfo& curFile, OutputJob::OutputJobVerbosity verbosity) +{ + DVcsJob* job = new DVcsJob(curFile.absolutePath(), this, verbosity); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "fstat" << curFile.fileName(); + return job; +} + +bool PerforcePlugin::parseP4fstat(const QFileInfo& curFile, OutputJob::OutputJobVerbosity verbosity) +{ + QScopedPointer job(p4fstatJob(curFile, verbosity)); + if (job->exec() && job->status() == KDevelop::VcsJob::JobSucceeded) { + qCDebug(PLUGIN_PERFORCE) << "Perforce returned: " << job->output(); + if (!job->output().isEmpty()) + return true; + } + return false; +} + +QString PerforcePlugin::getRepositoryName(const QFileInfo& curFile) +{ + static const QString DEPOT_FILE_STR("... depotFile "); + QString ret; + QScopedPointer job(p4fstatJob(curFile, KDevelop::OutputJob::Silent)); + if (job->exec() && job->status() == KDevelop::VcsJob::JobSucceeded) { + if (!job->output().isEmpty()) { + QStringList outputLines = job->output().split('\n', QString::SkipEmptyParts); + foreach(const QString & line, outputLines) { + int idx(line.indexOf(DEPOT_FILE_STR)); + if (idx != -1) { + ret = line.right(line.size() - DEPOT_FILE_STR.size()); + return ret; + } + } + } + } + + return ret; +} + +KDevelop::VcsJob* PerforcePlugin::repositoryLocation(const QUrl& /*localLocation*/) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::add(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + QFileInfo curFile(localLocations.front().toLocalFile()); + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "add" << localLocations; + + return job; +} + +KDevelop::VcsJob* PerforcePlugin::remove(const QList& /*localLocations*/) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::copy(const QUrl& /*localLocationSrc*/, const QUrl& /*localLocationDstn*/) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::move(const QUrl& /*localLocationSrc*/, const QUrl& /*localLocationDst*/) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::status(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + if (localLocations.count() != 1) { + KMessageBox::error(nullptr, i18n("Please select only one item for this operation")); + return nullptr; + } + + QFileInfo curFile(localLocations.front().toLocalFile()); + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "fstat" << curFile.fileName(); + connect(job, &DVcsJob::readyForParsing, this, &PerforcePlugin::parseP4StatusOutput); + + return job; +} + +KDevelop::VcsJob* PerforcePlugin::revert(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + if (localLocations.count() != 1) { + KMessageBox::error(nullptr, i18n("Please select only one item for this operation")); + return nullptr; + } + + QFileInfo curFile(localLocations.front().toLocalFile()); + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "revert" << curFile.fileName(); + + return job; + +} + +KDevelop::VcsJob* PerforcePlugin::update(const QList& localLocations, const KDevelop::VcsRevision& /*rev*/, KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + QFileInfo curFile(localLocations.front().toLocalFile()); + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + //*job << m_perforceExecutable << "-p" << "127.0.0.1:1666" << "info"; - Let's keep this for now it's very handy for debugging + QString fileOrDirectory; + if (curFile.isDir()) + fileOrDirectory = curFile.absolutePath() + "/..."; + else + fileOrDirectory = curFile.fileName(); + *job << m_perforceExecutable << "sync" << fileOrDirectory; + return job; +} + +KDevelop::VcsJob* PerforcePlugin::commit(const QString& message, const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + if (localLocations.empty() || message.isEmpty()) + return errorsFound(i18n("No files or message specified")); + + + QFileInfo curFile(localLocations.front().toLocalFile()); + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "submit" << "-d" << message << localLocations; + + return job; +} + +KDevelop::VcsJob* PerforcePlugin::diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, KDevelop::VcsDiff::Type , KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + QFileInfo curFile(fileOrDirectory.toLocalFile()); + QString depotSrcFileName = getRepositoryName(curFile); + QString depotDstFileName = depotSrcFileName; + depotSrcFileName.append(toRevisionName(srcRevision, dstRevision.prettyValue())); // dstRevision acutally contains the number that we want to take previous of + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + switch (dstRevision.revisionType()) { + case VcsRevision::FileNumber: + case VcsRevision::GlobalNumber: + depotDstFileName.append("#"); + depotDstFileName.append(dstRevision.prettyValue()); + *job << m_perforceExecutable << "diff2" << "-u" << depotSrcFileName << depotDstFileName; + break; + case VcsRevision::Special: + switch (dstRevision.revisionValue().value()) { + case VcsRevision::Working: + *job << m_perforceExecutable << "diff" << "-du" << depotSrcFileName; + break; + case VcsRevision::Start: + case VcsRevision::UserSpecialType: + default: + break; + } + default: + break; + } + + connect(job, &DVcsJob::readyForParsing, this, &PerforcePlugin::parseP4DiffOutput); + return job; +} + +KDevelop::VcsJob* PerforcePlugin::log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, long unsigned int limit) +{ + static QString lastSeenChangeList; + QFileInfo curFile(localLocation.toLocalFile()); + QString localLocationAndRevStr = localLocation.toLocalFile(); + + DVcsJob* job = new DVcsJob(urlDir(localLocation), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "filelog" << "-lit"; + if(limit > 0) + *job << QStringLiteral("-m %1").arg(limit); + + if (curFile.isDir()) { + localLocationAndRevStr.append("/..."); + } + QString revStr = toRevisionName(rev, QString()); + if(!revStr.isEmpty()) { + // This is not too nice, but perforce argument for restricting output from filelog does not Work :-( + // So putting this in so we do not end up in infinite loop calling log, + if(revStr == lastSeenChangeList) { + localLocationAndRevStr.append("#none"); + lastSeenChangeList.clear(); + } else { + localLocationAndRevStr.append(revStr); + lastSeenChangeList = revStr; + } + } + *job << localLocationAndRevStr; + qCDebug(PLUGIN_PERFORCE) << "Issuing the following command to p4: " << job->dvcsCommand(); + connect(job, &DVcsJob::readyForParsing, this, &PerforcePlugin::parseP4LogOutput); + return job; +} + +KDevelop::VcsJob* PerforcePlugin::log(const QUrl& localLocation, const KDevelop::VcsRevision& /*rev*/, const KDevelop::VcsRevision& /*limit*/) +{ + QFileInfo curFile(localLocation.toLocalFile()); + if (curFile.isDir()) { + KMessageBox::error(nullptr, i18n("Please select a file for this operation")); + return errorsFound(i18n("Directory not supported for this operation")); + } + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "filelog" << "-lit" << localLocation; + + connect(job, &DVcsJob::readyForParsing, this , &PerforcePlugin::parseP4LogOutput); + return job; +} + +KDevelop::VcsJob* PerforcePlugin::annotate(const QUrl& localLocation, const KDevelop::VcsRevision& /*rev*/) +{ + QFileInfo curFile(localLocation.toLocalFile()); + if (curFile.isDir()) { + KMessageBox::error(nullptr, i18n("Please select a file for this operation")); + return errorsFound(i18n("Directory not supported for this operation")); + } + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "annotate" << "-qi" << localLocation; + + connect(job, &DVcsJob::readyForParsing, this , &PerforcePlugin::parseP4AnnotateOutput); + return job; +} + +KDevelop::VcsJob* PerforcePlugin::resolve(const QList& /*localLocations*/, KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::createWorkingCopy(const KDevelop::VcsLocation& /*sourceRepository*/, const QUrl& /*destinationDirectory*/, KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) +{ + return nullptr; +} + +KDevelop::VcsLocationWidget* PerforcePlugin::vcsLocation(QWidget* parent) const +{ + return new StandardVcsLocationWidget(parent); +} + + +KDevelop::VcsJob* PerforcePlugin::edit(const QList& localLocations) +{ + QFileInfo curFile(localLocations.front().toLocalFile()); + + DVcsJob* job = new DVcsJob(curFile.dir(), this, KDevelop::OutputJob::Verbose); + setEnvironmentForJob(job, curFile); + *job << m_perforceExecutable << "edit" << localLocations; + + return job; +} + +KDevelop::VcsJob* PerforcePlugin::edit(const QUrl& /*localLocation*/) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::unedit(const QUrl& /*localLocation*/) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::localRevision(const QUrl& /*localLocation*/, KDevelop::VcsRevision::RevisionType) +{ + return nullptr; +} + +KDevelop::VcsJob* PerforcePlugin::import(const QString& /*commitMessage*/, const QUrl& /*sourceDirectory*/, const KDevelop::VcsLocation& /*destinationRepository*/) +{ + return nullptr; +} + +KDevelop::ContextMenuExtension PerforcePlugin::contextMenuExtension(KDevelop::Context* context) +{ + m_common->setupFromContext(context); + + const QList & ctxUrlList = m_common->contextUrlList(); + + bool hasVersionControlledEntries = false; + for( const QUrl& url : ctxUrlList) { + if (isValidDirectory(url)) { + hasVersionControlledEntries = true; + break; + } + } + + if (!hasVersionControlledEntries) + return IPlugin::contextMenuExtension(context); + + QMenu * perforceMenu = m_common->commonActions(); + perforceMenu->addSeparator(); + + perforceMenu->addSeparator(); + if (!m_edit_action) { + m_edit_action = new QAction(i18n("Edit"), this); + connect(m_edit_action, &QAction::triggered, this, & PerforcePlugin::ctxEdit); + } + perforceMenu->addAction(m_edit_action); + + ContextMenuExtension menuExt; + menuExt.addAction(ContextMenuExtension::VcsGroup, perforceMenu->menuAction()); + + return menuExt; +} + +void PerforcePlugin::ctxEdit() +{ + QList const & ctxUrlList = m_common->contextUrlList(); + KDevelop::ICore::self()->runController()->registerJob(edit(ctxUrlList)); +} + +void PerforcePlugin::setEnvironmentForJob(DVcsJob* job, const QFileInfo& curFile) +{ + KProcess* jobproc = job->process(); + jobproc->setEnv("P4CONFIG", m_perforceConfigName); + if (curFile.isDir()) { + jobproc->setEnv("PWD", curFile.filePath()); + } else { + jobproc->setEnv("PWD", curFile.absolutePath()); + } +} + +QList PerforcePlugin::getQvariantFromLogOutput(QStringList const& outputLines) +{ + static const QString LOGENTRY_START("... #"); + static const QString DEPOTMESSAGE_START("... ."); + QMap changes; + QList commits; + QString currentFileName; + QString changeNumberStr, author,changeDescription, commitMessage; + VcsEvent currentVcsEvent; + VcsItemEvent currentRepoFile; + VcsRevision rev; + int indexofAt; + int changeNumber = 0; + + foreach(const QString & line, outputLines) { + if (!line.startsWith(LOGENTRY_START) && !line.startsWith(DEPOTMESSAGE_START) && !line.startsWith('\t')) { + currentFileName = line; + } + if(line.indexOf(LOGENTRY_START) != -1) + { + // expecting the Logentry line to be of the form: + //... #5 change 10 edit on 2010/12/06 12:07:31 by mvo@testbed (text) + changeNumberStr = line.section(' ', 3, 3 ); // We use global change number + changeNumber = changeNumberStr.toInt(); + author = line.section(' ', 9, 9); + changeDescription = line.section(' ' , 4, 4 ); + indexofAt = author.indexOf('@'); + author.remove(indexofAt, author.size()); // Only keep the username itself + rev.setRevisionValue(changeNumberStr, KDevelop::VcsRevision::GlobalNumber); + + changes[changeNumber].setRevision(rev); + changes[changeNumber].setAuthor(author); + changes[changeNumber].setDate(QDateTime::fromString(line.section(' ', 6, 7), "yyyy/MM/dd hh:mm:ss")); + currentRepoFile.setRepositoryLocation(currentFileName); + currentRepoFile.setActions( actionsFromString(changeDescription) ); + changes[changeNumber].addItem(currentRepoFile); + commitMessage.clear(); // We have a new entry, clear message + } + if (line.startsWith('\t') || line.startsWith(DEPOTMESSAGE_START)) { + commitMessage += line.trimmed() + '\n'; + changes[changeNumber].setMessage(commitMessage); + } + + } + + for(auto item : changes) { + commits.prepend(QVariant::fromValue(item)); + } + return commits; +} + + +void PerforcePlugin::parseP4StatusOutput(DVcsJob* job) +{ + QStringList outputLines = job->output().split('\n', QString::SkipEmptyParts); + QVariantList statuses; + QList processedFiles; + static const QString ACTION_STR("... action "); + static const QString CLIENT_FILE_STR("... clientFile "); + + + + VcsStatusInfo status; + status.setState(VcsStatusInfo::ItemUserState); + foreach(const QString & line, outputLines) { + int idx(line.indexOf(ACTION_STR)); + if (idx != -1) { + QString curr = line.right(line.size() - ACTION_STR.size()); + + if (curr == "edit") { + status.setState(VcsStatusInfo::ItemModified); + } else if (curr == "add") { + status.setState(VcsStatusInfo::ItemAdded); + } else { + status.setState(VcsStatusInfo::ItemUserState); + } + continue; + } + idx = line.indexOf(CLIENT_FILE_STR); + if (idx != -1) { + QUrl fileUrl = QUrl::fromLocalFile(line.right(line.size() - CLIENT_FILE_STR.size())); + + status.setUrl(fileUrl); + } + } + statuses.append(qVariantFromValue(status)); + job->setResults(statuses); +} + +void PerforcePlugin::parseP4LogOutput(KDevelop::DVcsJob* job) +{ + QList commits(getQvariantFromLogOutput(job->output().split('\n', QString::SkipEmptyParts))); + + job->setResults(commits); +} + +void PerforcePlugin::parseP4DiffOutput(DVcsJob* job) +{ + VcsDiff diff; + diff.setDiff(job->output()); + QDir dir(job->directory()); + + do { + if (dir.exists(m_perforceConfigName)) { + break; + } + } while (dir.cdUp()); + + diff.setBaseDiff(QUrl::fromLocalFile(dir.absolutePath())); + + job->setResults(qVariantFromValue(diff)); +} + +void PerforcePlugin::parseP4AnnotateOutput(DVcsJob *job) +{ + QVariantList results; + /// First get the changelists for this file + QStringList strList(job->dvcsCommand()); + QString localLocation(strList.last()); /// ASSUMPTION WARNING - localLocation is the last in the annotate command + KDevelop::VcsRevision dummyRev; + QScopedPointer logJob(new DVcsJob(job->directory(), this, OutputJob::Silent)); + QFileInfo curFile(localLocation); + setEnvironmentForJob(logJob.data(), curFile); + *logJob << m_perforceExecutable << "filelog" << "-lit" << localLocation; + + QList commits; + if (logJob->exec() && logJob->status() == KDevelop::VcsJob::JobSucceeded) { + if (!job->output().isEmpty()) { + commits = getQvariantFromLogOutput(logJob->output().split('\n', QString::SkipEmptyParts)); + } + } + + VcsEvent item; + QMap globalCommits; + /// Move the VcsEvents to a more suitable data strucure + for (QList::const_iterator commitsIt = commits.constBegin(), commitsEnd = commits.constEnd(); + commitsIt != commitsEnd; ++commitsIt) { + if(commitsIt->canConvert()) + { + item = commitsIt->value(); + } + globalCommits.insert(item.revision().revisionValue().toLongLong(), item); + } + + VcsAnnotationLine* annotation; + QStringList lines = job->output().split('\n'); + + size_t lineNumber(0); + QMap definedRevisions; + QMap::iterator currentEvent; + bool convertToIntOk(false); + int globalRevisionInt(0); + QString globalRevision; + for (QStringList::const_iterator it = lines.constBegin(), itEnd = lines.constEnd(); + it != itEnd; ++it) { + if (it->isEmpty()) { + continue; + } + + globalRevision = it->left(it->indexOf(':')); + + annotation = new VcsAnnotationLine; + annotation->setLineNumber(lineNumber); + VcsRevision rev; + rev.setRevisionValue(globalRevision, KDevelop::VcsRevision::GlobalNumber); + annotation->setRevision(rev); + // Find the other info in the commits list + globalRevisionInt = globalRevision.toLongLong(&convertToIntOk); + if(convertToIntOk) + { + currentEvent = globalCommits.find(globalRevisionInt); + annotation->setAuthor(currentEvent->author()); + annotation->setCommitMessage(currentEvent->message()); + annotation->setDate(currentEvent->date()); + } + + results += qVariantFromValue(*annotation); + ++lineNumber; + } + + job->setResults(results); +} + + +KDevelop::VcsJob* PerforcePlugin::errorsFound(const QString& error, KDevelop::OutputJob::OutputJobVerbosity verbosity) +{ + DVcsJob* j = new DVcsJob(QDir::temp(), this, verbosity); + *j << "echo" << i18n("error: %1", error) << "-n"; + return j; +} + + diff --git a/plugins/perforce/perforcepluginmetadata.cpp b/plugins/perforce/perforcepluginmetadata.cpp new file mode 100644 --- /dev/null +++ b/plugins/perforce/perforcepluginmetadata.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright 2015 Morten Danielsen Volden * + * * + * 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) version 3 or any later version * + * accepted by the membership of KDE e.V. (or its successor approved * + * by the membership of KDE e.V.), which shall act as a proxy * + * defined in Section 14 of version 3 of the license. * + * * + * 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, see . * + ***************************************************************************/ + +#include "perforceplugin.h" + +#include + + +// This file only exists so that the tests can be built: +// test_kdevperforce builds perforceplugin.cpp again but in a different directory. +// This means that the kdevperforce.json file is no longer found. +// Since the JSON metadata is not needed in the test, we simply move +// the K_PLUGIN_FACTORY_WITH_JSON to a separate file. + +K_PLUGIN_FACTORY_WITH_JSON(KdevPerforceFactory, "kdevperforce.json", registerPlugin();) + +#include "perforcepluginmetadata.moc" diff --git a/plugins/perforce/test/CMakeLists.txt b/plugins/perforce/test/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/plugins/perforce/test/CMakeLists.txt @@ -0,0 +1,12 @@ +set(perforceplugintest_SRCS + test_perforce.cpp + ../perforceplugin.cpp +) +include_directories(../) + +add_definitions( "-DP4_CLIENT_STUB_EXE=\"${CMAKE_CURRENT_BINARY_DIR}/../p4clientstub/p4clientstub\"" ) + +ecm_add_test(${perforceplugintest_SRCS} + TEST_NAME test_kdevperforce + LINK_LIBRARIES Qt5::Test KDev::Vcs KDev::Util KDev::Tests ) + diff --git a/plugins/perforce/test/test_perforce.h b/plugins/perforce/test/test_perforce.h new file mode 100644 --- /dev/null +++ b/plugins/perforce/test/test_perforce.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * This file was inspired by KDevelop's git plugin * + * Copyright 2008 Evgeniy Ivanov * + * * + * Adapted for Perforce * + * Copyright 2011 Morten Danielsen Volden * + * * + * 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, see . * + ***************************************************************************/ + +#ifndef PERFORCEPLUGIN_TEST_H +#define PERFORCEPLUGIN_TEST_H + +#include + +class PerforcePlugin; + +namespace KDevelop +{ +class TestCore; +} + +class PerforcePluginTest : public QObject +{ + Q_OBJECT +private slots: + void init(); + void cleanup(); + void testAdd(); + void testEdit(); + void testEditMultipleFiles(); + void testStatus(); + void testAnnotate(); + void testHistory(); + void testRevert(); + void testUpdateFile(); + void testUpdateDir(); + void testCommit(); + void testDiff(); +private: + PerforcePlugin* m_plugin; + KDevelop::TestCore* m_core; + void removeTempDirsIfAny(); + void createNewTempDirs(); +}; + +#endif diff --git a/plugins/perforce/test/test_perforce.cpp b/plugins/perforce/test/test_perforce.cpp new file mode 100644 --- /dev/null +++ b/plugins/perforce/test/test_perforce.cpp @@ -0,0 +1,190 @@ +/*************************************************************************** + * This file was inspired by KDevelop's git plugin * + * Copyright 2008 Evgeniy Ivanov * + * * + * Adapted for Perforce * + * Copyright 2011 Morten Danielsen Volden * + * * + * 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, see . * + ***************************************************************************/ + +#include "test_perforce.h" + +#include + +#include +#include + +#include +#include +#include + +#include + +#define VERIFYJOB(j) \ + QVERIFY(j); QVERIFY(j->exec()); QVERIFY((j)->status() == VcsJob::JobSucceeded) + +const QString tempDir = QDir::tempPath(); +const QString perforceTestBaseDirNoSlash(tempDir + "/kdevPerforce_testdir"); +const QString perforceTestBaseDir(tempDir + "/kdevPerforce_testdir/"); +const QString perforceTestBaseDir2(tempDir + "/kdevPerforce_testdir2/"); +const QString perforceConfigFileName("p4config.txt"); + +const QString perforceSrcDir(perforceTestBaseDir + "src/"); +const QString perforceTest_FileName("testfile"); +const QString perforceTest_FileName2("foo"); +const QString perforceTest_FileName3("bar"); + +using namespace KDevelop; + +void PerforcePluginTest::init() +{ + AutoTestShell::init({"kdevperforce"}); + m_core = new TestCore(); + m_core->initialize(); + m_plugin = new PerforcePlugin(m_core); + /// During test we are setting the executable the plugin uses to our own stub + m_plugin->m_perforceExecutable = P4_CLIENT_STUB_EXE; + removeTempDirsIfAny(); + createNewTempDirs(); +} + +void PerforcePluginTest::createNewTempDirs() +{ + // Now create the basic directory structure + QDir tmpdir(tempDir); + tmpdir.mkdir(perforceTestBaseDir); + //we start it after repoInit, so we still have empty repo + QFile f(perforceTestBaseDir + perforceConfigFileName); + if (f.open(QIODevice::WriteOnly)) { + QTextStream input(&f); + input << "P4PORT=127.0.0.1:1666\n"; + input << "P4USER=mvo\n"; + input << "P4CLIENT=testbed\n"; + } + f.close(); + + //Put a file here because the annotate and update function will check for that + QFile g(perforceTestBaseDir + perforceTest_FileName); + if (g.open(QIODevice::WriteOnly)) { + QTextStream input(&g); + input << "HELLO WORLD"; + } + g.close(); + + + tmpdir.mkdir(perforceSrcDir); + tmpdir.mkdir(perforceTestBaseDir2); +} + + +void PerforcePluginTest::removeTempDirsIfAny() +{ + QDir dir(perforceTestBaseDir); + if (dir.exists() && !dir.removeRecursively()) + qDebug() << "QDir::removeRecursively(" << perforceTestBaseDir << ") returned false"; + + QDir dir2(perforceTestBaseDir); + if (dir2.exists() && !dir2.removeRecursively()) + qDebug() << "QDir::removeRecursively(" << perforceTestBaseDir2 << ") returned false"; +} + + +void PerforcePluginTest::cleanup() +{ + m_core->cleanup(); + delete m_core; + removeTempDirsIfAny(); +} + +void PerforcePluginTest::testAdd() +{ + VcsJob* j = m_plugin->add(QList({ QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName) } )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testEdit() +{ + VcsJob* j = m_plugin->edit(QList( { QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName) } )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testEditMultipleFiles() +{ + QList filesForEdit; + filesForEdit.push_back(QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName)); + filesForEdit.push_back(QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName2)); + filesForEdit.push_back(QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName3)); + VcsJob* j = m_plugin->edit(filesForEdit); + VERIFYJOB(j); +} + + +void PerforcePluginTest::testStatus() +{ + VcsJob* j = m_plugin->status(QList( { QUrl::fromLocalFile(perforceTestBaseDirNoSlash) } )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testAnnotate() +{ + VcsJob* j = m_plugin->annotate(QUrl( QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName) )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testHistory() +{ + VcsJob* j = m_plugin->log(QUrl( QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName) )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testRevert() +{ + VcsJob* j = m_plugin->revert(QList( { QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName) } )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testUpdateFile() +{ + VcsJob* j = m_plugin->update(QList( { QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName) } )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testUpdateDir() +{ + VcsJob* j = m_plugin->update(QList( { QUrl::fromLocalFile(perforceTestBaseDirNoSlash) } )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testCommit() +{ + QString commitMsg("this is the commit message"); + VcsJob* j = m_plugin->commit(commitMsg, QList( { QUrl::fromLocalFile(perforceTestBaseDirNoSlash) } )); + VERIFYJOB(j); +} + +void PerforcePluginTest::testDiff() +{ + VcsRevision srcRevision; + srcRevision.setRevisionValue(QVariant(1), VcsRevision::GlobalNumber); + VcsRevision dstRevision; + dstRevision.setRevisionValue(QVariant(2), VcsRevision::GlobalNumber); + + VcsJob* j = m_plugin->diff( QUrl::fromLocalFile(perforceTestBaseDir + perforceTest_FileName), srcRevision, dstRevision, VcsDiff::Type::DiffUnified ); + VERIFYJOB(j); +} + + +QTEST_MAIN(PerforcePluginTest) + diff --git a/plugins/problemreporter/kdevproblemreporter.json b/plugins/problemreporter/kdevproblemreporter.json --- a/plugins/problemreporter/kdevproblemreporter.json +++ b/plugins/problemreporter/kdevproblemreporter.json @@ -2,17 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "Hamish Rodda" + "Name": "Hamish Rodda", + "Name[x-test]": "xxHamish Roddaxx" } ], "Category": "Utilities", "Description": "This plugin shows errors in source code.", + "Description[ar]": "تظهر هذه الملحقة الأخطاء في الشِّفرة المصدريّة.", "Description[ca@valencia]": "Este connector permet mostrar errors en el codi font.", "Description[ca]": "Aquest connector permet mostrar errors en el codi font.", "Description[de]": "Dieses Modul zeigt Fehler im Quelltext an.", - "Description[en_GB]": "This plugin shows errors in source code.", "Description[es]": "Este complemento muestra errores en el código fuente.", - "Description[et]": "See plugin näitab vigu lähtekoodis.", "Description[fi]": "Tämä liitännäinen näyttää virheet lähdekoodissa.", "Description[gl]": "Esta extensión mostra erros no código fonte.", "Description[it]": "Questa estensione mostra gli errori nel codice sorgente.", @@ -23,37 +23,49 @@ "Description[sk]": "Tento plugin ukáže chyby v zdrojovom kóde.", "Description[sl]": "Vstavek prikazuje napake v izvorni kodi.", "Description[sv]": "Insticksprogrammet visar fel i källkod.", + "Description[tr]": "Bu eklenti kaynak koddaki hataları gösterir.", "Description[uk]": "За допомогою цього додатка можна переглянути повідомлення про помилки у коді.", "Description[x-test]": "xxThis plugin shows errors in source code.xx", "Description[zh_CN]": "此插件显示源代码中的错误。", "Icon": "emblem-important", "Id": "kdevproblemreporter", "License": "LGPL", "Name": "Problem Reporter View", + "Name[ar]": "عرض مبلّغ المشاكل", + "Name[bg]": "Преглед на съобщенията за грешки", + "Name[bs]": "Pregled pomoću prikazivača problema", "Name[ca@valencia]": "Vista del notificador de problemes", "Name[ca]": "Vista del notificador de problemes", + "Name[da]": "Visning af problemrapportering", "Name[de]": "Ansicht für Fehlerberichte", - "Name[en_GB]": "Problem Reporter View", + "Name[el]": "Προβολή ανταποκριτή προβλημάτων", "Name[es]": "Vista del notificador de problemas", "Name[et]": "Probleemide teavitaja vaade", "Name[fi]": "Ongelmailmoitinnäkymä", "Name[gl]": "Vista do relator de problemas", + "Name[hu]": "Hibajelentő nézet", "Name[it]": "Vista segnalazione problemi", + "Name[kk]": "Мәселе хабарлағыш көрінісі", "Name[nb]": "Problemmeldervisning", + "Name[nds]": "Problemsöök-Ansicht", "Name[nl]": "Probleemrapporteuroverzicht", "Name[pl]": "Widok raportów o problemach", "Name[pt]": "Área de Relatórios de Erros", "Name[pt_BR]": "Área de Relatórios de Erros", + "Name[ru]": "Панель диагностики проблем", "Name[sk]": "Pohľad na zadávač problémov", "Name[sl]": "Prikaz poročevalca o težavah", "Name[sv]": "Problemrapporteringsvisning", + "Name[tr]": "Sorun Bildirici Görünümü", + "Name[ug]": "مەسىلە مەلۇم قىلغۇچ كۆرۈنۈشى", "Name[uk]": "Перегляд інструмента звітування про проблеми", "Name[x-test]": "xxProblem Reporter Viewxx", "Name[zh_CN]": "错误汇报视图", + "Name[zh_TW]": "問題回報器檢視", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/problemreporter/problemsview.h b/plugins/problemreporter/problemsview.h --- a/plugins/problemreporter/problemsview.h +++ b/plugins/problemreporter/problemsview.h @@ -22,27 +22,31 @@ #include -#include +#include class ProblemTreeView; +class KActionMenu; + +class QAction; +class QActionGroup; +class QMenu; +class QTabWidget; + namespace KDevelop { struct ModelData; /** * @brief Provides a tabbed view for models in the ProblemModelSet. * + * * Also provides a toolbar for actions for the models and shows the number of messages in each tab's text. * When the load() method is called it looks up the models in the ProblemModelSet. * For each model it creates a treeview, which is then added to the tabbed view and a new tab. * The tab's text will be the name of the model + the number of items in the treeview. - * - * TODO: According to apol this should NOT be a QMainWindow, - * because updating the widget's actions should be sufficient to update the - * toolbar of the toolviiew */ -class ProblemsView : public QMainWindow, public IToolViewActionListener +class ProblemsView : public QWidget, public IToolViewActionListener { Q_OBJECT Q_INTERFACES(KDevelop::IToolViewActionListener) @@ -73,17 +77,30 @@ private: ProblemTreeView* currentView() const; + void setupActions(); + void updateActions(); + + void handleSeverityActionToggled(); + void setScope(int scope); + /// Create a view for the model and add to the tabbed widget void addModel(const ModelData& data); - /// Update the toolbar with the widget's actions - void updateToolBar(); - /// Update the tab's text (name + number of problems in that tab) void updateTab(int idx, int rows); - QToolBar* m_toolBar; QTabWidget* m_tabWidget; + + KActionMenu* m_scopeMenu = nullptr; + KActionMenu* m_groupingMenu = nullptr; + QAction* m_fullUpdateAction = nullptr; + QAction* m_showImportsAction = nullptr; + QActionGroup* m_severityActions = nullptr; + QAction* m_currentDocumentAction = nullptr; + QAction* m_showAllAction = nullptr; + QAction* m_errorSeverityAction = nullptr; + QAction* m_warningSeverityAction = nullptr; + QAction* m_hintSeverityAction = nullptr; }; } diff --git a/plugins/problemreporter/problemsview.cpp b/plugins/problemreporter/problemsview.cpp --- a/plugins/problemreporter/problemsview.cpp +++ b/plugins/problemreporter/problemsview.cpp @@ -19,20 +19,218 @@ #include "problemsview.h" +#include #include -#include +#include +#include +#include #include +#include #include #include +#include #include #include "problemtreeview.h" #include "problemmodel.h" namespace KDevelop { +void ProblemsView::setupActions() +{ + { + m_fullUpdateAction = new QAction(this); + m_fullUpdateAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); + m_fullUpdateAction->setText(i18n("Force Full Update")); + m_fullUpdateAction->setToolTip(i18nc("@info:tooltip", "Re-parse all watched documents")); + m_fullUpdateAction->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); + connect(m_fullUpdateAction, &QAction::triggered, this, [this]() { + currentView()->model()->forceFullUpdate(); + }); + addAction(m_fullUpdateAction); + } + + { + m_showImportsAction = new QAction(this); + addAction(m_showImportsAction); + m_showImportsAction->setCheckable(true); + m_showImportsAction->setChecked(false); + m_showImportsAction->setText(i18n("Show Imports")); + m_showImportsAction->setToolTip(i18nc("@info:tooltip", "Display problems in imported files")); + connect(m_showImportsAction, &QAction::triggered, this, [this](bool checked) { + currentView()->model()->setShowImports(checked); + }); + } + + { + m_scopeMenu = new KActionMenu(this); + m_scopeMenu->setDelayed(false); + m_scopeMenu->setToolTip(i18nc("@info:tooltip", "Which files to display the problems for")); + m_scopeMenu->setObjectName(QStringLiteral("scopeMenu")); + + QActionGroup* scopeActions = new QActionGroup(this); + + m_currentDocumentAction = new QAction(this); + m_currentDocumentAction->setText(i18n("Current Document")); + m_currentDocumentAction->setToolTip(i18nc("@info:tooltip", "Display problems in current document")); + + QAction* openDocumentsAction = new QAction(this); + openDocumentsAction->setText(i18n("Open Documents")); + openDocumentsAction->setToolTip(i18nc("@info:tooltip", "Display problems in all open documents")); + + QAction* currentProjectAction = new QAction(this); + currentProjectAction->setText(i18n("Current Project")); + currentProjectAction->setToolTip(i18nc("@info:tooltip", "Display problems in current project")); + + QAction* allProjectAction = new QAction(this); + allProjectAction->setText(i18n("All Projects")); + allProjectAction->setToolTip(i18nc("@info:tooltip", "Display problems in all projects")); + + QVector actions; + actions.push_back(m_currentDocumentAction); + actions.push_back(openDocumentsAction); + actions.push_back(currentProjectAction); + actions.push_back(allProjectAction); + + m_showAllAction = new QAction(this); + m_showAllAction->setText(i18n("Show All")); + m_showAllAction->setToolTip(i18nc("@info:tooltip", "Display ALL problems")); + actions.push_back(m_showAllAction); + + foreach (QAction* action, actions) { + action->setCheckable(true); + scopeActions->addAction(action); + m_scopeMenu->addAction(action); + } + addAction(m_scopeMenu); + + QSignalMapper* scopeMapper = new QSignalMapper(this); + scopeMapper->setMapping(m_currentDocumentAction, CurrentDocument); + scopeMapper->setMapping(openDocumentsAction, OpenDocuments); + scopeMapper->setMapping(currentProjectAction, CurrentProject); + scopeMapper->setMapping(allProjectAction, AllProjects); + connect(m_currentDocumentAction, &QAction::triggered, scopeMapper, + static_cast(&QSignalMapper::map)); + connect(openDocumentsAction, &QAction::triggered, scopeMapper, + static_cast(&QSignalMapper::map)); + connect(currentProjectAction, &QAction::triggered, scopeMapper, + static_cast(&QSignalMapper::map)); + connect(allProjectAction, &QAction::triggered, scopeMapper, + static_cast(&QSignalMapper::map)); + + { + scopeMapper->setMapping(actions.last(), BypassScopeFilter); + connect(actions.last(), &QAction::triggered, scopeMapper, + static_cast(&QSignalMapper::map)); + } + + connect(scopeMapper, static_cast(&QSignalMapper::mapped), + this, [this](int index) { + setScope(index); + }); + } + + { + m_severityActions = new QActionGroup(this); + + m_errorSeverityAction = new QAction(this); + m_errorSeverityAction->setToolTip(i18nc("@info:tooltip", "Display errors")); + m_errorSeverityAction->setIcon(QIcon::fromTheme(QStringLiteral("dialog-error"))); + + m_warningSeverityAction = new QAction(this); + m_warningSeverityAction->setToolTip(i18nc("@info:tooltip", "Display warnings")); + m_warningSeverityAction->setIcon(QIcon::fromTheme(QStringLiteral("dialog-warning"))); + + m_hintSeverityAction = new QAction(this); + m_hintSeverityAction->setToolTip(i18nc("@info:tooltip", "Display hints")); + m_hintSeverityAction->setIcon(QIcon::fromTheme(QStringLiteral("dialog-information"))); + + QAction* severityActionArray[] = { m_errorSeverityAction, m_warningSeverityAction, m_hintSeverityAction }; + for (int i = 0; i < 3; ++i) { + severityActionArray[i]->setCheckable(true); + m_severityActions->addAction(severityActionArray[i]); + addAction(severityActionArray[i]); + } + m_severityActions->setExclusive(false); + + m_hintSeverityAction->setChecked(true); + m_warningSeverityAction->setChecked(true); + m_errorSeverityAction->setChecked(true); + + connect(m_errorSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); + connect(m_warningSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); + connect(m_hintSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); + } + + { + m_groupingMenu = new KActionMenu(i18n("Grouping"), this); + m_groupingMenu->setDelayed(false); + + QActionGroup* groupingActions = new QActionGroup(this); + + QAction* noGroupingAction = new QAction(i18n("None"), this); + QAction* pathGroupingAction = new QAction(i18n("Path"), this); + QAction* severityGroupingAction = new QAction(i18n("Severity"), this); + + QAction* groupingActionArray[] = { noGroupingAction, pathGroupingAction, severityGroupingAction }; + for (unsigned i = 0; i < sizeof(groupingActionArray) / sizeof(QAction*); ++i) { + QAction* action = groupingActionArray[i]; + action->setCheckable(true); + groupingActions->addAction(action); + m_groupingMenu->addAction(action); + } + addAction(m_groupingMenu); + + noGroupingAction->setChecked(true); + QSignalMapper* groupingMapper = new QSignalMapper(this); + groupingMapper->setMapping(noGroupingAction, NoGrouping); + groupingMapper->setMapping(pathGroupingAction, PathGrouping); + groupingMapper->setMapping(severityGroupingAction, SeverityGrouping); + + connect(noGroupingAction, &QAction::triggered, groupingMapper, + static_cast(&QSignalMapper::map)); + connect(pathGroupingAction, &QAction::triggered, groupingMapper, + static_cast(&QSignalMapper::map)); + connect(severityGroupingAction, &QAction::triggered, groupingMapper, + static_cast(&QSignalMapper::map)); + + connect(groupingMapper, static_cast(&QSignalMapper::mapped), + this, [this](int index) { + currentView()->model()->setGrouping(index); + }); + } +} + +void ProblemsView::updateActions() +{ + auto problemModel = currentView()->model(); + Q_ASSERT(problemModel); + + m_fullUpdateAction->setVisible(problemModel->features().testFlag(ProblemModel::CanDoFullUpdate)); + m_showImportsAction->setVisible(problemModel->features().testFlag(ProblemModel::CanShowImports)); + m_scopeMenu->setVisible(problemModel->features().testFlag(ProblemModel::ScopeFilter)); + m_severityActions->setVisible(problemModel->features().testFlag(ProblemModel::SeverityFilter)); + m_groupingMenu->setVisible(problemModel->features().testFlag(ProblemModel::Grouping)); + + m_showAllAction->setVisible(problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)); + + problemModel->setShowImports(false); + setScope(CurrentDocument); + + // Show All should be default if it's supported. It helps with error messages that are otherwise invisible + if (problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)) { + //actions.last()->setChecked(true); + setScope(BypassScopeFilter); + } else { + m_currentDocumentAction->setChecked(true); + setScope(CurrentDocument); + } + + problemModel->setSeverities(IProblem::Error | IProblem::Warning | IProblem::Hint); +} + /// TODO: Move to util? /// Note: Support for recursing into child indices would be nice class ItemViewWalker @@ -91,19 +289,19 @@ } ProblemsView::ProblemsView(QWidget* parent) - : QMainWindow(parent) + : QWidget(parent) { setWindowTitle(i18n("Problems")); setWindowIcon(QIcon::fromTheme(QStringLiteral("script-error"), windowIcon())); - m_toolBar = new QToolBar(this); - m_toolBar->setMovable(false); - m_toolBar->setFloatable(false); - addToolBar(m_toolBar); + auto layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); m_tabWidget = new QTabWidget(this); m_tabWidget->setTabPosition(QTabWidget::South); - setCentralWidget(m_tabWidget); + layout->addWidget(m_tabWidget); + + setupActions(); } ProblemsView::~ProblemsView() @@ -128,7 +326,7 @@ connect(m_tabWidget, &QTabWidget::currentChanged, this, &ProblemsView::onCurrentChanged); if (m_tabWidget->currentIndex() == 0) { - updateToolBar(); + updateActions(); return; } @@ -172,12 +370,10 @@ void ProblemsView::onCurrentChanged(int idx) { - m_toolBar->clear(); - if (idx == -1) return; - updateToolBar(); + updateActions(); } void ProblemsView::onViewChanged() @@ -199,12 +395,6 @@ updateTab(idx, rows); } -void ProblemsView::updateToolBar() -{ - QWidget* w = m_tabWidget->currentWidget(); - m_toolBar->addActions(w->actions()); -} - void ProblemsView::updateTab(int idx, int rows) { const QString name = nameFromLabel(m_tabWidget->tabText(idx)); @@ -236,4 +426,19 @@ view->openDocumentForCurrentProblem(); } } + +void ProblemsView::handleSeverityActionToggled() +{ + currentView()->model()->setSeverities( (m_errorSeverityAction->isChecked() ? IProblem::Error : IProblem::Severities()) | + (m_warningSeverityAction->isChecked() ? IProblem::Warning : IProblem::Severities()) | + (m_hintSeverityAction->isChecked() ? IProblem::Hint : IProblem::Severities()) ); +} + +void ProblemsView::setScope(int scope) +{ + m_scopeMenu->setText(i18n("Scope: %1", m_scopeMenu->menu()->actions().at(scope)->text())); + + currentView()->model()->setScope(scope); +} + } diff --git a/plugins/problemreporter/problemtreeview.h b/plugins/problemreporter/problemtreeview.h --- a/plugins/problemreporter/problemtreeview.h +++ b/plugins/problemreporter/problemtreeview.h @@ -62,17 +62,11 @@ private slots: void itemActivated(const QModelIndex& index); - void handleSeverityActionToggled(); - - void setScope(int scope); private: void resizeColumns(); ProblemReporterPlugin* m_plugin; QSortFilterProxyModel* m_proxy; - QAction* m_errorSeverityAction; - QAction* m_warningSeverityAction; - QAction* m_hintSeverityAction; }; #endif diff --git a/plugins/problemreporter/problemtreeview.cpp b/plugins/problemreporter/problemtreeview.cpp --- a/plugins/problemreporter/problemtreeview.cpp +++ b/plugins/problemreporter/problemtreeview.cpp @@ -28,10 +28,8 @@ #include #include #include -#include #include -#include #include #include @@ -81,9 +79,6 @@ ProblemTreeView::ProblemTreeView(QWidget* parent, QAbstractItemModel* itemModel) : QTreeView(parent) , m_proxy(new QSortFilterProxyModel(this)) - , m_errorSeverityAction(nullptr) - , m_warningSeverityAction(nullptr) - , m_hintSeverityAction(nullptr) { setObjectName(QStringLiteral("Problem Reporter Tree")); setWhatsThis(i18n("Problems")); @@ -100,174 +95,6 @@ header()->setStretchLastSection(false); - if (problemModel->features().testFlag(ProblemModel::CanDoFullUpdate)) { - QAction* fullUpdateAction = new QAction(this); - fullUpdateAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); - fullUpdateAction->setText(i18n("Force Full Update")); - fullUpdateAction->setToolTip(i18nc("@info:tooltip", "Re-parse all watched documents")); - fullUpdateAction->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); - connect(fullUpdateAction, &QAction::triggered, model(), &ProblemModel::forceFullUpdate); - addAction(fullUpdateAction); - } - - if (problemModel->features().testFlag(ProblemModel::CanShowImports)) { - QAction* showImportsAction = new QAction(this); - addAction(showImportsAction); - showImportsAction->setCheckable(true); - showImportsAction->setChecked(false); - showImportsAction->setText(i18n("Show Imports")); - showImportsAction->setToolTip(i18nc("@info:tooltip", "Display problems in imported files")); - this->model()->setShowImports(false); - connect(showImportsAction, &QAction::triggered, model(), &ProblemModel::setShowImports); - } - - if (problemModel->features().testFlag(ProblemModel::ScopeFilter)) { - KActionMenu* scopeMenu = new KActionMenu(this); - scopeMenu->setDelayed(false); - scopeMenu->setToolTip(i18nc("@info:tooltip", "Which files to display the problems for")); - scopeMenu->setObjectName(QStringLiteral("scopeMenu")); - - QActionGroup* scopeActions = new QActionGroup(this); - - QAction* currentDocumentAction = new QAction(this); - currentDocumentAction->setText(i18n("Current Document")); - currentDocumentAction->setToolTip(i18nc("@info:tooltip", "Display problems in current document")); - - QAction* openDocumentsAction = new QAction(this); - openDocumentsAction->setText(i18n("Open Documents")); - openDocumentsAction->setToolTip(i18nc("@info:tooltip", "Display problems in all open documents")); - - QAction* currentProjectAction = new QAction(this); - currentProjectAction->setText(i18n("Current Project")); - currentProjectAction->setToolTip(i18nc("@info:tooltip", "Display problems in current project")); - - QAction* allProjectAction = new QAction(this); - allProjectAction->setText(i18n("All Projects")); - allProjectAction->setToolTip(i18nc("@info:tooltip", "Display problems in all projects")); - - QVector actions; - actions.push_back(currentDocumentAction); - actions.push_back(openDocumentsAction); - actions.push_back(currentProjectAction); - actions.push_back(allProjectAction); - - if (problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)) { - QAction* showAllAction = new QAction(this); - showAllAction->setText(i18n("Show All")); - showAllAction->setToolTip(i18nc("@info:tooltip", "Display ALL problems")); - actions.push_back(showAllAction); - } - - foreach (QAction* action, actions) { - action->setCheckable(true); - scopeActions->addAction(action); - scopeMenu->addAction(action); - } - addAction(scopeMenu); - setScope(CurrentDocument); - - // Show All should be default if it's supported. It helps with error messages that are otherwise invisible - if (problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)) { - actions.last()->setChecked(true); - model()->setScope(BypassScopeFilter); - } else { - currentDocumentAction->setChecked(true); - model()->setScope(CurrentDocument); - } - - QSignalMapper* scopeMapper = new QSignalMapper(this); - scopeMapper->setMapping(currentDocumentAction, CurrentDocument); - scopeMapper->setMapping(openDocumentsAction, OpenDocuments); - scopeMapper->setMapping(currentProjectAction, CurrentProject); - scopeMapper->setMapping(allProjectAction, AllProjects); - connect(currentDocumentAction, &QAction::triggered, scopeMapper, - static_cast(&QSignalMapper::map)); - connect(openDocumentsAction, &QAction::triggered, scopeMapper, - static_cast(&QSignalMapper::map)); - connect(currentProjectAction, &QAction::triggered, scopeMapper, - static_cast(&QSignalMapper::map)); - connect(allProjectAction, &QAction::triggered, scopeMapper, - static_cast(&QSignalMapper::map)); - - if (problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)) { - scopeMapper->setMapping(actions.last(), BypassScopeFilter); - connect(actions.last(), &QAction::triggered, scopeMapper, - static_cast(&QSignalMapper::map)); - } - - connect(scopeMapper, static_cast(&QSignalMapper::mapped), this, - &ProblemTreeView::setScope); - } - - if (problemModel->features().testFlag(ProblemModel::SeverityFilter)) { - QActionGroup* severityActions = new QActionGroup(this); - - m_errorSeverityAction = new QAction(this); - m_errorSeverityAction->setToolTip(i18nc("@info:tooltip", "Display errors")); - m_errorSeverityAction->setIcon(QIcon::fromTheme(QStringLiteral("dialog-error"))); - - m_warningSeverityAction = new QAction(this); - m_warningSeverityAction->setToolTip(i18nc("@info:tooltip", "Display warnings")); - m_warningSeverityAction->setIcon(QIcon::fromTheme(QStringLiteral("dialog-warning"))); - - m_hintSeverityAction = new QAction(this); - m_hintSeverityAction->setToolTip(i18nc("@info:tooltip", "Display hints")); - m_hintSeverityAction->setIcon(QIcon::fromTheme(QStringLiteral("dialog-information"))); - - QAction* severityActionArray[] = { m_errorSeverityAction, m_warningSeverityAction, m_hintSeverityAction }; - for (int i = 0; i < 3; ++i) { - severityActionArray[i]->setCheckable(true); - severityActions->addAction(severityActionArray[i]); - addAction(severityActionArray[i]); - } - severityActions->setExclusive(false); - - m_hintSeverityAction->setChecked(true); - m_warningSeverityAction->setChecked(true); - m_errorSeverityAction->setChecked(true); - - model()->setSeverities(IProblem::Error | IProblem::Warning | IProblem::Hint); - connect(m_errorSeverityAction, &QAction::toggled, this, &ProblemTreeView::handleSeverityActionToggled); - connect(m_warningSeverityAction, &QAction::toggled, this, &ProblemTreeView::handleSeverityActionToggled); - connect(m_hintSeverityAction, &QAction::toggled, this, &ProblemTreeView::handleSeverityActionToggled); - } - - if (problemModel->features().testFlag(ProblemModel::Grouping)) { - KActionMenu* groupingMenu = new KActionMenu(i18n("Grouping"), this); - groupingMenu->setDelayed(false); - - QActionGroup* groupingActions = new QActionGroup(this); - - QAction* noGroupingAction = new QAction(i18n("None"), this); - QAction* pathGroupingAction = new QAction(i18n("Path"), this); - QAction* severityGroupingAction = new QAction(i18n("Severity"), this); - - QAction* groupingActionArray[] = { noGroupingAction, pathGroupingAction, severityGroupingAction }; - for (unsigned i = 0; i < sizeof(groupingActionArray) / sizeof(QAction*); ++i) { - QAction* action = groupingActionArray[i]; - action->setCheckable(true); - groupingActions->addAction(action); - groupingMenu->addAction(action); - } - addAction(groupingMenu); - - noGroupingAction->setChecked(true); - QSignalMapper* groupingMapper = new QSignalMapper(this); - groupingMapper->setMapping(noGroupingAction, NoGrouping); - groupingMapper->setMapping(pathGroupingAction, PathGrouping); - groupingMapper->setMapping(severityGroupingAction, SeverityGrouping); - - connect(noGroupingAction, &QAction::triggered, groupingMapper, - static_cast(&QSignalMapper::map)); - connect(pathGroupingAction, &QAction::triggered, groupingMapper, - static_cast(&QSignalMapper::map)); - connect(severityGroupingAction, &QAction::triggered, groupingMapper, - static_cast(&QSignalMapper::map)); - - connect(groupingMapper, static_cast(&QSignalMapper::mapped), model(), - &ProblemModel::setGrouping); - } - connect(this, &ProblemTreeView::clicked, this, &ProblemTreeView::itemActivated); connect(model(), &QAbstractItemModel::rowsInserted, this, &ProblemTreeView::changed); @@ -306,24 +133,6 @@ ICore::self()->documentController()->openDocument(url, start); } -void ProblemTreeView::handleSeverityActionToggled() -{ - model()->setSeverities( (m_errorSeverityAction->isChecked() ? IProblem::Error : IProblem::Severities()) | - (m_warningSeverityAction->isChecked() ? IProblem::Warning : IProblem::Severities()) | - (m_hintSeverityAction->isChecked() ? IProblem::Hint : IProblem::Severities()) ); -} - -void ProblemTreeView::setScope(int scope) -{ - foreach (auto action, actions()) { - if (action->objectName() == QLatin1String("scopeMenu")) { - action->setText(i18n("Scope: %1", action->menu()->actions().at(scope)->text())); - } - } - - model()->setScope(scope); -} - void ProblemTreeView::resizeColumns() { for (int i = 0; i < model()->columnCount(); ++i) @@ -357,31 +166,37 @@ void ProblemTreeView::contextMenuEvent(QContextMenuEvent* event) { QModelIndex index = indexAt(event->pos()); - if (index.isValid()) { - const auto problem = index.data(ProblemModel::ProblemRole).value(); - if (!problem) { - return; - } - QExplicitlySharedDataPointer solution = problem->solutionAssistant(); - if (!solution) { - return; - } - QList actions; - foreach (KDevelop::IAssistantAction::Ptr action, solution->actions()) { - actions << action->toKAction(); - } - if (!actions.isEmpty()) { - QString title = solution->title(); - title = KDevelop::htmlToPlainText(title); - title.replace(QLatin1String("'"), QLatin1String("\'")); - - QPointer m = new QMenu(this); - m->addSection(title); - m->addActions(actions); - m->exec(event->globalPos()); - delete m; - } + if (!index.isValid()) + return; + + const auto problem = index.data(ProblemModel::ProblemRole).value(); + if (!problem) { + return; } + + QExplicitlySharedDataPointer solution = problem->solutionAssistant(); + if (!solution) { + return; + } + + QList actions; + foreach (KDevelop::IAssistantAction::Ptr action, solution->actions()) { + actions << action->toKAction(); + } + + if (actions.isEmpty()) { + return; + } + + QString title = solution->title(); + title = KDevelop::htmlToPlainText(title); + title.replace(QLatin1String("'"), QLatin1String("\'")); + + QPointer m = new QMenu(this); + m->addSection(title); + m->addActions(actions); + m->exec(event->globalPos()); + delete m; } void ProblemTreeView::showEvent(QShowEvent* event) diff --git a/plugins/problemreporter/tests/test_problemsview.cpp b/plugins/problemreporter/tests/test_problemsview.cpp --- a/plugins/problemreporter/tests/test_problemsview.cpp +++ b/plugins/problemreporter/tests/test_problemsview.cpp @@ -18,7 +18,9 @@ */ #include +#include #include +#include #include #include "../problemsview.h" @@ -49,8 +51,6 @@ private: QTabWidget* tabWidget(); - QToolBar* toolBar(); - bool compareActions(QWidget* w, QToolBar* tb); QScopedPointer m_view; }; @@ -80,7 +80,7 @@ // Check that the inital model's tab shows up QTabWidget* tab = tabWidget(); - QVERIFY(tab != nullptr); + QVERIFY(tab); QCOMPARE(tab->count(), 1); QCOMPARE(tab->tabText(0), QStringLiteral("MODEL1 (1)")); } @@ -91,59 +91,66 @@ pms->addModel(QStringLiteral("MODEL2"), new ProblemModel(pms)); QTabWidget* tab = tabWidget(); - QVERIFY(tab != nullptr); + QVERIFY(tab); QCOMPARE(tab->count(), 2); QCOMPARE(tab->tabText(0), QStringLiteral("MODEL1 (1)")); QCOMPARE(tab->tabText(1), QStringLiteral("MODEL2 (0)")); } +QVector visibilites(const QList actions) +{ + QVector visibilites; + foreach (auto action, actions) { + visibilites << action->isVisible(); + } + return visibilites; +} + void TestProblemsView::testSwitchTab() { QTabWidget* tab = tabWidget(); - QVERIFY(tab != nullptr); - - QToolBar* tb = toolBar(); - QVERIFY(tb != nullptr); + QVERIFY(tab); // Check that the current widget's actions are in the toolbar QWidget* oldWidget = tab->currentWidget(); - QVERIFY(oldWidget != nullptr); - QVERIFY(compareActions(oldWidget, tb)); + QVERIFY(oldWidget); + const auto oldVisibilites = visibilites(m_view->actions()); tab->setCurrentIndex(1); // Check that the new widget's actions are in the toolbar QWidget* newWidget = tab->currentWidget(); - QVERIFY(newWidget != nullptr); + QVERIFY(newWidget); QVERIFY(newWidget != oldWidget); - QVERIFY(compareActions(newWidget, tb)); + const auto newVisibilites = visibilites(m_view->actions()); + QCOMPARE(oldVisibilites, newVisibilites); } void TestProblemsView::testRemoveModel() { // Remove the model ProblemModelSet* pms = ICore::self()->languageController()->problemModelSet(); ProblemModel* model = pms->findModel(QStringLiteral("MODEL1")); - QVERIFY(model != nullptr); + QVERIFY(model); pms->removeModel(QStringLiteral("MODEL1")); delete model; model = nullptr; // Now let's see if the view has been updated! QTabWidget* tab = tabWidget(); - QVERIFY(tab != nullptr); + QVERIFY(tab); QCOMPARE(tab->count(), 1); QCOMPARE(tab->tabText(0), QStringLiteral("MODEL2 (0)")); } void TestProblemsView::testAddRemoveProblems() { ProblemModelSet* pms = ICore::self()->languageController()->problemModelSet(); ProblemModel* model = pms->findModel(QStringLiteral("MODEL2")); - QVERIFY(model != nullptr); + QVERIFY(model); QTabWidget* tab = tabWidget(); - QVERIFY(tab != nullptr); + QVERIFY(tab); // Make sure there are no problems right now model->clearProblems(); @@ -172,10 +179,10 @@ { ProblemModelSet* pms = ICore::self()->languageController()->problemModelSet(); ProblemModel* model = pms->findModel(QStringLiteral("MODEL2")); - QVERIFY(model != nullptr); + QVERIFY(model); QTabWidget* tab = tabWidget(); - QVERIFY(tab != nullptr); + QVERIFY(tab); // Make sure there are no problems right now model->clearProblems(); @@ -201,27 +208,6 @@ return tab; } -QToolBar* TestProblemsView::toolBar() -{ - QToolBar* tb = m_view->findChild(); - return tb; -} - -bool TestProblemsView::compareActions(QWidget* w, QToolBar* tb) -{ - // Check that they have the same number of actions - if (w->actions().count() != tb->actions().count()) - return false; - - // Check that the actions are the same - for (int i = 0; i < w->actions().count(); i++) { - if (w->actions().at(i) != tb->actions().at(i)) - return false; - } - - return true; -} - QTEST_MAIN(TestProblemsView) #include "test_problemsview.moc" diff --git a/plugins/projectfilter/kdevprojectfilter.json b/plugins/projectfilter/kdevprojectfilter.json --- a/plugins/projectfilter/kdevprojectfilter.json +++ b/plugins/projectfilter/kdevprojectfilter.json @@ -2,17 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "Milian Wolff" + "Name": "Milian Wolff", + "Name[x-test]": "xxMilian Wolffxx" } ], "Category": "Project Management", "Description": "Configure which files and folders inside the project folder should be included or excluded.", + "Description[ar]": "اضبط أيّ الملفّات والمجلّدات داخل مجلّد المشروع يجب تضمينها أو استثنائها.", "Description[ca@valencia]": "Configura quins fitxers i carpetes dins de la carpeta del projecte s'han d'incloure o excloure.", "Description[ca]": "Configura quins fitxers i carpetes dins de la carpeta del projecte s'han d'incloure o excloure.", "Description[de]": "Legt fest, welche Dateien und Ordner innerhalb des Projektordners ein- oder ausgeschlossen werden sollen.", - "Description[en_GB]": "Configure which files and folders inside the project folder should be included or excluded.", "Description[es]": "Configurar los archivos y carpetas que pertenecen a la carpeta del proyecto y que deben ser incluidos o excluidos.", - "Description[et]": "Määramine, millised projektikataloogi failid ja kataloogid kaasata või välja jätta.", "Description[fi]": "Valitse, mitkä projektikansiossa olevat tiedostot ja kansiot pitäisi ottaa mukaan ja mitkä pitäisi jättää pois.", "Description[gl]": "Configurar cales ficheiros e cartafoles dentro do cartafol do proxecto deben incluírse ou excluírse.", "Description[it]": "Configura quali file e cartelle nella cartella del progetto devono essere incluse o escluse.", @@ -23,32 +23,40 @@ "Description[sk]": "Nastaviť, ktoré súbory a priečinky v priečinku projektu majú byť zahrnuté alebo vylúčené.", "Description[sl]": "Nastavi katere datoteke in mape znotraj mape projekta naj bodo vključene ali izključene.", "Description[sv]": "Anpassa vilka filer och kataloger inne i projektkatalogen som ska inkluderas eller exkluderas.", + "Description[tr]": "Proje klasörü içerisindeki hangi dosya ve klasörlerin dahil edilip edilmeyeceğini yapılandır.", "Description[uk]": "За допомогою цього модуля можна визначити, які файли і теки у теці проекту має бути включено або виключено з його складу.", "Description[x-test]": "xxConfigure which files and folders inside the project folder should be included or excluded.xx", "Description[zh_CN]": "配置项目文件中哪些文件被加入或排除。", "Icon": "view-filter", "Id": "KDevProjectFilter", "Name": "Project Filter", + "Name[ar]": "مرشّح المشروع", + "Name[bs]": "Filter projekta", "Name[ca@valencia]": "Filtre de projecte", "Name[ca]": "Filtre de projecte", + "Name[da]": "Projektfilter", "Name[de]": "Projektfilter", - "Name[en_GB]": "Project Filter", "Name[es]": "Filtro del proyecto", "Name[et]": "Projektifilter", "Name[fi]": "Projektisuodatin", "Name[gl]": "Filtro do proxecto", + "Name[hu]": "Projektszűrő", "Name[it]": "Filtro progetto", + "Name[kk]": "Жоба сүзгісі", "Name[nb]": "Prosjektfilter", "Name[nl]": "Projectfilter", "Name[pl]": "Filtr projektu", "Name[pt]": "Filtro de Projectos", "Name[pt_BR]": "Filtro de projetos", + "Name[ru]": "Фильтр проекта", "Name[sk]": "Filter projektu", "Name[sl]": "Filter projektov", "Name[sv]": "Projektfilter", + "Name[tr]": "Proje Süzgeci", "Name[uk]": "Фільтр проекту", "Name[x-test]": "xxProject Filterxx", "Name[zh_CN]": "项目过滤器", + "Name[zh_TW]": "專案過濾器", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/projectmanagerview/kdevprojectmanagerview.json b/plugins/projectmanagerview/kdevprojectmanagerview.json --- a/plugins/projectmanagerview/kdevprojectmanagerview.json +++ b/plugins/projectmanagerview/kdevprojectmanagerview.json @@ -2,17 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "Roberto Raggi" + "Name": "Roberto Raggi", + "Name[x-test]": "xxRoberto Raggixx" } ], "Category": "Core", "Description": "Lets you manage the project contents.", + "Description[ar]": "يتيح لك إدارة محتويات المشروع.", "Description[ca@valencia]": "Vos permet gestionar els continguts del projecte.", "Description[ca]": "Us permet gestionar els continguts del projecte.", "Description[de]": "Lässt Sie den Inhalt Ihres Projekts verwalten.", - "Description[en_GB]": "Lets you manage the project contents.", "Description[es]": "Le permite gestionar el contenido del proyecto.", - "Description[et]": "Projektide sisu haldamine.", "Description[fi]": "Mahdollistaa projektien sisällön hallinnan.", "Description[gl]": "Permítelle xestionar os contidos do proxecto.", "Description[it]": "Consente di gestire il contenuto del progetto.", @@ -23,37 +23,50 @@ "Description[sk]": "Umožní vám spravovať obsah projektu.", "Description[sl]": "Pomaga vam upravljati z vsebino projekta.", "Description[sv]": "Låter dig hantera projektets innehåll.", + "Description[tr]": "Proje içeriğini yönetmenizi sağlar.", "Description[uk]": "Надає вам змогу керувати вмістом проектів.", "Description[x-test]": "xxLets you manage the project contents.xx", "Description[zh_CN]": "让您管理项目内容。", "Icon": "kdevelop", "Id": "KDevProjectManagerView", "License": "LGPL", "Name": "Project Manager View", + "Name[ar]": "عرض مدير المشاريع", + "Name[bg]": "Преглед на редактора на проекти", + "Name[bs]": "Pregled menadžera projekta", "Name[ca@valencia]": "Vista del gestor de projectes", "Name[ca]": "Vista del gestor de projectes", + "Name[da]": "Visning af projekthåndtering", "Name[de]": "Ansicht für Projektverwaltung", - "Name[en_GB]": "Project Manager View", + "Name[el]": "Προβολή διαχειριστή έργου", "Name[es]": "Vista del gestor de proyectos", "Name[et]": "Projektihalduri vaade", "Name[fi]": "Projektinhallintanäkymä", "Name[gl]": "Vista do xestor de proxectos", + "Name[hu]": "Projektkezelő nézet", "Name[it]": "Vista gestore progetto", + "Name[kk]": "Жоба менеджер көрінісі", "Name[nb]": "Prosjektbehandlervisning", + "Name[nds]": "Projektpleger-Ansicht", "Name[nl]": "Projectbeheerder-overzicht", + "Name[pa]": "ਪਰੋਜੈਕਟ ਮੈਨੇਜਰ ਝਲਕ", "Name[pl]": "Widok zarządzania projektem", "Name[pt]": "Área do Gestor de Projectos", "Name[pt_BR]": "Visualizador do gerenciador de projeto", + "Name[ru]": "Панель управления проектами", "Name[sk]": "Pohľad na správcu projektu", "Name[sl]": "Prikaz upravljalnika projektov", "Name[sv]": "Projekthanteringsvisning", + "Name[tr]": "Proje Yöneticisi Görünümü", + "Name[ug]": "قۇرۇلۇش باشقۇرغۇ كۆرۈنۈشى", "Name[uk]": "Перегляд керування проектами", "Name[x-test]": "xxProject Manager Viewxx", "Name[zh_CN]": "工程管理器视图", + "Name[zh_TW]": "專案管理員檢視", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/projectmanagerview/projectmanagerviewplugin.cpp b/plugins/projectmanagerview/projectmanagerviewplugin.cpp --- a/plugins/projectmanagerview/projectmanagerviewplugin.cpp +++ b/plugins/projectmanagerview/projectmanagerviewplugin.cpp @@ -241,13 +241,13 @@ } if ( needsCreateFile ) { - QAction* action = new QAction( i18n( "Create File" ), this ); + QAction* action = new QAction( i18n( "Create File..." ), this ); action->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::createFileFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); } if ( needsCreateFolder ) { - QAction* action = new QAction( i18n( "Create Folder" ), this ); + QAction* action = new QAction( i18n( "Create Folder..." ), this ); action->setIcon(QIcon::fromTheme(QStringLiteral("folder-new"))); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::createFolderFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); @@ -289,7 +289,7 @@ remove->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); connect( remove, &QAction::triggered, this, &ProjectManagerViewPlugin::removeFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, remove ); - QAction* rename = new QAction( i18n( "Rename" ), this ); + QAction* rename = new QAction( i18n( "Rename..." ), this ); rename->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename"))); connect( rename, &QAction::triggered, this, &ProjectManagerViewPlugin::renameItemFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, rename ); diff --git a/plugins/quickopen/kdevquickopen.json b/plugins/quickopen/kdevquickopen.json --- a/plugins/quickopen/kdevquickopen.json +++ b/plugins/quickopen/kdevquickopen.json @@ -2,17 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "David Nolden" + "Name": "David Nolden", + "Name[x-test]": "xxDavid Noldenxx" } ], "Category": "Core", "Description": "This plugin allows quick access to project files and language-items like classes/functions.", + "Description[ar]": "تسمح هذه الملحقة بالوصول السريع إلى ملفّات المشروع وعناصر اللغة كالأصناف والدّوال.", "Description[ca@valencia]": "Este connector permet un ràpid accés als fitxers del projecte i a elements del llenguatge com classes/funcions.", "Description[ca]": "Aquest connector permet un ràpid accés als fitxers del projecte i a elements del llenguatge com classes/funcions.", "Description[de]": "Dieses Modul bietet schnellen Zugriff auf Projektdateien und Sprachelemente wie Klassen und Funktionen.", - "Description[en_GB]": "This plugin allows quick access to project files and language-items like classes/functions.", "Description[es]": "Este complemento permite acceder rápidamente a los archivos del proyecto y a elementos del lenguaje, como clases y funciones.", - "Description[et]": "See plugin pakub kiiret ligipääsu projekti failidele ja keele elementidele, näiteks klassidele ja funktsioonidele.", "Description[fi]": "Tämä liitännäinen mahdollistaa projektitiedostojen nopean haun ja kielialkiot kuten luokat/funktiot.", "Description[gl]": "Este complemento permite acceder rapidamente a ficheiros de proxecto e elementos da linguaxe como clases e funcións.", "Description[it]": "Questa estensione permette di accedere rapidamente ai file di progetto e agli elementi del linguaggio come le classi/funzioni.", @@ -23,33 +23,46 @@ "Description[sk]": "Tento plugin umožňuje rýchly prístup k súborom projektu a položiek jazyka ako triedy/funkcie.", "Description[sl]": "Vstavek omogoča hiter dostop do projektnih datotek in predmetov kot so razredi in funkcije.", "Description[sv]": "Insticksprogrammet ger snabb åtkomst av projektfiler och språkobjekt som klasser och funktioner.", + "Description[tr]": "Bu eklenti proje dosyalarına ve sınıflar/fonksiyonlar gibi dil öğelerine hızlı erişim sağlar.", "Description[uk]": "За допомогою цього додатка можна пришвидшити доступ до файлів проектів і елементів мови на зразок класів або функцій.", "Description[x-test]": "xxThis plugin allows quick access to project files and language-items like classes/functions.xx", "Description[zh_CN]": "此插件允许快速访问工程文件和诸如类/函数的语言项目。", "Icon": "quickopen", "Id": "kdevquickopen", "License": "GPL", "Name": "Quick Open", + "Name[ar]": "فتح سريع", + "Name[bg]": "Бързо отваряне", + "Name[bs]": "Brzo otvori", "Name[ca@valencia]": "Obertura ràpida", "Name[ca]": "Obertura ràpida", + "Name[da]": "Åbn hurtigt", "Name[de]": "Schnellöffner", - "Name[en_GB]": "Quick Open", + "Name[el]": "Γρήγορο άνοιγμα", "Name[es]": "Apertura rápida", "Name[et]": "Kiiravamine", "Name[fi]": "Pika-avaus", + "Name[ga]": "Oscailt Thapa", "Name[gl]": "Apertura rápida", + "Name[hu]": "Gyors megnyitás", "Name[it]": "Apertura veloce", + "Name[kk]": "Тез ашу", "Name[nb]": "Hurtigåpne", + "Name[nds]": "Fixopmaken", "Name[nl]": "Snel openen", "Name[pl]": "Szybkie otwarcie", "Name[pt]": "Abertura Rápida", - "Name[pt_BR]": "Abertura rápida", + "Name[pt_BR]": "Abrir rapidamente", + "Name[ru]": "Быстрый переход", "Name[sk]": "Rýchlo otvoriť", "Name[sl]": "Hitro odpiranje", "Name[sv]": "Snabböppna", + "Name[tr]": "Hızlı Aç", + "Name[ug]": "تېز ئېچىش", "Name[uk]": "Швидке відкриття", "Name[x-test]": "xxQuick Openxx", "Name[zh_CN]": "快速打开", + "Name[zh_TW]": "快速開啟", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/standardoutputview/kdevstandardoutputview.json b/plugins/standardoutputview/kdevstandardoutputview.json --- a/plugins/standardoutputview/kdevstandardoutputview.json +++ b/plugins/standardoutputview/kdevstandardoutputview.json @@ -5,9 +5,7 @@ "Description[ca@valencia]": "Proporciona una vista d'eina d'eixida de text per a utilitzar en altres connectors, per a visualitzar missatges del compilador, per exemple.", "Description[ca]": "Proporciona una vista d'eina de sortida de text per a utilitzar en altres connectors, per a visualitzar missatges del compilador, per exemple.", "Description[de]": "Stellt eine Textausgabe für andere Module zur Verfügung, um Dinge wie Compiler-Nachrichten anzuzeigen.", - "Description[en_GB]": "Provides a text output toolview for other plugins to use, to show things like compiler messages.", "Description[es]": "Proporciona un visor de salida de texto para que otros complementos muestren cosas como mensajes del compilador, por ejemplo.", - "Description[et]": "Teistele pluginatele kättesaadav tekstiväljundi tööriistavaade, mis näitab kompilaatori teateid ja muud.", "Description[fi]": "Tarjoaa tekstitulostetyökalunäkymän muille liitännäisille käytettäväksi, näyttää asiat kuin kääntäjäviestit.", "Description[gl]": "Fornece unha ferramenta de saída de texto a outros complementos, para mostrar cousas como mensaxes do compilador.", "Description[it]": "Fornisce una vista strumenti testuale per le estensioni da usare, per mostrare le cose come i messaggi del compilatore.", @@ -18,32 +16,45 @@ "Description[sk]": "Poskytuje textový výstup pohľadu nástrojov pre iné pluginy na použitie, na zobrazenie napríklad správy prekladača.", "Description[sl]": "Drugim vstavkom ponuja okno za prikaz besedilnega izhoda, na primer za sporočila izgrajevalnika.", "Description[sv]": "Tillhandahåller en verktygsvy för textutmatning som andra insticksprogram kan använda för att visa saker som kompilatormeddelanden.", + "Description[tr]": "Diğer eklentilerin derleyici iletileri gibi şeyleri göstermesi için metin çıktı araç görünümü sağlar.", "Description[uk]": "Забезпечує роботу панелі показу текстових даних інших додатків, зокрема попереджень компілятора.", "Description[x-test]": "xxProvides a text output toolview for other plugins to use, to show things like compiler messages.xx", "Description[zh_CN]": "提供让其它插件使用的文本输出工具视图,以便显示诸如编译器消息的信息。", "Icon": "gear", "Id": "KDevStandardOutputView", "Name": "Output View", + "Name[ar]": "عرض الخَرْج", + "Name[bg]": "Преглед на резултата", + "Name[bs]": "Pregled izlaza", "Name[ca@valencia]": "Vista de l'eixida", "Name[ca]": "Vista de la sortida", + "Name[da]": "Visning af output", "Name[de]": "Ansicht für Ausgaben", - "Name[en_GB]": "Output View", + "Name[el]": "Προβολή αποτελεσμάτων", "Name[es]": "Vista de la salida", "Name[et]": "Väljundivaade", "Name[fi]": "Tulostenäkymä", + "Name[ga]": "Amharc Aschurtha", "Name[gl]": "Vista da saída", + "Name[hu]": "Kimenet nézet", "Name[it]": "Vista output", + "Name[kk]": "Шығыс көрінісі", "Name[nb]": "Utdata-visning", + "Name[nds]": "Utgaavansicht", "Name[nl]": "Uitvoerweergave", "Name[pl]": "Widok wyjścia", "Name[pt]": "Área de Resultados", "Name[pt_BR]": "Área de Resultados", + "Name[ru]": "Панель вывода", "Name[sk]": "Pohľad na výstup", "Name[sl]": "Prikaz izhoda", "Name[sv]": "Utmatningsvisning", + "Name[tr]": "Çıktı Görünümü", + "Name[ug]": "چىقىرىش كۆرۈنۈشى", "Name[uk]": "Перегляд виводу", "Name[x-test]": "xxOutput Viewxx", "Name[zh_CN]": "输出视图", + "Name[zh_TW]": "輸出檢視", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/subversion/kdevsubversion.json b/plugins/subversion/kdevsubversion.json --- a/plugins/subversion/kdevsubversion.json +++ b/plugins/subversion/kdevsubversion.json @@ -2,18 +2,17 @@ "KPlugin": { "Authors": [ { - "Name": "Dukju Ahn" + "Name": "Dukju Ahn", + "Name[x-test]": "xxDukju Ahnxx" } ], "Category": "Version Control", "Description": "This plugin integrates subversion to KDevelop.", "Description[ca@valencia]": "Este connector integra el «subversion» en el KDevelop.", "Description[ca]": "Aquest connector integra el «subversion» en el KDevelop.", "Description[cs]": "Tento modul integruje podporu pro subversion v KDevelop", "Description[de]": "Dieses Modul integriert Subversion in KDevelop.", - "Description[en_GB]": "This plugin integrates subversion to KDevelop.", "Description[es]": "Este complemento integra Subversion en KDevelop", - "Description[et]": "See plugin lõimib Subversioni KDevelopiga.", "Description[fi]": "Tämä liitännäinen integroi subversionin KDevelopiin.", "Description[gl]": "Este complemento integra subversion en KDevelop.", "Description[it]": "Questa estensione integra subversion in KDevelop.", @@ -24,34 +23,46 @@ "Description[sk]": "Tento plugin integruje subversion do KDevelop.", "Description[sl]": "Vstavek v KDevelop vgradi Subversion.", "Description[sv]": "Insticksprogrammet integrerar Subversion i KDevelop.", + "Description[tr]": "Bu eklenti subversion'u KDevelop'a bütünleştirir.", "Description[uk]": "Цей додаток інтегрує Subversion із KDevelop", "Description[x-test]": "xxThis plugin integrates subversion to KDevelop.xx", "Description[zh_CN]": "此插件对 KDevelop 整合 subversion。", "Icon": "subversion", "Id": "kdevsubversion", "License": "GPL", "Name": "Subversion Support", + "Name[bg]": "Поддръжка на Subversion", + "Name[bs]": "Podrška za subversion", "Name[ca@valencia]": "Implementació del «subversion»", "Name[ca]": "Implementació del «subversion»", "Name[cs]": "Podpora subversion", + "Name[da]": "Subversion-understøttelse", "Name[de]": "Subversion-Unterstützung", - "Name[en_GB]": "Subversion Support", + "Name[el]": "Υποστήριξη Subversion", "Name[es]": "Implementación de Subversion", "Name[et]": "Subversioni toetus", "Name[fi]": "Subversion-tuki", "Name[gl]": "Soporte de Subversion", + "Name[hu]": "Subversion támogatás", "Name[it]": "Supporto subversion", + "Name[kk]": "Subversion қолдауы", "Name[nb]": "Støtte for subversion", + "Name[nds]": "Subversion-Ünnerstütten", "Name[nl]": "Ondersteuning van subversion", + "Name[pa]": "ਸਬਵਰਜਨ ਸਹਿਯੋਗ", "Name[pl]": "Obsługa Subversion", "Name[pt]": "Suporte para o Subversion", "Name[pt_BR]": "Suporte a Subversion", + "Name[ru]": "Поддержка Subversion", "Name[sk]": "Podpora subversion", "Name[sl]": "Podpora za Subversion", "Name[sv]": "Stöd för Subversion", + "Name[tr]": "Subversion Desteği", + "Name[ug]": "Subversion قوللىشى", "Name[uk]": "Підтримка Subversion", "Name[x-test]": "xxSubversion Supportxx", "Name[zh_CN]": "Subversion 支持", + "Name[zh_TW]": "Subversion 支援", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/plugins/switchtobuddy/kdevswitchtobuddy.json b/plugins/switchtobuddy/kdevswitchtobuddy.json --- a/plugins/switchtobuddy/kdevswitchtobuddy.json +++ b/plugins/switchtobuddy/kdevswitchtobuddy.json @@ -5,9 +5,7 @@ "Description[ca@valencia]": "Permet commutar entre documents associats com fitxers d'implementacions i de capçaleres.", "Description[ca]": "Permet commutar entre documents associats com fitxers d'implementacions i de capçaleres.", "Description[de]": "Ermöglicht das Umschalten zwischen verwandten Dokumenten wie Implementations- und Header-Dateien.", - "Description[en_GB]": "Allows switching between buddy documents like implementation and header file.", "Description[es]": "Permite cambiar entre documentos complementarios, como la implementación y el archivo de cabecera.", - "Description[et]": "Võimaldab lülituda sõltlasdokumentide, näiteks teostus- ja päisefaili vahel.", "Description[fi]": "Mahdollistaa vaihtamisen yhteen kuuluvien tiedostojen, kuten toteutus- ja otsikkotiedoston, välillä.", "Description[gl]": "Permite trocar entre documentos tipo buddy como implementación e ficheiro de cabeceira.", "Description[it]": "Consente il passaggio tra i documenti associati come implementazioni e header file.", @@ -18,36 +16,44 @@ "Description[sk]": "Umožňuje prepínanie medzi dokumentmi priateľov ako súbor implementácie a hlavičky.", "Description[sl]": "Omogoča preklapljanje med prijateljskimi dokumenti kot na primer izvedbo in datoteko glave.", "Description[sv]": "Tillåter byte mellan samhörande dokument som implementerings- och deklarationsfiler.", + "Description[tr]": "Uygulama ve başlık dosyası gibi ilişkili belgeler arasında geçişe izin verir.", "Description[uk]": "Надає змогу перемикатися на споріднені документи, зокрема файли з реалізацією та файли заголовків.", "Description[x-test]": "xxAllows switching between buddy documents like implementation and header file.xx", "Description[zh_CN]": "允许在伙伴文件中切换,如实现与头文件", "Icon": "document-multiple", "Id": "kdevswitchtobuddy", "Name": "Switch to Buddy", + "Name[bs]": "Pređi na prijatelja", "Name[ca@valencia]": "Commuta a associat", "Name[ca]": "Commuta a associat", + "Name[da]": "Skift til vennefil", "Name[de]": "Zu verwandtem Element wechseln", - "Name[en_GB]": "Switch to Buddy", + "Name[el]": "Εναλλαγή στο συμπληρωματικό", "Name[es]": "Cambiar a relacionado", "Name[et]": "Lülitumine sõltlasele", "Name[fi]": "Vaihda yhteen kuuluvaan tiedostoon", "Name[gl]": "Pasar a Buddy", + "Name[hu]": "Váltás az ismerősre", "Name[it]": "Passa al file associato", + "Name[kk]": "Тиістіге ауысу", "Name[nb]": "Bytt til kamerat", "Name[nl]": "Naar Buddy omschakelen", "Name[pl]": "Przełącz do stowarzyszonego", "Name[pt]": "Mudar para o Ficheiro Associado", "Name[pt_BR]": "Mudar para o arquivo associado", + "Name[ru]": "Переход к связанному", "Name[sk]": "Prepnúť na Buddy", "Name[sl]": "Preklopi na prijatelja", "Name[sv]": "Byt till samhörande", + "Name[tr]": "Dosta Geçiş Yap", "Name[uk]": "Перемикання на споріднений", "Name[x-test]": "xxSwitch to Buddyxx", "Name[zh_CN]": "切换至伙伴文件", + "Name[zh_TW]": "切換到相關文件", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/testview/kdevtestview.json b/plugins/testview/kdevtestview.json --- a/plugins/testview/kdevtestview.json +++ b/plugins/testview/kdevtestview.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Name": "Miha Čančula" + "Name": "Miha Čančula", + "Name[x-test]": "xxMiha Čančulaxx" } ], "Category": "Testing", "Description": "Lets you see and run unit tests.", "Description[ca@valencia]": "Vos permet veure i executar proves unitàries.", "Description[ca]": "Us permet veure i executar proves unitàries.", "Description[de]": "Unit-Tests anzeigen und ausführen.", - "Description[en_GB]": "Lets you see and run unit tests.", "Description[es]": "Le permite ver y ejecutar pruebas unitarias.", - "Description[et]": "Ühiktestide näitamine ja käivitamine.", "Description[fi]": "Mahdollistaa yksikkötestien tarkastelemisen ja suorittamisen.", "Description[gl]": "Permite ver e executar probas unitarias.", "Description[it]": "Consente di vedere ed eseguire i test d'unità.", @@ -23,37 +22,45 @@ "Description[sk]": "Umožní vám vidieť a spustiť unit testy.", "Description[sl]": "Omogoča ogled in zagon preizkusov enot.", "Description[sv]": "Låter dig titta på och köra enhetstester.", + "Description[tr]": "Birim testlerini görmenizi ve çalıştırmanızı sağlar.", "Description[uk]": "Надає вам змогу переглядати і виконувати перевірки модулів.", "Description[x-test]": "xxLets you see and run unit tests.xx", "Description[zh_CN]": "让您查看并运行单元测试。", "Icon": "preflight-verifier", "Id": "kdevtestview", "License": "GPL", "Name": "Unit Test View", + "Name[bs]": "Pogled testa jedinica", "Name[ca@valencia]": "Vista de proves unitàries", "Name[ca]": "Vista de proves unitàries", + "Name[da]": "Visning af unittests", "Name[de]": "Unittest-Ansicht", - "Name[en_GB]": "Unit Test View", + "Name[el]": "Προβολή unit test", "Name[es]": "Vista de la prueba unitaria", "Name[et]": "Ühiktestide vaade", "Name[fi]": "Yksikkötestinäkymä", "Name[gl]": "Vista de probas unitarias", + "Name[hu]": "Egységteszt nézet", "Name[it]": "Vista test d'unità", + "Name[kk]": "Модульді сынау көрінісі", "Name[nb]": "Enhetstest-visning", "Name[nl]": "Weergave van test van eenheid", "Name[pl]": "Widok jednostkowego testu", "Name[pt]": "Área de Testes Unitários", "Name[pt_BR]": "Exibição de testes unitários", + "Name[ru]": "Панель модульных тестов", "Name[sk]": "Pohľad unit testov", "Name[sl]": "Prikaz preizkusov enot", "Name[sv]": "Visning av enhetstester", + "Name[tr]": "Birim Test Görünümü", "Name[uk]": "Перегляд перевірок модулів", "Name[x-test]": "xxUnit Test Viewxx", "Name[zh_CN]": "单元测试视图", + "Name[zh_TW]": "單元測試檢視", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/vcschangesview/kdevvcschangesview.json b/plugins/vcschangesview/kdevvcschangesview.json --- a/plugins/vcschangesview/kdevvcschangesview.json +++ b/plugins/vcschangesview/kdevvcschangesview.json @@ -3,17 +3,17 @@ "Authors": [ { "Email": "aleixpol@kde.org", - "Name": "Aleix Pol" + "Name": "Aleix Pol", + "Name[x-test]": "xxAleix Polxx" } ], "Category": "Version Control", "Description": "This plugin provides integration between the projects and their VCS infrastructure", + "Description[ar]": "توفّر هذه الملحقة التّكامل بين مشاريعك ومركزيّة VCS", "Description[ca@valencia]": "Este connector proporciona la integració entre els projectes i la seua infraestructura de VCS", "Description[ca]": "Aquest connector proporciona la integració entre els projectes i la seva infraestructura de VCS", "Description[de]": "Dieses Modul stellt eine Integration zwischen Projekten und ihrer VCS-Infrastruktur her.", - "Description[en_GB]": "This plugin provides integration between the projects and their VCS infrastructure", "Description[es]": "Este complemento proporciona integración entre los proyectos y su infraestructura VCS", - "Description[et]": "See plugin võimaldab lõimida projektid ja nende versioonihalduse infrastruktuuri", "Description[fi]": "Tämä liitännäinen tarjoaa projektien ja niiden versionhallintajärjestelmien välisen integraation", "Description[gl]": "Este complemento fornece integración entre os proxectos e a súa infraestrutura VCS", "Description[it]": "Questa estensione fornisce integrazione tra i progetti e la loro infrastruttura VCS", @@ -24,37 +24,49 @@ "Description[sk]": "Tento plugin poskytuje integráciu medzi projektami a ich VCS infraštruktúrou", "Description[sl]": "Ta vstavek ponuja most med projekti in njihovo infrastrukturo nadzora različic", "Description[sv]": "Det här insticksprogrammet tillhandahåller integrering mellan projekten och deras VCS infrastruktur", + "Description[tr]": "Bu eklenti projeler ile VCS altyapıları arasında bütünleşme sağlar", "Description[uk]": "За допомогою цього додатка забезпечується інтеграція між проектами та інфраструктурою системи керування версіями (VCS)", "Description[x-test]": "xxThis plugin provides integration between the projects and their VCS infrastructurexx", "Description[zh_CN]": "此插件提供工程和它们的代码管理系统的集成", "Icon": "git", "Id": "kdevvcschangesviewplugin", "License": "GPL", "Name": "VCS Integration", + "Name[ar]": "تكامل VCS", + "Name[bg]": "Интеграция с VCS", + "Name[bs]": "VCS Integracija", "Name[ca@valencia]": "Integració de VCS", "Name[ca]": "Integració de VCS", + "Name[da]": "VCS-integration", "Name[de]": "VCS-Integration", - "Name[en_GB]": "VCS Integration", + "Name[el]": "VCS ολοκλήρωση", "Name[es]": "Integración VCS", "Name[et]": "Versioonihalduse lõimimine", "Name[fi]": "VCS-integraatio", "Name[gl]": "Integración con VCS", + "Name[hu]": "VCS integráció", "Name[it]": "Integrazione VCS", + "Name[kk]": "Нұсқаларын қадағалау жүйесімен біріктіру ", "Name[nb]": "VCS-integrering", + "Name[nds]": "VKS-Inbinnen", "Name[nl]": "VCS-integratie", "Name[pl]": "Integracja VCS", "Name[pt]": "Integração com o SCV", "Name[pt_BR]": "Integração com o VCS", + "Name[ru]": "Интеграция VCS", "Name[sk]": "Integrácia VCS", "Name[sl]": "Vgradnja nadzora različic", "Name[sv]": "Integrering av VCS", + "Name[tr]": "Sürüm Kontrol Sistemi Bütünleşmesi", + "Name[ug]": "VCS يۈرۈشلەشتۈرۈلۈشى", "Name[uk]": "Інтеграція з системами керування версіями", "Name[x-test]": "xxVCS Integrationxx", "Name[zh_CN]": "VCS 工程集成", + "Name[zh_TW]": "版本控制系統整合", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Global", "X-KDevelop-Mode": "GUI" } \ No newline at end of file diff --git a/plugins/welcomepage/kdevwelcomepage.json b/plugins/welcomepage/kdevwelcomepage.json --- a/plugins/welcomepage/kdevwelcomepage.json +++ b/plugins/welcomepage/kdevwelcomepage.json @@ -1,12 +1,11 @@ { "KPlugin": { "Description": "Configure which macros and include directories/files will be added to the parser during project parsing.", + "Description[ar]": "اضبط أيّ الماكروهات والملفّات/الأدلّة المضمّنة ستُضاف إلى المحلّل أثناء تحليل المشروع.", "Description[ca@valencia]": "Configura quines macros i directoris/fitxers s'afegiran a l'analitzador durant l'anàlisi del projecte.", "Description[ca]": "Configura quines macros i directoris/fitxers s'afegiran a l'analitzador durant l'anàlisi del projecte.", "Description[de]": "Einstellung der Makros und Include-Ordner/-Dateien, die für den Parser während des Einlesens des Projekts hinzugefügt werden.", - "Description[en_GB]": "Configure which macros and include directories/files will be added to the parser during project parsing.", "Description[es]": "Configurar las macros y los directorios/archivos a incluir que se añadirán al analizador sintáctico durante el análisis de los proyectos.", - "Description[et]": "Aitab seadistada, millised makrod ja päistekataloogid või -failid lisada parserile projekti parsimiseks.", "Description[fi]": "Määritä, mitkä makrot ja include-hakemistot/tiedostot lisätään jäsentimelle projektin jäsentämisen aikana.", "Description[gl]": "Configure que macros e ficheiros ou cartafoles de inclusión se engaden ao analizador do proxecto.", "Description[it]": "Configura quali macro e cartelle/file di inclusione saranno aggiunti all'analizzatore durante l'analisi del progetto.", @@ -17,28 +16,30 @@ "Description[sk]": "Nastaviť, ktoré makrá a zahrnuté adresáre/súbory sa pridajú do spracovača počas spracovania projektu.", "Description[sl]": "Nastavi, kateri makri in mape/datoteke z vključitvami bodo dodane razčlenjevalniku med razčlenjevanjem projekta.", "Description[sv]": "Anpassa vilka makron och filer eller kataloger att inkludera som läggs till i tolken under projekttolkning.", + "Description[tr]": "Proje ayrıştırma süresinde hangi makroların ve içerme dizinlerinin/dosyalarının ayrıştırıcıya ekleneceğini ayarla.", "Description[uk]": "Налаштувати макроси і включені каталоги або файли, які буде додано під час обробки проекту.", "Description[x-test]": "xxConfigure which macros and include directories/files will be added to the parser during project parsing.xx", "Description[zh_CN]": "配置在解析项目时加入哪些宏、引用目录和文件。", "Icon": "kdevelop", "Id": "KDevWelcomePage", "Name": "KDevelop Welcome Page", + "Name[ar]": "صفحة ترحيب مطوّرك", "Name[ca@valencia]": "Pàgina de benvinguda del KDevelop", "Name[ca]": "Pàgina de benvinguda del KDevelop", "Name[de]": "KDevelop-Startseite", - "Name[en_GB]": "KDevelop Welcome Page", "Name[es]": "Página de bienvenida de KDevelop", - "Name[et]": "KDevelopi tervituslehekülg", "Name[fi]": "KDevelopin tervetulosivu", "Name[gl]": "Páxina de benvida de KDevelop", + "Name[hu]": "KDevelop üdvözlőképernyő", "Name[it]": "Pagina di benvenuto di KDevelop", "Name[nl]": "Welkomstpagina van KDevelop", "Name[pl]": "Strona powitalna KDevelop", "Name[pt]": "Página de Boas-Vindas do KDevelop", "Name[pt_BR]": "Página de boas-vindas do KDevelop", "Name[sk]": "Uvítacia stránka KDevelop", "Name[sl]": "Pozdravna stran za KDevelop", "Name[sv]": "KDevelop välkomstsida", + "Name[tr]": "KDevelop Karşılama Sayfası", "Name[uk]": "Сторінка вітання KDevelop", "Name[x-test]": "xxKDevelop Welcome Pagexx", "Name[zh_CN]": "KDevelop 欢迎页面", diff --git a/project/CMakeLists.txt b/project/CMakeLists.txt --- a/project/CMakeLists.txt +++ b/project/CMakeLists.txt @@ -20,8 +20,11 @@ interfaces/ibuildsystemmanager.cpp interfaces/iprojectfilter.cpp interfaces/iprojectfilterprovider.cpp + widgets/dependencieswidget.cpp ) +ki18n_wrap_ui( KDevPlatformProject_LIB_SRCS widgets/dependencieswidget.ui) + kdevplatform_add_library(KDevPlatformProject SOURCES ${KDevPlatformProject_LIB_SRCS}) target_link_libraries(KDevPlatformProject LINK_PUBLIC @@ -61,3 +64,8 @@ projectfiltermanager.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/project COMPONENT Devel ) + +install(FILES + widgets/dependencieswidget.h + DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/project/widgets COMPONENT Devel +) diff --git a/project/interfaces/ibuildsystemmanager.h b/project/interfaces/ibuildsystemmanager.h --- a/project/interfaces/ibuildsystemmanager.h +++ b/project/interfaces/ibuildsystemmanager.h @@ -64,6 +64,11 @@ virtual Path::List includeDirectories(ProjectBaseItem*) const = 0; /** + * Provide a list of framework directories. + */ + virtual Path::List frameworkDirectories(ProjectBaseItem*) const = 0; + + /** * Provide a list of preprocessor defines for the project item */ virtual QHash defines(ProjectBaseItem*) const = 0; @@ -114,7 +119,7 @@ /** * Returns if the build system has information specific to @p item */ - virtual bool hasIncludesOrDefines(ProjectBaseItem* item) const = 0; + virtual bool hasBuildInfo(ProjectBaseItem* item) const = 0; /** * Get the toplevel build directory for the project diff --git a/project/widgets/dependencieswidget.h b/project/widgets/dependencieswidget.h new file mode 100644 --- /dev/null +++ b/project/widgets/dependencieswidget.h @@ -0,0 +1,61 @@ +/* This file is part of KDevelop + Copyright 2009 Andreas Pakulat + Copyright 2009 Niko Sams + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef DEPENDENCIESWIDGET_H +#define DEPENDENCIESWIDGET_H + +#include +#include +#include + +namespace Ui { class DependenciesWidget; } +namespace KDevelop { +class IProject; + +class KDEVPLATFORMPROJECT_EXPORT DependenciesWidget : public QWidget +{ + Q_OBJECT + public: + DependenciesWidget(QWidget* parent); + ~DependenciesWidget(); + + void setSuggestion(KDevelop::IProject* project); + + void setDependencies(const QVariantList &deps); + QVariantList dependencies() const; + + Q_SIGNALS: + void changed(); + + private: + void depEdited( const QString& str ); + void checkActions( const QItemSelection& selected, const QItemSelection& unselected ); + void moveDependencyDown(); + void moveDependencyUp(); + void addDep(); + void removeDep(); + void selectItemDialog(); + + Ui::DependenciesWidget* m_ui; +}; + +} + +#endif diff --git a/project/widgets/dependencieswidget.cpp b/project/widgets/dependencieswidget.cpp new file mode 100644 --- /dev/null +++ b/project/widgets/dependencieswidget.cpp @@ -0,0 +1,179 @@ +/* This file is part of KDevelop + Copyright 2009 Andreas Pakulat + Copyright 2009 Niko Sams + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "dependencieswidget.h" +#include "ui_dependencieswidget.h" +#include +#include +#include +#include + +using namespace KDevelop; + +static KDevelop::ProjectBaseItem* itemForPath(const QStringList& path, KDevelop::ProjectModel* model) +{ + return model->itemFromIndex(model->pathToIndex(path)); +} + +DependenciesWidget::DependenciesWidget(QWidget* parent) + : QWidget(parent) + , m_ui(new Ui::DependenciesWidget) +{ + m_ui->setupUi(this); + + connect( m_ui->addDependency, &QPushButton::clicked, this, &DependenciesWidget::addDep ); + connect( m_ui->addDependency, &QPushButton::clicked, this, &DependenciesWidget::changed ); + connect( m_ui->removeDependency, &QPushButton::clicked, this, &DependenciesWidget::changed ); + connect( m_ui->removeDependency, &QPushButton::clicked, this, &DependenciesWidget::removeDep ); + connect( m_ui->moveDepDown, &QPushButton::clicked, this, &DependenciesWidget::changed ); + connect( m_ui->moveDepUp, &QPushButton::clicked, this, &DependenciesWidget::changed ); + connect( m_ui->moveDepDown, &QPushButton::clicked, this, &DependenciesWidget::moveDependencyDown ); + connect( m_ui->moveDepUp, &QPushButton::clicked, this, &DependenciesWidget::moveDependencyUp ); + connect( m_ui->dependencies->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DependenciesWidget::checkActions ); + connect( m_ui->targetDependency, &ProjectItemLineEdit::textChanged, this, &DependenciesWidget::depEdited); + connect( m_ui->browseProject, &QPushButton::clicked, this, &DependenciesWidget::selectItemDialog); +} + +DependenciesWidget::~DependenciesWidget() +{ + delete m_ui; +} + +void DependenciesWidget::setSuggestion(KDevelop::IProject* project) +{ + m_ui->targetDependency->setSuggestion(project); +} + +void DependenciesWidget::depEdited( const QString& str ) +{ + int pos; + QString tmp = str; + m_ui->addDependency->setEnabled( !str.isEmpty() + && ( !m_ui->targetDependency->validator() + || m_ui->targetDependency->validator()->validate( tmp, pos ) == QValidator::Acceptable ) ); +} + +void DependenciesWidget::checkActions( const QItemSelection& selected, const QItemSelection& unselected ) +{ + Q_UNUSED( unselected ); + if( !selected.indexes().isEmpty() ) + { + Q_ASSERT( selected.indexes().count() == 1 ); + QModelIndex idx = selected.indexes().at( 0 ); + m_ui->moveDepUp->setEnabled( idx.row() > 0 ); + m_ui->moveDepDown->setEnabled( idx.row() < m_ui->dependencies->count() - 1 ); + m_ui->removeDependency->setEnabled( true ); + } else + { + m_ui->removeDependency->setEnabled( false ); + m_ui->moveDepUp->setEnabled( false ); + m_ui->moveDepDown->setEnabled( false ); + } +} + +void DependenciesWidget::moveDependencyDown() +{ + QList list = m_ui->dependencies->selectedItems(); + if( !list.isEmpty() ) + { + Q_ASSERT( list.count() == 1 ); + QListWidgetItem* item = list.at( 0 ); + int row = m_ui->dependencies->row( item ); + m_ui->dependencies->takeItem( row ); + m_ui->dependencies->insertItem( row+1, item ); + m_ui->dependencies->selectionModel()->select( m_ui->dependencies->model()->index( row+1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); + } +} + +void DependenciesWidget::moveDependencyUp() +{ + + QList list = m_ui->dependencies->selectedItems(); + if( !list.isEmpty() ) + { + Q_ASSERT( list.count() == 1 ); + QListWidgetItem* item = list.at( 0 ); + int row = m_ui->dependencies->row( item ); + m_ui->dependencies->takeItem( row ); + m_ui->dependencies->insertItem( row-1, item ); + m_ui->dependencies->selectionModel()->select( m_ui->dependencies->model()->index( row-1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); + } +} + +void DependenciesWidget::addDep() +{ + QIcon icon; + KDevelop::ProjectBaseItem* pitem = m_ui->targetDependency->currentItem(); + if(pitem) + icon = QIcon::fromTheme(pitem->iconName()); + + QListWidgetItem* item = new QListWidgetItem(icon, m_ui->targetDependency->text(), m_ui->dependencies); + item->setData( Qt::UserRole, m_ui->targetDependency->itemPath() ); + m_ui->targetDependency->clear(); + m_ui->addDependency->setEnabled( false ); + m_ui->dependencies->selectionModel()->clearSelection(); + item->setSelected(true); +// dependencies->selectionModel()->select( dependencies->model()->index( dependencies->model()->rowCount() - 1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); +} + +void DependenciesWidget::selectItemDialog() +{ + if(m_ui->targetDependency->selectItemDialog()) { + addDep(); + } +} + +void DependenciesWidget::removeDep() +{ + QList list = m_ui->dependencies->selectedItems(); + if( !list.isEmpty() ) + { + Q_ASSERT( list.count() == 1 ); + int row = m_ui->dependencies->row( list.at(0) ); + delete m_ui->dependencies->takeItem( row ); + + m_ui->dependencies->selectionModel()->select( m_ui->dependencies->model()->index( row - 1, 0, QModelIndex() ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::SelectCurrent ); + } +} + +void DependenciesWidget::setDependencies(const QVariantList &deps) +{ + foreach( const QVariant& dep, deps ) { + QStringList deplist = dep.toStringList(); + KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel(); + KDevelop::ProjectBaseItem* pitem=itemForPath(deplist, model); + QIcon icon; + if(pitem) + icon=QIcon::fromTheme(pitem->iconName()); + + QListWidgetItem* item = new QListWidgetItem(icon, KDevelop::joinWithEscaping( deplist, '/', '\\' ), m_ui->dependencies ); + item->setData( Qt::UserRole, dep ); + } +} + +QVariantList DependenciesWidget::dependencies() const +{ + QVariantList deps; + for( int i = 0; i < m_ui->dependencies->count(); i++ ) + { + deps << m_ui->dependencies->item( i )->data( Qt::UserRole ); + } + return deps; +} diff --git a/project/widgets/dependencieswidget.ui b/project/widgets/dependencieswidget.ui new file mode 100644 --- /dev/null +++ b/project/widgets/dependencieswidget.ui @@ -0,0 +1,153 @@ + + + DependenciesWidget + + + + 0 + 0 + 400 + 300 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Enter a dependency to add to the list + + + Enter a dependency to add to the list + + + true + + + + + + + + + + + + + + false + + + Adds the listed target to the dependency list. + + + + + + + + + + + + + List of indirect dependent targets. + + + This list should contain targets that the application does not directly depend on, but for which an action needs to be taken before running the application. + + + true + + + true + + + + + + + false + + + Removes the selected dependencies from the list. + + + + + + + + + + + + + false + + + Moves the selected dependency up in the list. + + + + + + + + + + + + + false + + + Moves the selected dependency down in the list. + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 151 + + + + + + + + + ProjectItemLineEdit + QLineEdit +
project/projectitemlineedit.h
+
+
+ + +
diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -18,6 +18,7 @@ shellextension.cpp core.cpp uicontroller.cpp + colorschemechooser.cpp projectcontroller.cpp project.cpp partcontroller.cpp @@ -82,6 +83,12 @@ ) +if(APPLE) + set(KDevPlatformShell_LIB_SRCS ${KDevPlatformShell_LIB_SRCS} + macdockprogressview.mm + ) +endif() + kconfig_add_kcfg_files(KDevPlatformShell_LIB_SRCS settings/uiconfig.kcfgc settings/projectconfig.kcfgc @@ -118,6 +125,7 @@ Qt5::QuickWidgets KF5::GuiAddons + KF5::ConfigWidgets KF5::IconThemes KF5::KIOFileWidgets KF5::KIOWidgets @@ -140,13 +148,17 @@ KDev::Util KDev::Documentation ) +if(APPLE) + target_link_libraries(KDevPlatformShell PRIVATE "-framework AppKit") +endif() install(FILES mainwindow.h plugincontroller.h shellextension.h core.h uicontroller.h + colorschemechooser.h projectcontroller.h project.h partcontroller.h diff --git a/shell/colorschemechooser.h b/shell/colorschemechooser.h new file mode 100644 --- /dev/null +++ b/shell/colorschemechooser.h @@ -0,0 +1,60 @@ +/************************************************************************************* + * This file is part of KDevPlatform * + * Copyright 2016 Zhigalin Alexander * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) version 3, or any * + * later version accepted by the membership of KDE e.V. (or its * + * successor approved by the membership of KDE e.V.), which shall * + * act as a proxy defined in Section 6 of version 3 of the license. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library. If not, see . * + *************************************************************************************/ + +#ifndef COLORSCHEMECHOOSER_H +#define COLORSCHEMECHOOSER_H + +#include +#include +#include +#include + +#include + +#include "mainwindow.h" + +class KActionCollection; + +namespace KDevelop +{ +/** + * Provides a menu that will offer to change the color scheme + * + * Furthermore, it will save the selection in the user configuration. + */ +class ColorSchemeChooser : public QAction +{ + public: + ColorSchemeChooser(QObject* parent); + + QString currentSchemeName() const; + private Q_SLOTS: + void slotSchemeChanged(QAction* triggeredAction); + + private: + QString loadCurrentScheme() const; + void saveCurrentScheme(const QString &name); + QString currentDesktopDefaultScheme() const; +}; + +} // namespace KDevelop + +#endif // COLORSCHEMECHOOSER_H diff --git a/shell/colorschemechooser.cpp b/shell/colorschemechooser.cpp new file mode 100644 --- /dev/null +++ b/shell/colorschemechooser.cpp @@ -0,0 +1,106 @@ +/************************************************************************************* + * This file is part of KDevPlatform * + * Copyright 2016 Zhigalin Alexander * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) version 3, or any * + * later version accepted by the membership of KDE e.V. (or its * + * successor approved by the membership of KDE e.V.), which shall * + * act as a proxy defined in Section 6 of version 3 of the license. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library. If not, see . * + *************************************************************************************/ + +#include "colorschemechooser.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "mainwindow.h" +#include "core.h" +#include "debug.h" + +namespace KDevelop +{ + +ColorSchemeChooser::ColorSchemeChooser(QObject* parent) + : QAction(parent) +{ + auto manager = new KColorSchemeManager(parent); + + const auto scheme(currentSchemeName()); + qCDebug(SHELL) << "Color scheme : " << scheme; + + auto selectionMenu = manager->createSchemeSelectionMenu(scheme, this); + + connect(selectionMenu->menu(), &QMenu::triggered, + this, &ColorSchemeChooser::slotSchemeChanged); + + manager->activateScheme(manager->indexForScheme(scheme)); + + setMenu(selectionMenu->menu()); + menu()->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-color"))); + menu()->setTitle(i18n("&Color Theme")); +} + +QString ColorSchemeChooser::loadCurrentScheme() const +{ + KSharedConfigPtr config = KSharedConfig::openConfig(); + KConfigGroup cg(config, "UiSettings"); + return cg.readEntry("ColorScheme", currentDesktopDefaultScheme()); +} + +void ColorSchemeChooser::saveCurrentScheme(const QString &name) +{ + KSharedConfigPtr config = KSharedConfig::openConfig(); + KConfigGroup cg(config, "UiSettings"); + cg.writeEntry("ColorScheme", name); + cg.sync(); +} + +QString ColorSchemeChooser::currentDesktopDefaultScheme() const +{ + KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("kdeglobals")); + KConfigGroup group(config, "General"); + return group.readEntry("ColorScheme", QStringLiteral("Breeze")); +} + +QString ColorSchemeChooser::currentSchemeName() const +{ + if(!menu()) return loadCurrentScheme(); + + QAction* const action = menu()->activeAction(); + + if(action) return KLocalizedString::removeAcceleratorMarker(action->text()); + return currentDesktopDefaultScheme(); +} + +void ColorSchemeChooser::slotSchemeChanged(QAction* triggeredAction) +{ + saveCurrentScheme(KLocalizedString::removeAcceleratorMarker(triggeredAction->text())); +} + +} // namespace KDevelop diff --git a/shell/documentcontroller.cpp b/shell/documentcontroller.cpp --- a/shell/documentcontroller.cpp +++ b/shell/documentcontroller.cpp @@ -408,32 +408,30 @@ Sublime::View* buddyView = 0; bool placeAfterBuddy = true; - if(Core::self()->uiControllerInternal()->arrangeBuddies()) { + if(Core::self()->uiControllerInternal()->arrangeBuddies() && !buddy && doc->mimeType().isValid()) { // If buddy is not set, look for a (usually) plugin which handles this URL's mimetype // and use its IBuddyDocumentFinder, if available, to find a buddy document - if(!buddy && doc->mimeType().isValid()) { - QString mime = doc->mimeType().name(); - IBuddyDocumentFinder* buddyFinder = IBuddyDocumentFinder::finderForMimeType(mime); - if(buddyFinder) { - buddy = findBuddyDocument(url, buddyFinder); - if(buddy) { - placeAfterBuddy = buddyFinder->buddyOrder(buddy->url(), doc->url()); - } + QString mime = doc->mimeType().name(); + IBuddyDocumentFinder* buddyFinder = IBuddyDocumentFinder::finderForMimeType(mime); + if(buddyFinder) { + buddy = findBuddyDocument(url, buddyFinder); + if(buddy) { + placeAfterBuddy = buddyFinder->buddyOrder(buddy->url(), doc->url()); } } + } - if(buddy) { - Sublime::Document* sublimeDocBuddy = dynamic_cast(buddy); - - if(sublimeDocBuddy) { - Sublime::AreaIndex *pActiveViewIndex = area->indexOf(uiController->activeSublimeWindow()->activeView()); - if(pActiveViewIndex) { - // try to find existing View of buddy document in current active view's tab - foreach (Sublime::View *pView, pActiveViewIndex->views()) { - if(sublimeDocBuddy->views().contains(pView)) { - buddyView = pView; - break; - } + if(buddy) { + Sublime::Document* sublimeDocBuddy = dynamic_cast(buddy); + + if(sublimeDocBuddy) { + Sublime::AreaIndex *pActiveViewIndex = area->indexOf(uiController->activeSublimeWindow()->activeView()); + if(pActiveViewIndex) { + // try to find existing View of buddy document in current active view's tab + foreach (Sublime::View *pView, pActiveViewIndex->views()) { + if(sublimeDocBuddy->views().contains(pView)) { + buddyView = pView; + break; } } } diff --git a/shell/launchconfiguration.cpp b/shell/launchconfiguration.cpp --- a/shell/launchconfiguration.cpp +++ b/shell/launchconfiguration.cpp @@ -127,7 +127,18 @@ } } - //No launcher configured, lets just try with the first one in the list and hope it works + // No launcher configured, if it's debug mode, prefer GDB if available. + if( mode == "debug" ) + { + foreach( ILauncher* l, type()->launchers() ) + { + if( l->supportedModes().contains( mode ) && l->id() == "gdb" ) + { + return l->id(); + } + } + } + // Otherwise, lets just try with the first one in the list and hope it works foreach( ILauncher* l, type()->launchers() ) { if( l->supportedModes().contains( mode ) ) diff --git a/shell/macdockprogressview.h b/shell/macdockprogressview.h new file mode 100644 --- /dev/null +++ b/shell/macdockprogressview.h @@ -0,0 +1,40 @@ +/* + * Copyright 2016 René J.V. Bertin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + */ + +#ifndef MACDOCKPROGRESSVIEW_H + +namespace KDevelop +{ + +class MacDockProgressView +{ +public: + static void setRange(int min, int max); + + static void setProgress(int value); + + static void setProgressVisible(bool visible); +}; + +} + +#define MACDOCKPROGRESSVIEW_H +#endif diff --git a/shell/macdockprogressview.mm b/shell/macdockprogressview.mm new file mode 100644 --- /dev/null +++ b/shell/macdockprogressview.mm @@ -0,0 +1,211 @@ +/* + * Copyright 2016 René J.V. Bertin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + */ + +#include "macdockprogressview.h" +#include +#include + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#import +#import +#import +#import +#import +#import +#import + +using namespace KDevelop; + +@interface MacDockProgressViewPrivate : NSView { + int min; + int max; + int value; + NSColor *bgColour, *fgColour; + NSTimer *indeterminateTimer; +} + ++ (MacDockProgressViewPrivate *)sharedProgressView; + +- (id)init; +- (void)dealloc; +- (void)removeTimer; +- (void)rangeStartsAt:(int)v1 endsAt:(int)v2; +- (void)setValue:(int)v; +- (void)updateBadge; + +@end + +static MacDockProgressViewPrivate *sharedProgressView = nil; + +@implementation MacDockProgressViewPrivate + ++ (MacDockProgressViewPrivate *)sharedProgressView +{ + if (sharedProgressView == nil) { + sharedProgressView = [[MacDockProgressViewPrivate alloc] init]; + [sharedProgressView rangeStartsAt:0 endsAt:100]; + } + return sharedProgressView; +} + +- (id)init +{ + self = [super init]; + bgColour = fgColour = nil; + indeterminateTimer = nil; + min = max = value = 0; + return self; +} + +- (void)dealloc +{ + [self removeTimer]; + [bgColour release]; + [fgColour release]; + [super dealloc]; +} + +- (void)removeTimer +{ + if (indeterminateTimer != nil) { + [indeterminateTimer invalidate]; + [indeterminateTimer release]; + indeterminateTimer = nil; + } +} + +- (void)rangeStartsAt:(int)v1 endsAt:(int)v2 +{ + min = v1; + max = v2; + // (re)set the colours to the standard progressbar colour scheme + [bgColour release]; + [fgColour release]; + bgColour = [[NSColor blackColor] retain]; + fgColour = [[NSColor lightGrayColor] retain]; + if (v1 == v2 ) { + if (indeterminateTimer == nil) { + indeterminateTimer = [[NSTimer timerWithTimeInterval:1 + target:self + selector:@selector(updateBadge) + userInfo:nil + repeats:YES] retain]; + if (indeterminateTimer) { + [[NSRunLoop currentRunLoop] addTimer:indeterminateTimer forMode:NSDefaultRunLoopMode]; + } + } + } else { + [self removeTimer]; + } + [self updateBadge]; +} + +- (void)setValue:(int)v +{ + value = v; + [self updateBadge]; +} + +- (void)updateBadge +{ + [[NSApp dockTile] display]; +} + +- (void)drawRect:(NSRect)rect +{ + Q_UNUSED(rect) + NSRect boundary = [self bounds]; + [[NSApp applicationIconImage] drawInRect:boundary + fromRect:NSZeroRect + operation:NSCompositeCopy + fraction:1.0]; + NSRect progressBoundary = boundary; + progressBoundary.size.height *= 0.1; + progressBoundary.size.width *= 0.8; + progressBoundary.origin.x = (NSWidth(boundary) - NSWidth(progressBoundary)) / 2.0; + progressBoundary.origin.y = NSHeight(boundary) * 0.1; + + double percent = 0.50; + if (min != max) { + double range = max - min; + percent = (value - min) / range; + if (percent > 1) { + percent = 1; + } else if (percent < 0) { + percent = 0; + } + } else { + // poor man's indefinite busy progressbar obtained by swapping + // fg and bg colours with the bar at the 50% point. + std::swap(fgColour, bgColour); + } + + NSRect currentProgress = progressBoundary; + currentProgress.size.width *= percent; + [bgColour setFill]; + [NSBezierPath fillRect:progressBoundary]; + [fgColour setFill]; + [NSBezierPath fillRect:currentProgress]; + [bgColour setStroke]; + [NSBezierPath strokeRect:progressBoundary]; +} + +@end + +void MacDockProgressView::setRange(int min, int max) +{ + [[MacDockProgressViewPrivate sharedProgressView] rangeStartsAt:min endsAt:max]; +} + +void MacDockProgressView::setProgress(int value) +{ + [[MacDockProgressViewPrivate sharedProgressView] setValue:value]; +} + +void MacDockProgressView::setProgressVisible(bool visible) +{ + if (visible) { + [[NSApp dockTile] setContentView:[MacDockProgressViewPrivate sharedProgressView]]; + } else { + [[NSApp dockTile] setContentView:nil]; + } + [[NSApp dockTile] display]; +} + +#else + +void MacDockProgressView::setRange(int min, int max) +{ + Q_UNUSED(min) + Q_UNUSED(max) +} + +void MacDockProgressView::setProgress(int value) +{ + Q_UNUSED(value) +} + +void MacDockProgressView::setProgressVisible(bool visible) +{ + Q_UNUSED(visible) +} + +#endif diff --git a/shell/mainwindow_p.cpp b/shell/mainwindow_p.cpp --- a/shell/mainwindow_p.cpp +++ b/shell/mainwindow_p.cpp @@ -53,6 +53,7 @@ #include "sessioncontroller.h" #include "debug.h" #include "ktexteditorpluginintegration.h" +#include "colorschemechooser.h" #include #include @@ -318,6 +319,9 @@ connect( action, &QAction::triggered, this, &MainWindowPrivate::viewAddNewToolView ); action->setToolTip( i18nc( "@info:tooltip", "Add tool view" ) ); action->setWhatsThis( i18nc( "@info:whatsthis", "Adds a new tool view to this window." ) ); + + //Load themes + actionCollection()->addAction(QStringLiteral("coloscheme_menu"), new ColorSchemeChooser(actionCollection())); } void MainWindowPrivate::toggleArea(bool b) diff --git a/shell/problemstore.cpp b/shell/problemstore.cpp --- a/shell/problemstore.cpp +++ b/shell/problemstore.cpp @@ -191,7 +191,7 @@ int ProblemStore::scope() const { - Q_ASSERT(d->m_documents != nullptr); + Q_ASSERT(d->m_documents); return d->m_documents->getScope(); } diff --git a/shell/progresswidget/statusbarprogresswidget.cpp b/shell/progresswidget/statusbarprogresswidget.cpp --- a/shell/progresswidget/statusbarprogresswidget.cpp +++ b/shell/progresswidget/statusbarprogresswidget.cpp @@ -37,6 +37,9 @@ #include "statusbarprogresswidget.h" #include "progressdialog.h" #include "progressmanager.h" +#ifdef Q_OS_OSX +#include "../macdockprogressview.h" +#endif #include @@ -180,6 +183,10 @@ m_pProgressBar->setMaximum( 100 ); m_pProgressBar->setValue( mCurrentItem->progress() ); m_pProgressBar->setTextVisible( true ); +#ifdef Q_OS_OSX + MacDockProgressView::setRange( 0, 100 ); + MacDockProgressView::setProgress( mCurrentItem->progress() ); +#endif } void StatusbarProgressWidget::slotShowItemDelayed() @@ -190,6 +197,10 @@ } else if ( !noItems ) { // N items m_pProgressBar->setMaximum( 0 ); m_pProgressBar->setTextVisible( false ); +#ifdef Q_OS_OSX + MacDockProgressView::setRange( 0, 0 ); + MacDockProgressView::setProgress( 0 ); +#endif } if ( !noItems && mode == None ) { @@ -203,6 +214,9 @@ Q_ASSERT( item == mCurrentItem); // the only one we should be connected to Q_UNUSED( item ); m_pProgressBar->setValue( value ); +#ifdef Q_OS_OSX + MacDockProgressView::setProgress( value ); +#endif } void StatusbarProgressWidget::setMode() { @@ -214,14 +228,20 @@ // show the empty label in order to make the status bar look better stack->show(); stack->setCurrentWidget( m_pLabel ); +#ifdef Q_OS_OSX + MacDockProgressView::setProgressVisible( false ); +#endif break; case Progress: stack->show(); stack->setCurrentWidget( m_pProgressBar ); if ( m_bShowButton ) { m_pButton->show(); } +#ifdef Q_OS_OSX + MacDockProgressView::setProgressVisible( true ); +#endif break; } } diff --git a/shell/tests/kdevnonguiinterfaceplugin.json b/shell/tests/kdevnonguiinterfaceplugin.json --- a/shell/tests/kdevnonguiinterfaceplugin.json +++ b/shell/tests/kdevnonguiinterfaceplugin.json @@ -39,9 +39,7 @@ "Description[ca@valencia]": "Este connector és exclusivament per a unitats de proves", "Description[ca]": "Aquest connector és exclusivament per a unitats de proves", "Description[de]": "Die ist eine Modul nur für Unit-Tests", - "Description[en_GB]": "This plugin is purely for unit-test", "Description[es]": "Este complemento es exclusivamente para pruebas unitarias", - "Description[et]": "See plugin on ainult ühiktesti jaoks", "Description[fi]": "Tämä liitännäinen on puhtaasti yksikkötestausta varten", "Description[gl]": "Este complemento é soamente para probas unitarias.", "Description[nl]": "Deze plugin is alleen voor eenheid-testen", @@ -51,32 +49,17 @@ "Description[sk]": "Tento plugin je čisto na unit testy", "Description[sl]": "Ta vstavek je samo za preizkušanje enot", "Description[sv]": "Insticksprogrammet är enbart avsett för enhetstest", + "Description[tr]": "Bu eklenti tamamen birim-testleri içindir", "Description[uk]": "Цей додаток призначено лише для тестування модулів", "Description[x-test]": "xxThis plugin is purely for unit-testxx", "Description[zh_CN]": "此插件只用于 unit 测试", "Id": "kdevnonguiinterface", "License": "LGPL", "Name": "KDevNonGuiInterface", - "Name[ca@valencia]": "KDevNonGuiInterface", - "Name[ca]": "KDevNonGuiInterface", - "Name[de]": "KDevNonGuiInterface", - "Name[en_GB]": "KDevNonGuiInterface", - "Name[es]": "KDevNonGuiInterface", - "Name[et]": "KDevNonGuiInterface", - "Name[fi]": "KDevNonGuiInterface", - "Name[gl]": "KDevNonGuiInterface", - "Name[it]": "KDevNonGuiInterface", - "Name[nb]": "KDevNonGuiInterface", - "Name[nl]": "KDevNonGuiInterface", - "Name[pl]": "KDevNonGuiInterface", - "Name[pt]": "KDevNonGuiInterface", - "Name[pt_BR]": "KDevNonGuiInterface", - "Name[sk]": "KDevNonGuiInterface", - "Name[sl]": "KDevNonGuiInterface", + "Name[bs]": "KDevNonGUI sučelje", + "Name[nds]": "KDevKeenBöversiet", "Name[sv]": "KDevelop icke grafiskt användargränssnitt", - "Name[uk]": "KDevNonGuiInterface", "Name[x-test]": "xxKDevNonGuiInterfacexx", - "Name[zh_CN]": "KDevNonGuiInterface", "ServiceTypes": [ "KDevelop/Plugin" ] diff --git a/shell/tests/test_filteredproblemstore.cpp b/shell/tests/test_filteredproblemstore.cpp --- a/shell/tests/test_filteredproblemstore.cpp +++ b/shell/tests/test_filteredproblemstore.cpp @@ -156,20 +156,20 @@ bool checkDiagnodes(const ProblemStoreNode *node, const IProblem::Ptr &reference) { const ProblemNode *problemNode = dynamic_cast(node); - MYVERIFY(problemNode != nullptr); + MYVERIFY(problemNode); MYCOMPARE(problemNode->problem()->description(), reference->description()); MYCOMPARE(problemNode->problem()->finalLocation().document.str(), reference->finalLocation().document.str()); MYCOMPARE(problemNode->count(), 1); const IProblem::Ptr diag = reference->diagnostics().at(0); const ProblemNode *diagNode = dynamic_cast(problemNode->child(0)); - MYVERIFY(diagNode != nullptr); + MYVERIFY(diagNode); MYCOMPARE(diagNode->problem()->description(), diag->description()); MYCOMPARE(diagNode->count(), 1); const IProblem::Ptr diagdiag = diag->diagnostics().at(0); const ProblemNode *diagdiagNode = dynamic_cast(diagNode->child(0)); - MYVERIFY(diagdiagNode != nullptr); + MYVERIFY(diagdiagNode); MYCOMPARE(diagdiagNode->problem()->description(), diagdiag->description()); MYCOMPARE(diagdiagNode->count(), 0); @@ -188,7 +188,7 @@ } for (int i = 0; i < c; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i]->description()); } @@ -202,7 +202,7 @@ QCOMPARE(m_problems.count(), m_store->count()); for (int i = 0; i < c; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i]->description()); } @@ -213,16 +213,16 @@ QCOMPARE(m_store->count(), ErrorFilterProblemCount); for (int i = 0; i < ErrorFilterProblemCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(0)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i]->description()); } // Warning filter m_store->setSeverity(IProblem::Warning); QCOMPARE(m_store->count(), WarningFilterProblemCount); for (int i = 0; i < WarningFilterProblemCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i]->description()); } @@ -232,7 +232,7 @@ QCOMPARE(m_store->count(), HintFilterProblemCount); for (int i = 0; i < HintFilterProblemCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i]->description()); } @@ -243,16 +243,16 @@ QCOMPARE(m_store->count(), ErrorCount); for (int i = 0; i < ErrorCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i]->description()); } // Warning filter m_store->setSeverities(IProblem::Warning); QCOMPARE(m_store->count(), WarningCount); for (int i = 0; i < WarningCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i+ErrorCount]->description()); } @@ -262,7 +262,7 @@ QCOMPARE(m_store->count(), HintCount); for (int i = 0; i < HintCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i+ErrorCount+WarningCount]->description()); } @@ -272,13 +272,13 @@ QCOMPARE(m_store->count(), HintCount + ErrorCount); for (int i = 0; i < ErrorCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i]->description()); } for (int i = ErrorCount; i < ErrorCount+HintCount; i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->problem()->description(), m_problems[i+WarningCount]->description()); } @@ -297,7 +297,7 @@ { const LabelNode *parent = dynamic_cast(node); - MYVERIFY(parent != nullptr); + MYVERIFY(parent); MYCOMPARE(parent->label(), label); return true; @@ -307,7 +307,7 @@ { const ProblemNode *n = dynamic_cast(node); - MYVERIFY(n != nullptr); + MYVERIFY(n); MYCOMPARE(n->problem()->description(), descr); return true; @@ -448,7 +448,7 @@ m_store->addProblem(m_diagnosticTestProblem); QCOMPARE(m_store->count(), 1); const LabelNode *node = dynamic_cast(m_store->findNode(0)); - QVERIFY(node != nullptr); + QVERIFY(node); QCOMPARE(node->label(), m_diagnosticTestProblem->finalLocation().document.str()); QVERIFY(checkDiagnodes(node->child(0), m_diagnosticTestProblem)); } @@ -573,9 +573,9 @@ const ProblemStoreNode *warningNode = m_store->findNode(1); const ProblemStoreNode *hintNode = m_store->findNode(2); - MYVERIFY(errorNode != nullptr); - MYVERIFY(warningNode != nullptr); - MYVERIFY(hintNode != nullptr); + MYVERIFY(errorNode); + MYVERIFY(warningNode); + MYVERIFY(hintNode); MYCOMPARE(errorNode->count(), error); MYCOMPARE(warningNode->count(), warning); diff --git a/shell/tests/test_problemmodelset.cpp b/shell/tests/test_problemmodelset.cpp --- a/shell/tests/test_problemmodelset.cpp +++ b/shell/tests/test_problemmodelset.cpp @@ -107,7 +107,7 @@ for (int i = 0; i < testModelCount; i++) { model = m_set->findModel(m_testData[i].name); - QVERIFY(model != nullptr); + QVERIFY(model); QVERIFY(model == m_testData[i].model); } diff --git a/shell/tests/test_problemstore.cpp b/shell/tests/test_problemstore.cpp --- a/shell/tests/test_problemstore.cpp +++ b/shell/tests/test_problemstore.cpp @@ -101,8 +101,8 @@ for (int i = 0; i < m_problems.count(); i++) { const ProblemNode *node = dynamic_cast(m_store->findNode(i)); - QVERIFY(node != nullptr); - QVERIFY(node->problem().data() != nullptr); + QVERIFY(node); + QVERIFY(node->problem().data()); QCOMPARE(node->problem().data()->description(), m_problems[i]->description()); } } diff --git a/shell/tests/test_problemstorenode.cpp b/shell/tests/test_problemstorenode.cpp --- a/shell/tests/test_problemstorenode.cpp +++ b/shell/tests/test_problemstorenode.cpp @@ -81,7 +81,7 @@ for (int i = 0; i < c; i++) { ProblemStoreNode *node = m_root->child(i); - QVERIFY(node != nullptr); + QVERIFY(node); QVERIFY(node == nodes[i]); QCOMPARE(node->index(), i); } diff --git a/sublime/area.h b/sublime/area.h --- a/sublime/area.h +++ b/sublime/area.h @@ -166,9 +166,6 @@ void setDesiredToolViews( const QMap& desiredToolViews); - void setThickness(Sublime::Position pos, int thickness); - int thickness(Sublime::Position pos) const; - void save(KConfigGroup& group) const; void load(const KConfigGroup& group); diff --git a/sublime/area.cpp b/sublime/area.cpp --- a/sublime/area.cpp +++ b/sublime/area.cpp @@ -92,7 +92,6 @@ QMap toolViewPositions; QMap desiredToolViews; QMap shownToolViews; - QMap thickness; QString iconName; QString workingSet; QPointer activeView; @@ -312,10 +311,6 @@ group.writeEntry("view on right", shownToolViews(Sublime::Right)); group.writeEntry("view on top", shownToolViews(Sublime::Top)); group.writeEntry("view on bottom", shownToolViews(Sublime::Bottom)); - group.writeEntry("thickness left", thickness(Sublime::Left)); - group.writeEntry("thickness right", thickness(Sublime::Right)); - group.writeEntry("thickness bottom", thickness(Sublime::Bottom)); - group.writeEntry("thickness top", thickness(Sublime::Top)); group.writeEntry("working set", d->workingSet); } @@ -346,10 +341,6 @@ setShownToolViews(Sublime::Top, group.readEntry("view on top", QStringList())); setShownToolViews(Sublime::Bottom, group.readEntry("view on bottom", QStringList())); - setThickness(Sublime::Left, group.readEntry("thickness left", -1)); - setThickness(Sublime::Right, group.readEntry("thickness right", -1)); - setThickness(Sublime::Bottom, group.readEntry("thickness bottom", -1)); - setThickness(Sublime::Top, group.readEntry("thickness top", -1)); setWorkingSet(group.readEntry("working set", d->workingSet)); } @@ -382,18 +373,6 @@ d->desiredToolViews = desiredToolViews; } -void Area::setThickness(Sublime::Position pos, int thickness) -{ - d->thickness[pos] = thickness; -} - -int Area::thickness(Sublime::Position pos) const -{ - if (!d->thickness.contains(pos)) - return -1; - return (d->thickness)[pos]; -} - QString Area::iconName() const { return d->iconName; diff --git a/sublime/container.cpp b/sublime/container.cpp --- a/sublime/container.cpp +++ b/sublime/container.cpp @@ -155,8 +155,27 @@ std::sort(views.begin(), views.end(), sortViews); - foreach(View* view, views) { - QAction* action = documentListMenu->addAction(view->document()->title()); + for (int i = 0; i < views.size(); ++i) { + View *view = views.at(i); + QString visibleEntryTitle; + // if filename is not unique, prepend containing directory + if ((i < views.size() - 1 && view->document()->title() == views.at(i + 1)->document()->title()) + || (i > 0 && view->document()->title() == views.at(i - 1)->document()->title()) + ) { + auto urlDoc = qobject_cast(view->document()); + if (!urlDoc) { + visibleEntryTitle = view->document()->title(); + } + else { + auto url = urlDoc->url().toString(); + int secondOffset = url.lastIndexOf('/'); + secondOffset = url.lastIndexOf('/', secondOffset - 1); + visibleEntryTitle = url.right(url.length() - url.lastIndexOf('/', secondOffset) - 1); + } + } else { + visibleEntryTitle = view->document()->title(); + } + QAction* action = documentListMenu->addAction(visibleEntryTitle); action->setData(QVariant::fromValue(view)); documentListActionForView[view] = action; action->setIcon(view->document()->icon()); @@ -400,13 +419,11 @@ if (tabIndex != -1) { d->tabBar->setTabText(tabIndex, doc->title()); } - - // Update document list popup title - Q_ASSERT(d->documentListActionForView.contains(view)); - d->documentListActionForView[view]->setText(doc->title()); break; } } + // Update document list popup title + d->updateDocumentListPopupMenu(); } int Container::count() const diff --git a/sublime/idealcontroller.h b/sublime/idealcontroller.h --- a/sublime/idealcontroller.h +++ b/sublime/idealcontroller.h @@ -78,8 +78,6 @@ enum Direction { NextDock, PrevDock }; void goPrevNextDock(IdealController::Direction direction); - void setWidthForArea(Qt::DockWidgetArea, int); - IdealButtonBarWidget *leftBarWidget; IdealButtonBarWidget *rightBarWidget; IdealButtonBarWidget *bottomBarWidget; @@ -120,7 +118,6 @@ /** Map from IdealDockWidget to an action that shows/hides that IdealDockWidget. */ QMap m_dockwidget_to_action; - QMap m_widthsForAreas; KActionMenu* m_docks; diff --git a/sublime/idealcontroller.cpp b/sublime/idealcontroller.cpp --- a/sublime/idealcontroller.cpp +++ b/sublime/idealcontroller.cpp @@ -500,11 +500,6 @@ m_mainWindow->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); } -void IdealController::setWidthForArea(Qt::DockWidgetArea area, int width) -{ - m_widthsForAreas[area] = width; -} - void IdealController::emitWidgetResized(Qt::DockWidgetArea dockArea, int thickness) { emit widgetResized(dockArea, thickness); diff --git a/sublime/mainwindow_p.cpp b/sublime/mainwindow_p.cpp --- a/sublime/mainwindow_p.cpp +++ b/sublime/mainwindow_p.cpp @@ -422,10 +422,6 @@ m_leftTabbarCornerWidget->setParent(0); } - idealController->setWidthForArea(Qt::LeftDockWidgetArea, area->thickness(Sublime::Left)); - idealController->setWidthForArea(Qt::BottomDockWidgetArea, area->thickness(Sublime::Bottom)); - idealController->setWidthForArea(Qt::RightDockWidgetArea, area->thickness(Sublime::Right)); - IdealToolViewCreator toolViewCreator(this); area->walkToolViews(toolViewCreator, Sublime::AllPositions); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,10 @@ testlanguagecontroller.cpp testhelpers.cpp testplugincontroller.cpp + testdebugsession.cpp + testvariablecontroller.cpp + testbreakpointcontroller.cpp + testframestackmodel.cpp modeltest.cpp json/delayedoutput.cpp @@ -19,6 +23,7 @@ KDev::Shell KDev::Language KDev::Project + KDev::Debugger ) target_link_libraries(KDevPlatformTests LINK_PRIVATE Qt5::Core @@ -35,6 +40,10 @@ testlanguagecontroller.h testhelpers.h testplugincontroller.h + testdebugsession.h + testvariablecontroller.h + testbreakpointcontroller.h + testframestackmodel.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/tests/ COMPONENT Devel ) diff --git a/tests/testbreakpointcontroller.h b/tests/testbreakpointcontroller.h new file mode 100644 --- /dev/null +++ b/tests/testbreakpointcontroller.h @@ -0,0 +1,48 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#ifndef TESTBREAKPOINTCONTROLLER_H +#define TESTBREAKPOINTCONTROLLER_H + +#include "testsexport.h" + +#include + +namespace KDevelop { + +/** + * Dummy BreakpointController + */ +class KDEVPLATFORMTESTS_EXPORT TestBreakpointController : public IBreakpointController +{ + Q_OBJECT + +public: + explicit TestBreakpointController(IDebugSession *parent); + +protected: + void sendMaybe(Breakpoint *breakpoint) override; +}; + +} // end of namespace KDevelop +#endif // TESTBREAKPOINTCONTROLLER_H diff --git a/tests/testbreakpointcontroller.cpp b/tests/testbreakpointcontroller.cpp new file mode 100644 --- /dev/null +++ b/tests/testbreakpointcontroller.cpp @@ -0,0 +1,37 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#include "testbreakpointcontroller.h" + +using namespace KDevelop; + +TestBreakpointController::TestBreakpointController(IDebugSession *parent) + : IBreakpointController(parent) +{ + +} + +void TestBreakpointController::sendMaybe(Breakpoint *breakpoint) +{ + Q_UNUSED(breakpoint); +} diff --git a/tests/testdebugsession.h b/tests/testdebugsession.h new file mode 100644 --- /dev/null +++ b/tests/testdebugsession.h @@ -0,0 +1,111 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#ifndef TESTDEBUGSESSION_H +#define TESTDEBUGSESSION_H + +#include "testsexport.h" + +#include + +#include + +using std::unique_ptr; + +namespace KDevelop { + +class IBreakpointController; +class IVariableController; +class IFrameStackModel; + +/** + * \class TestDebugSession testdebugsession.h + * + * This is an IDebugSession implementation that should be used only inside + * unit tests. + * + * The initial debug state is NotStartedState, one can use normal slots to + * change the state, for example calling runToCursor() changes to PausedState. + * See corresponding implementation for what state a specific slot changes to. + * + * This class also allows one to replace IBreakpointController, IVariableController, + * or IFrameStackModel implementation with custom implementation to make it possible + * to write tests more easily. + * + * The usage is as follows: + * \code + * AutoTestShell::init(); + * TestCore::initialize(Core::NoUi); + * TestDebugSession* session = new TestDebugSession(); + * //replace variable controller or similar + * session->setVariableController(new MyCustomVariableController(session)); + * ... //test code + * delete session; + * TestCore::shutdown(); + * \endcode + * + * @note It is important to set custom controllers right after the creation of the + * debug session, and not change them inside the test code, as required by + * IDebugSession that controllers do not change during the lifetime of a session + */ +class KDEVPLATFORMTESTS_EXPORT TestDebugSession : public IDebugSession +{ + Q_OBJECT + +public: + TestDebugSession(); + ~TestDebugSession() override; + + void setBreakpointController(IBreakpointController *breakpointController); + void setVariableController(IVariableController *variableController); + void setFrameStackModel(IFrameStackModel *frameStackModel); + + DebuggerState state() const override; + + bool restartAvaliable() const override; + IBreakpointController* breakpointController() const override; + IVariableController* variableController() const override; + IFrameStackModel* frameStackModel() const override; + +public Q_SLOTS: + void restartDebugger() override; + void stopDebugger() override; + void interruptDebugger() override; + void run() override; + void runToCursor() override; + void jumpToCursor() override; + void stepOver() override; + void stepIntoInstruction() override; + void stepInto() override; + void stepOverInstruction() override; + void stepOut() override; + +private: + IBreakpointController *m_breakpointController; + IVariableController *m_variableController; + IFrameStackModel *m_frameStackModel; + DebuggerState m_sessionState; +}; + +} // end of namespace KDevelop +#endif // TESTDEBUGSESSION_H diff --git a/tests/testdebugsession.cpp b/tests/testdebugsession.cpp new file mode 100644 --- /dev/null +++ b/tests/testdebugsession.cpp @@ -0,0 +1,155 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#include "testdebugsession.h" + +#include "testbreakpointcontroller.h" +#include "testvariablecontroller.h" +#include "testframestackmodel.h" + +using namespace KDevelop; + +TestDebugSession::TestDebugSession() + : m_breakpointController(nullptr) + , m_variableController(nullptr) + , m_frameStackModel(nullptr) + , m_sessionState(NotStartedState) +{ + setBreakpointController(nullptr); + setVariableController(nullptr); + setFrameStackModel(nullptr); +} + +TestDebugSession::~TestDebugSession() +{ + delete m_breakpointController; + delete m_variableController; + delete m_frameStackModel; +} + +void TestDebugSession::setBreakpointController(IBreakpointController *breakpointController) +{ + delete m_breakpointController; + m_breakpointController = breakpointController; + if (!m_breakpointController) { + m_breakpointController = new TestBreakpointController(this); + } +} + +void TestDebugSession::setVariableController(IVariableController *variableController) +{ + delete m_variableController; + m_variableController = variableController; + if (!m_variableController) { + m_variableController = new TestVariableController(this); + } +} + +void TestDebugSession::setFrameStackModel(IFrameStackModel *frameStackModel) +{ + delete m_frameStackModel; + m_frameStackModel = frameStackModel; + if (!m_frameStackModel) { + m_frameStackModel = new TestFrameStackModel(this); + } +} + +IDebugSession::DebuggerState TestDebugSession::state() const +{ + return m_sessionState; +} + +bool TestDebugSession::restartAvaliable() const +{ + return true; +} + +IBreakpointController* TestDebugSession::breakpointController() const +{ + return m_breakpointController; +} + +IVariableController* TestDebugSession::variableController() const +{ + return m_variableController; +} + +IFrameStackModel* TestDebugSession::frameStackModel() const +{ + return m_frameStackModel; +} + +void TestDebugSession::restartDebugger() +{ + m_sessionState = ActiveState; +} + +void TestDebugSession::stopDebugger() +{ + m_sessionState = StoppedState; +} + +void TestDebugSession::interruptDebugger() +{ + m_sessionState = StoppedState; +} + +void TestDebugSession::run() +{ + m_sessionState = ActiveState; +} + +void TestDebugSession::runToCursor() +{ + m_sessionState = PausedState; +} + +void TestDebugSession::jumpToCursor() +{ + m_sessionState = PausedState; +} + +void TestDebugSession::stepOver() +{ + m_sessionState = PausedState; +} + +void TestDebugSession::stepIntoInstruction() +{ + m_sessionState = PausedState; +} + +void TestDebugSession::stepInto() +{ + m_sessionState = PausedState; +} + +void TestDebugSession::stepOverInstruction() +{ + m_sessionState = PausedState; +} + +void TestDebugSession::stepOut() +{ + m_sessionState = PausedState; +} diff --git a/tests/testframestackmodel.h b/tests/testframestackmodel.h new file mode 100644 --- /dev/null +++ b/tests/testframestackmodel.h @@ -0,0 +1,51 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#ifndef TESTFRAMESTACKMODEL_H +#define TESTFRAMESTACKMODEL_H + +#include "testsexport.h" + +#include + +namespace KDevelop { + +/** + * Dummy frame stack model + */ +class KDEVPLATFORMTESTS_EXPORT TestFrameStackModel : public FrameStackModel +{ + Q_OBJECT + +public: + explicit TestFrameStackModel(IDebugSession *parent); + +protected: + void fetchThreads() override; + void fetchFrames(int threadNumber, int from, int to) override; + +private: +}; + +} // end of namespace KDevelop +#endif // TESTFRAMESTACKMODEL_H diff --git a/tests/testframestackmodel.cpp b/tests/testframestackmodel.cpp new file mode 100644 --- /dev/null +++ b/tests/testframestackmodel.cpp @@ -0,0 +1,43 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#include "testframestackmodel.h" + +using namespace KDevelop; + +TestFrameStackModel::TestFrameStackModel(IDebugSession *parent) + : FrameStackModel(parent) +{ +} + +void TestFrameStackModel::fetchThreads() +{ + +} + +void TestFrameStackModel::fetchFrames(int threadNumber, int from, int to) +{ + Q_UNUSED(threadNumber); + Q_UNUSED(from); + Q_UNUSED(to); +} diff --git a/tests/testvariablecontroller.h b/tests/testvariablecontroller.h new file mode 100644 --- /dev/null +++ b/tests/testvariablecontroller.h @@ -0,0 +1,66 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#ifndef TESTVARIABLECONTROLLER_H +#define TESTVARIABLECONTROLLER_H + +#include "testsexport.h" + +#include + +namespace KDevelop { + +/** + * Dummy VariableController that does nothing. + */ +class KDEVPLATFORMTESTS_EXPORT TestVariableController : public IVariableController +{ + Q_OBJECT + +public: + explicit TestVariableController(IDebugSession* parent); + + Variable* createVariable(TreeModel* model, TreeItem* parent, + const QString& expression, + const QString& display = {}) override; + + KTextEditor::Range expressionRangeUnderCursor(KTextEditor::Document* doc, + const KTextEditor::Cursor& cursor) override; + + void addWatch(Variable* variable) override; + void addWatchpoint(Variable* variable) override; + + /** + * Number of times update() has been called since creation. + */ + int updatedTimes() const; + +protected: + void update() override; + +private: + int m_updatedTimes; +}; + +} // end of namespace KDevelop +#endif // TESTVARIABLECONTROLLER_H diff --git a/tests/testvariablecontroller.cpp b/tests/testvariablecontroller.cpp new file mode 100644 --- /dev/null +++ b/tests/testvariablecontroller.cpp @@ -0,0 +1,77 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Aetf + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#include "testvariablecontroller.h" + +using namespace KDevelop; +using KTextEditor::Range; +using KTextEditor::Document; +using KTextEditor::Cursor; + +TestVariableController::TestVariableController(IDebugSession* parent) + : IVariableController(parent) + , m_updatedTimes(0) +{ + +} + +Variable* TestVariableController::createVariable(TreeModel* model, TreeItem* parent, + const QString& expression, + const QString& display) +{ + Q_UNUSED(model); + Q_UNUSED(parent); + Q_UNUSED(expression); + Q_UNUSED(display); + + return nullptr; +} + +Range TestVariableController::expressionRangeUnderCursor(Document* doc, + const Cursor& cursor) +{ + Q_UNUSED(doc); + Q_UNUSED(cursor); + + return {}; +} + +void TestVariableController::addWatch(Variable* variable) +{ + Q_UNUSED(variable); +} + +void TestVariableController::addWatchpoint(Variable* variable) +{ + Q_UNUSED(variable); +} + +void TestVariableController::update() +{ + ++m_updatedTimes; +} + +int TestVariableController::updatedTimes() const +{ + return m_updatedTimes; +} diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -26,6 +26,7 @@ path.cpp debug.cpp texteditorhelpers.cpp + stack.cpp ) set (KDevPlatformUtil_LIB_UI @@ -83,5 +84,6 @@ projecttestjob.h widgetcolorizer.h path.h + stack.h ${CMAKE_CURRENT_BINARY_DIR}/utilexport.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/util COMPONENT Devel) diff --git a/util/shellutils.cpp b/util/shellutils.cpp --- a/util/shellutils.cpp +++ b/util/shellutils.cpp @@ -72,7 +72,7 @@ bool ensureWritable( const QList &urls ) { - QList notWritable; + QStringList notWritable; foreach (QUrl url, urls) { if (url.isLocalFile()) diff --git a/util/stack.h b/util/stack.h new file mode 100644 --- /dev/null +++ b/util/stack.h @@ -0,0 +1,80 @@ +/* + * Copyright 2015 Kevin Funk + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#ifndef KDEVELOP_STACK_H +#define KDEVELOP_STACK_H + +#include + +namespace KDevelop { + +/** + * @brief Implementation of a stack based on QVarLengthArray + * + * Since stacks are usually short-lived containers, it make sense to optimize their memory usage + * + * Internally using QVarLengthArray. The first @p Prealloc items are placed on the stack. + * If the size of the stack exceeds @p Prealloc, the contents are moved to the heap. + * + * @note Make sure to pass a sensible amount for @p Prealloc; avoiding stack overflows + * + * The default value for Prealloc, 32, + * seems to be a good candidate for between conserving stack space and keeping heap allocations low + * (verified by a few heaptrack runs of duchainify) + * + * @sa QVarLengthArray + */ +template +class Stack : public QVarLengthArray +{ + using Base = QVarLengthArray; + +public: + using Base::QVarLengthArray; + + inline void swap(Stack &other) + { + // prevent Stack<->QVarLengthArray swaps + Base::swap(other); + } + inline void push(const T &t) + { + Base::append(t); + } + + inline T pop() + { + T r = Base::last(); + Base::removeLast(); + return r; + } + inline T& top() { + return Base::last(); + } + inline const T& top() const + { + return Base::last(); + } +}; + +} + +#endif // KDEVELOP_STACK_H diff --git a/util/stack.cpp b/util/stack.cpp new file mode 100644 --- /dev/null +++ b/util/stack.cpp @@ -0,0 +1,22 @@ +/* + * Copyright 2015 Kevin Funk + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + * + */ + +#include "stack.h" diff --git a/vcs/models/vcsfilechangesmodel.h b/vcs/models/vcsfilechangesmodel.h --- a/vcs/models/vcsfilechangesmodel.h +++ b/vcs/models/vcsfilechangesmodel.h @@ -92,6 +92,13 @@ return checkUrls(invisibleRootItem(), urls); } + /** + * Returns the item for the specified url + * */ + QStandardItem* itemForUrl(const QUrl &url) const { + return fileItemForUrl(invisibleRootItem(), url); + } + /** * Changes the check-state of all files to the given state * */