diff --git a/kdevplatform/language/duchain/types/typeregister.cpp b/kdevplatform/language/duchain/types/typeregister.cpp index c107920d9f..44928a3506 100644 --- a/kdevplatform/language/duchain/types/typeregister.cpp +++ b/kdevplatform/language/duchain/types/typeregister.cpp @@ -1,104 +1,103 @@ /* This file is part of KDevelop Copyright 2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 "typeregister.h" #include namespace KDevelop { AbstractType* TypeSystem::create(AbstractTypeData* data) const { Q_ASSERT(data); if (!ensureFactoryLoaded(*data)) { return nullptr; } return m_factories.value(data->typeClassId)->create(data); } void TypeSystem::callDestructor(AbstractTypeData* data) const { Q_ASSERT(data); if (!ensureFactoryLoaded(*data)) { return; } return m_factories.value(data->typeClassId)->callDestructor(data); } uint TypeSystem::dynamicSize(const AbstractTypeData& data) const { if (!ensureFactoryLoaded(data)) { return 0; } return m_factories.value(data.typeClassId)->dynamicSize(data); } uint TypeSystem::dataClassSize(const AbstractTypeData& data) const { Q_ASSERT(m_dataClassSizes.contains(data.typeClassId)); return m_dataClassSizes.value(data.typeClassId); } bool TypeSystem::isFactoryLoaded(const AbstractTypeData& data) const { return m_factories.contains(data.typeClassId); } bool TypeSystem::ensureFactoryLoaded(const AbstractTypeData& data) const { if (!m_factories.contains(data.typeClassId)) { qCWarning(LANGUAGE) << "Factory for this type not loaded:" << data.typeClassId; Q_ASSERT(false); return false; } return true; } void TypeSystem::copy(const AbstractTypeData& from, AbstractTypeData& to, bool constant) const { //Shouldn't try to copy an unknown type ensureFactoryLoaded(from); return m_factories.value(from.typeClassId)->copy(from, to, constant); } TypeSystem& TypeSystem::self() { static TypeSystem system; return system; } void TypeSystem::registerTypeClassInternal(AbstractTypeFactory* repo, uint dataClassSize, uint identity) { - qCDebug(LANGUAGE) << "Registering type class" << identity; Q_ASSERT(repo); Q_ASSERT(!m_factories.contains(identity)); m_factories.insert(identity, repo); Q_ASSERT(!m_dataClassSizes.contains(identity)); m_dataClassSizes.insert(identity, dataClassSize); } void TypeSystem::unregisterTypeClassInternal(uint identity) { qCDebug(LANGUAGE) << "Unregistering type class" << identity; AbstractTypeFactory* repo = m_factories.take(identity); Q_ASSERT(repo); delete repo; int removed = m_dataClassSizes.remove(identity); Q_ASSERT(removed); Q_UNUSED(removed); } } diff --git a/kdevplatform/plugins/contextbrowser/browsemanager.cpp b/kdevplatform/plugins/contextbrowser/browsemanager.cpp index 0fb1a9b04f..bef8d5d0e8 100644 --- a/kdevplatform/plugins/contextbrowser/browsemanager.cpp +++ b/kdevplatform/plugins/contextbrowser/browsemanager.cpp @@ -1,341 +1,346 @@ /* * This file is part of KDevelop * * Copyright 2008 David Nolden * * This program 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "browsemanager.h" #include #include #include #include #include #include #include #include #include #include "contextbrowserview.h" #include #include #include #include #include #include #include #include #include #include #include #include "contextbrowser.h" #include "debug.h" using namespace KDevelop; using namespace KTextEditor; EditorViewWatcher::EditorViewWatcher(QObject* parent) : QObject(parent) { connect(ICore::self()->documentController(), &IDocumentController::textDocumentCreated, this, &EditorViewWatcher::documentCreated); foreach(KDevelop::IDocument* document, ICore::self()->documentController()->openDocuments()) documentCreated(document); } void EditorViewWatcher::documentCreated( KDevelop::IDocument* document ) { KTextEditor::Document* textDocument = document->textDocument(); if(textDocument) { connect(textDocument, &Document::viewCreated, this, &EditorViewWatcher::viewCreated); foreach(KTextEditor::View* view, textDocument->views()) { Q_ASSERT(view->parentWidget()); addViewInternal(view); } } } void EditorViewWatcher::addViewInternal(KTextEditor::View* view) { m_views << view; viewAdded(view); connect(view, &View::destroyed, this, &EditorViewWatcher::viewDestroyed); } void EditorViewWatcher::viewAdded(KTextEditor::View*) { } void EditorViewWatcher::viewDestroyed(QObject* view) { m_views.removeAll(static_cast(view)); } void EditorViewWatcher::viewCreated(KTextEditor::Document* /*doc*/, KTextEditor::View* view) { Q_ASSERT(view->parentWidget()); addViewInternal(view); } QList EditorViewWatcher::allViews() { return m_views; } void BrowseManager::eventuallyStartDelayedBrowsing() { avoidMenuAltFocus(); if(m_browsingByKey == Qt::Key_Alt && m_browsingStartedInView) emit startDelayedBrowsing(m_browsingStartedInView); } BrowseManager::BrowseManager(ContextBrowserPlugin* controller) : QObject(controller) , m_plugin(controller) , m_browsing(false) , m_browsingByKey(0) , m_watcher(this) { m_delayedBrowsingTimer = new QTimer(this); m_delayedBrowsingTimer->setSingleShot(true); connect(m_delayedBrowsingTimer, &QTimer::timeout, this, &BrowseManager::eventuallyStartDelayedBrowsing); foreach(KTextEditor::View* view, m_watcher.allViews()) viewAdded(view); } KTextEditor::View* viewFromWidget(QWidget* widget) { if(!widget) return nullptr; KTextEditor::View* view = qobject_cast(widget); if(view) return view; else return viewFromWidget(widget->parentWidget()); } BrowseManager::JumpLocation BrowseManager::determineJumpLoc(KTextEditor::Cursor textCursor, const QUrl& viewUrl) const { // @todo find out why this is needed, fix the code in kate if (textCursor.column() > 0) { textCursor.setColumn(textCursor.column() - 1); } // Step 1: Look for a special language object(Macro, included header, etc.) foreach (const auto& language, ICore::self()->languageController()->languagesForUrl(viewUrl)) { auto jumpTo = language->specialLanguageObjectJumpCursor(viewUrl, textCursor); if (jumpTo.first.isValid() && jumpTo.second.isValid()) { return {jumpTo.first, jumpTo.second}; } } // Step 2: Look for a declaration/use DUChainReadLocker lock; // Jump to definition by default, unless a definition itself was selected, // in which case jump to declaration. if (auto selectedDeclaration = DUChainUtils::itemUnderCursor(viewUrl, textCursor).declaration) { auto jumpDestination = selectedDeclaration; if (selectedDeclaration->isDefinition()) { // A definition was clicked directly - jump to declaration instead. if (auto declaration = DUChainUtils::declarationForDefinition(selectedDeclaration)) { jumpDestination = declaration; } } else if (selectedDeclaration == DUChainUtils::declarationForDefinition(selectedDeclaration)) { // Clicked the declaration - jump to definition if (auto definition = FunctionDefinition::definition(selectedDeclaration)) { jumpDestination = definition; } } return {jumpDestination->url().toUrl(), jumpDestination->rangeInCurrentRevision().start()}; } return {}; } bool BrowseManager::eventFilter(QObject * watched, QEvent * event) { QWidget* widget = qobject_cast(watched); Q_ASSERT(widget); QKeyEvent* keyEvent = dynamic_cast(event); const int browseKey = Qt::Key_Control; const int magicModifier = Qt::Key_Alt; KTextEditor::View* view = viewFromWidget(widget); //Eventually start key-browsing if(keyEvent && (keyEvent->key() == browseKey || keyEvent->key() == magicModifier) && !m_browsingByKey && keyEvent->type() == QEvent::KeyPress) { m_delayedBrowsingTimer->start(300); // always start the timer, to get consistent behavior regarding the ALT key and the menu activation m_browsingByKey = keyEvent->key(); if(!view) { return false; } if(keyEvent->key() == magicModifier) { if(dynamic_cast(view) && dynamic_cast(view)->isCompletionActive()) { //Completion is active. avoidMenuAltFocus(); m_delayedBrowsingTimer->stop(); }else{ m_browsingStartedInView = view; } } } if (keyEvent && m_browsingByKey && m_browsingStartedInView && keyEvent->type() == QEvent::KeyPress) { if (keyEvent->key() >= Qt::Key_1 && keyEvent->key() <= Qt::Key_9) { // user wants to trigger an action in the code browser const int index = keyEvent->key() - Qt::Key_1; emit invokeAction(index); stopDelayedBrowsing(); return true; } } if(!view) { return false; } QFocusEvent* focusEvent = dynamic_cast(event); //Eventually stop key-browsing if((keyEvent && m_browsingByKey && keyEvent->key() == m_browsingByKey && keyEvent->type() == QEvent::KeyRelease) || (focusEvent && focusEvent->lostFocus()) || event->type() == QEvent::WindowDeactivate) { m_browsingByKey = 0; emit stopDelayedBrowsing(); } QMouseEvent* mouseEvent = dynamic_cast(event); if(mouseEvent) { if (mouseEvent->type() == QEvent::MouseButtonPress && mouseEvent->button() == Qt::XButton1) { m_plugin->historyPrevious(); return true; } if (mouseEvent->type() == QEvent::MouseButtonPress && mouseEvent->button() == Qt::XButton2) { m_plugin->historyNext(); return true; } } if(!m_browsing && !m_browsingByKey) { resetChangedCursor(); return false; } if(mouseEvent) { QPoint coordinatesInView = widget->mapTo(view, mouseEvent->pos()); KTextEditor::Cursor textCursor = view->coordinatesToCursor(coordinatesInView); if (textCursor.isValid()) { JumpLocation jumpTo = determineJumpLoc(textCursor, view->document()->url()); if (jumpTo.isValid()) { if(mouseEvent->button() == Qt::LeftButton) { if(mouseEvent->type() == QEvent::MouseButtonPress) { m_buttonPressPosition = textCursor; // view->setCursorPosition(textCursor); // return false; }else if(mouseEvent->type() == QEvent::MouseButtonRelease && textCursor == m_buttonPressPosition) { ICore::self()->documentController()->openDocument(jumpTo.url, jumpTo.cursor); // event->accept(); // return true; } }else if(mouseEvent->type() == QEvent::MouseMove) { //Make the cursor a "hand" setHandCursor(widget); return false; } } } resetChangedCursor(); } return false; } void BrowseManager::resetChangedCursor() { QMap, QCursor> cursors = m_oldCursors; m_oldCursors.clear(); for(QMap, QCursor>::iterator it = cursors.begin(); it != cursors.end(); ++it) if(it.key()) it.key()->setCursor(QCursor(Qt::IBeamCursor)); } void BrowseManager::setHandCursor(QWidget* widget) { if(m_oldCursors.contains(widget)) return; //Nothing to do m_oldCursors[widget] = widget->cursor(); widget->setCursor(QCursor(Qt::PointingHandCursor)); } -void BrowseManager::avoidMenuAltFocus() { +void BrowseManager::avoidMenuAltFocus() +{ + auto mainWindow = ICore::self()->uiController()->activeMainWindow(); + if (!mainWindow) + return; + // send an invalid key event to the main menu bar. The menu bar will // stop listening when observing another key than ALT between the press // and the release. QKeyEvent event1(QEvent::KeyPress, 0, Qt::NoModifier); - QApplication::sendEvent(ICore::self()->uiController()->activeMainWindow()->menuBar(), &event1); + QApplication::sendEvent(mainWindow->menuBar(), &event1); QKeyEvent event2(QEvent::KeyRelease, 0, Qt::NoModifier); - QApplication::sendEvent(ICore::self()->uiController()->activeMainWindow()->menuBar(), &event2); + QApplication::sendEvent(mainWindow->menuBar(), &event2); } void BrowseManager::applyEventFilter(QWidget* object, bool install) { if(install) object->installEventFilter(this); else object->removeEventFilter(this); foreach(QObject* child, object->children()) if(qobject_cast(child)) applyEventFilter(qobject_cast(child), install); } void BrowseManager::viewAdded(KTextEditor::View* view) { applyEventFilter(view, true); //We need to listen for cursorPositionChanged, to clear the shift-detector. The problem: Kate listens for the arrow-keys using shortcuts, //so those keys are not passed to the event-filter // can't use new signal/slot syntax here, these signals are only defined in KateView // TODO: should we really depend on kate internals here? connect(view, SIGNAL(navigateLeft()), m_plugin, SLOT(navigateLeft())); connect(view, SIGNAL(navigateRight()), m_plugin, SLOT(navigateRight())); connect(view, SIGNAL(navigateUp()), m_plugin, SLOT(navigateUp())); connect(view, SIGNAL(navigateDown()), m_plugin, SLOT(navigateDown())); connect(view, SIGNAL(navigateAccept()), m_plugin, SLOT(navigateAccept())); connect(view, SIGNAL(navigateBack()), m_plugin, SLOT(navigateBack())); } void Watcher::viewAdded(KTextEditor::View* view) { m_manager->viewAdded(view); } void BrowseManager::setBrowsing(bool enabled) { if(enabled == m_browsing) return; m_browsing = enabled; //This collects all the views if(enabled) { qCDebug(PLUGIN_CONTEXTBROWSER) << "Enabled browsing-mode"; }else{ qCDebug(PLUGIN_CONTEXTBROWSER) << "Disabled browsing-mode"; resetChangedCursor(); } } Watcher::Watcher(BrowseManager* manager) : EditorViewWatcher(manager), m_manager(manager) { foreach(KTextEditor::View* view, allViews()) m_manager->applyEventFilter(view, true); } diff --git a/kdevplatform/plugins/subversion/kdevsvncpp/client_ls.cpp b/kdevplatform/plugins/subversion/kdevsvncpp/client_ls.cpp index c9915c4b63..a3f56b04f0 100644 --- a/kdevplatform/plugins/subversion/kdevsvncpp/client_ls.cpp +++ b/kdevplatform/plugins/subversion/kdevsvncpp/client_ls.cpp @@ -1,166 +1,166 @@ /* * ==================================================================== * Copyright (c) 2002-2009 The RapidSvn Group. All rights reserved. * * 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 3 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 (in the file GPL.txt. * If not, see . * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://rapidsvn.tigris.org/. * ==================================================================== */ #if defined( _MSC_VER) && _MSC_VER <= 1200 #pragma warning( disable: 4786 )// debug symbol truncated #endif // subversion api #include "svn_client.h" #include "svn_path.h" #include "svn_sorts.h" #include "svn_version.h" //#include "svn_utf.h" // svncpp #include "kdevsvncpp/client.hpp" #include "kdevsvncpp/dirent.hpp" #include "kdevsvncpp/exception.hpp" #if SVN_VER_MAJOR == 1 && SVN_VER_MINOR < 8 static int compare_items_as_paths(const svn_sort__item_t *a, const svn_sort__item_t *b) { return svn_path_compare_paths((const char *)a->key, (const char *)b->key); } namespace svn { DirEntries Client::list(const char * pathOrUrl, svn_opt_revision_t * revision, - bool recurse) throw(ClientException) + bool recurse) { Pool pool; apr_hash_t * hash; svn_error_t * error = svn_client_ls(&hash, pathOrUrl, revision, recurse, *m_context, pool); if (error != 0) throw ClientException(error); apr_array_header_t * array = svn_sort__hash( hash, compare_items_as_paths, pool); DirEntries entries; for (int i = 0; i < array->nelts; ++i) { const char *entryname; svn_dirent_t *dirent; svn_sort__item_t *item; item = &APR_ARRAY_IDX(array, i, svn_sort__item_t); entryname = static_cast(item->key); dirent = static_cast (apr_hash_get(hash, entryname, item->klen)); entries.push_back(DirEntry(entryname, dirent)); } return entries; } } #else #include static svn_error_t* store_entry( void *baton, const char *path, const svn_dirent_t *dirent, const svn_lock_t *, const char *abs_path, const char *, const char *, apr_pool_t *scratch_pool) { svn::DirEntries *entries = reinterpret_cast(baton); if (path[0] == '\0') { if (dirent->kind == svn_node_file) { // for compatibility with svn_client_ls behaviour, listing a file // stores that file name entries->push_back(svn::DirEntry(svn_path_basename(abs_path, scratch_pool), dirent)); } } else { entries->push_back(svn::DirEntry(path, dirent)); } return SVN_NO_ERROR; } static bool sort_by_path(svn::DirEntry const& a, svn::DirEntry const& b) { return svn_path_compare_paths(a.name(), b.name()) < 0; } namespace svn { DirEntries Client::list(const char * pathOrUrl, svn_opt_revision_t * revision, bool recurse) { Pool pool; DirEntries entries; svn_error_t * error = svn_client_list3(pathOrUrl, revision, revision, SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse), SVN_DIRENT_ALL, FALSE, // fetch locks FALSE, // include externals &store_entry, &entries, *m_context, pool); if (error != SVN_NO_ERROR) throw ClientException(error); std::sort(entries.begin(), entries.end(), &sort_by_path); return entries; } } #endif /* ----------------------------------------------------------------- * local variables: * eval: (load-file "../../rapidsvn-dev.el") * end: */